From c27dd75732d3e04964962dc93c46d3e55978d0b9 Mon Sep 17 00:00:00 2001 From: Nate Bracy Date: Thu, 10 Jul 2025 23:35:54 -0400 Subject: [PATCH 1/6] feat: introduce shell metacharacter escaping for exec Signed-off-by: Nate Bracy --- cmd/nvidia-container-runtime-hook/main.go | 5 +- cmd/nvidia-container-runtime/main_test.go | 20 +++---- .../container/container.go | 5 +- internal/ldconfig/safe-exec_linux.go | 8 +-- internal/ldconfig/safe-exec_other.go | 9 ++- internal/nvsandboxutils/zz_generated.api.go | 12 ++-- internal/oci/runtime_syscall_exec.go | 32 ++++++++++- internal/oci/runtime_syscall_exec_test.go | 55 +++++++++++++++++++ 8 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 internal/oci/runtime_syscall_exec_test.go diff --git a/cmd/nvidia-container-runtime-hook/main.go b/cmd/nvidia-container-runtime-hook/main.go index 7cdb0ad83..c6529c821 100644 --- a/cmd/nvidia-container-runtime-hook/main.go +++ b/cmd/nvidia-container-runtime-hook/main.go @@ -17,6 +17,7 @@ import ( "github.com/NVIDIA/nvidia-container-toolkit/internal/info" "github.com/NVIDIA/nvidia-container-toolkit/internal/logger" "github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" + "github.com/NVIDIA/nvidia-container-toolkit/internal/oci" ) var ( @@ -150,8 +151,8 @@ func doPrestart() { args = append(args, rootfs) env := append(os.Environ(), cli.Environment...) - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection? - err = syscall.Exec(args[0], args, env) + args = oci.Escape(args) + err = syscall.Exec(args[0], args, env) //nolint:gosec log.Panicln("exec failed:", err) } diff --git a/cmd/nvidia-container-runtime/main_test.go b/cmd/nvidia-container-runtime/main_test.go index ab5ddee73..ba706c3f8 100644 --- a/cmd/nvidia-container-runtime/main_test.go +++ b/cmd/nvidia-container-runtime/main_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/NVIDIA/nvidia-container-toolkit/internal/modifier" + "github.com/NVIDIA/nvidia-container-toolkit/internal/oci" "github.com/NVIDIA/nvidia-container-toolkit/internal/test" ) @@ -87,8 +88,7 @@ func TestBadInput(t *testing.T) { t.Fatal(err) } - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - cmdCreate := exec.Command(nvidiaRuntime, "create", "--bundle") + cmdCreate := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"create", "--bundle"})...) //nolint:gosec t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) err = cmdCreate.Run() require.Error(t, err, "runtime should return an error") @@ -105,8 +105,8 @@ func TestGoodInput(t *testing.T) { t.Fatalf("error generating runtime spec: %v", err) } - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - cmdRun := exec.Command(nvidiaRuntime, "run", "--bundle", cfg.bundlePath(), "testcontainer") + //nolint:gosec + cmdRun := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"run", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdRun.Args, " ")) output, err := cmdRun.CombinedOutput() require.NoErrorf(t, err, "runtime should not return an error", "output=%v", string(output)) @@ -116,8 +116,8 @@ func TestGoodInput(t *testing.T) { require.NoError(t, err, "should be no errors when reading and parsing spec from config.json") require.Empty(t, spec.Hooks, "there should be no hooks in config.json") - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - cmdCreate := exec.Command(nvidiaRuntime, "create", "--bundle", cfg.bundlePath(), "testcontainer") + //nolint:gosec + cmdCreate := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) err = cmdCreate.Run() require.NoError(t, err, "runtime should not return an error") @@ -161,8 +161,8 @@ func TestDuplicateHook(t *testing.T) { } // Test how runtime handles already existing prestart hook in config.json - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - cmdCreate := exec.Command(nvidiaRuntime, "create", "--bundle", cfg.bundlePath(), "testcontainer") + //nolint:gosec + cmdCreate := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) output, err := cmdCreate.CombinedOutput() require.NoErrorf(t, err, "runtime should not return an error", "output=%v", string(output)) @@ -230,8 +230,8 @@ func (c testConfig) generateNewRuntimeSpec() error { return err } - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - cmd := exec.Command("cp", c.unmodifiedSpecFile(), c.specFilePath()) + //nolint:gosec + cmd := exec.Command(oci.Escape1("cp"), oci.Escape([]string{c.unmodifiedSpecFile(), c.specFilePath()})...) err = cmd.Run() if err != nil { return err diff --git a/cmd/nvidia-ctk-installer/container/container.go b/cmd/nvidia-ctk-installer/container/container.go index 0583e051a..08290b0dc 100644 --- a/cmd/nvidia-ctk-installer/container/container.go +++ b/cmd/nvidia-ctk-installer/container/container.go @@ -24,6 +24,7 @@ import ( "github.com/sirupsen/logrus" "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/operator" + "github.com/NVIDIA/nvidia-container-toolkit/internal/oci" "github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine" ) @@ -147,8 +148,8 @@ func (o Options) SystemdRestart(service string) error { logrus.Infof("Restarting %v%v using systemd: %v", service, msg, args) - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - cmd := exec.Command(args[0], args[1:]...) + args = oci.Escape(args) + cmd := exec.Command(args[0], args[1:]...) //nolint:gosec cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() diff --git a/internal/ldconfig/safe-exec_linux.go b/internal/ldconfig/safe-exec_linux.go index 09b6cc22c..a430e122c 100644 --- a/internal/ldconfig/safe-exec_linux.go +++ b/internal/ldconfig/safe-exec_linux.go @@ -25,20 +25,20 @@ import ( "syscall" "github.com/opencontainers/runc/libcontainer/exeseal" + + "github.com/NVIDIA/nvidia-container-toolkit/internal/oci" ) // SafeExec attempts to clone the specified binary (as an memfd, for example) before executing it. func SafeExec(path string, args []string, envv []string) error { safeExe, err := cloneBinary(path) if err != nil { - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - return syscall.Exec(path, args, envv) + return syscall.Exec(path, oci.Escape(args), envv) //nolint:gosec } defer safeExe.Close() exePath := "/proc/self/fd/" + strconv.Itoa(int(safeExe.Fd())) - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - return syscall.Exec(exePath, args, envv) + return syscall.Exec(exePath, oci.Escape(args), envv) //nolint:gosec } func cloneBinary(path string) (*os.File, error) { diff --git a/internal/ldconfig/safe-exec_other.go b/internal/ldconfig/safe-exec_other.go index 3d0176458..245c1e207 100644 --- a/internal/ldconfig/safe-exec_other.go +++ b/internal/ldconfig/safe-exec_other.go @@ -18,11 +18,14 @@ package ldconfig -import "syscall" +import ( + "syscall" + + "github.com/NVIDIA/nvidia-container-toolkit/internal/oci" +) // SafeExec is not implemented on non-linux systems and forwards directly to the // Exec syscall. func SafeExec(path string, args []string, envv []string) error { - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - return syscall.Exec(path, args, envv) + return syscall.Exec(path, oci.Escape(args), envv) //nolint:gosec } diff --git a/internal/nvsandboxutils/zz_generated.api.go b/internal/nvsandboxutils/zz_generated.api.go index 631b2b05a..1f444a39c 100644 --- a/internal/nvsandboxutils/zz_generated.api.go +++ b/internal/nvsandboxutils/zz_generated.api.go @@ -20,13 +20,13 @@ package nvsandboxutils // The variables below represent package level methods from the library type. var ( - ErrorString = libnvsandboxutils.ErrorString + ErrorString = libnvsandboxutils.ErrorString GetDriverVersion = libnvsandboxutils.GetDriverVersion - GetFileContent = libnvsandboxutils.GetFileContent - GetGpuResource = libnvsandboxutils.GetGpuResource - Init = libnvsandboxutils.Init - LookupSymbol = libnvsandboxutils.LookupSymbol - Shutdown = libnvsandboxutils.Shutdown + GetFileContent = libnvsandboxutils.GetFileContent + GetGpuResource = libnvsandboxutils.GetGpuResource + Init = libnvsandboxutils.Init + LookupSymbol = libnvsandboxutils.LookupSymbol + Shutdown = libnvsandboxutils.Shutdown ) // Interface represents the interface for the library type. diff --git a/internal/oci/runtime_syscall_exec.go b/internal/oci/runtime_syscall_exec.go index 349edf86e..216dfc050 100644 --- a/internal/oci/runtime_syscall_exec.go +++ b/internal/oci/runtime_syscall_exec.go @@ -19,16 +19,25 @@ package oci import ( "fmt" "os" + "regexp" + "strings" "syscall" ) +// shellMetachars represents a set of shell metacharacters that are commonly +// used for shell scripting and may lead to security vulnerabilities if not +// properly handled. +// +// These metacharacters include: | & ; ( ) < > \t \n $ \ ` +const shellMetachars = "|&;()<> \t\n$\\`" + type syscallExec struct{} var _ Runtime = (*syscallExec)(nil) func (r syscallExec) Exec(args []string) error { - //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection - err := syscall.Exec(args[0], args, os.Environ()) + args = Escape(args) + err := syscall.Exec(args[0], args, os.Environ()) //nolint:gosec if err != nil { return fmt.Errorf("could not exec '%v': %v", args[0], err) } @@ -41,3 +50,22 @@ func (r syscallExec) Exec(args []string) error { func (r syscallExec) String() string { return "exec" } + +// Escape1 escapes shell metacharacters in a single command-line argument. +func Escape1(arg string) string { + if strings.ContainsAny(arg, shellMetachars) { + e := regexp.MustCompile(`([|&;()<> \t\n$\\`+"`"+`])`).ReplaceAllString(arg, `\$1`) + return fmt.Sprintf(`"%s"`, e) + } + return arg +} + +// Escape escapes shell metacharacters in a slice of command-line arguments +// and returns a new slice containing the escaped arguments. +func Escape(args []string) []string { + escaped := make([]string, len(args)) + for i := range args { + escaped[i] = Escape1(args[i]) + } + return escaped +} diff --git a/internal/oci/runtime_syscall_exec_test.go b/internal/oci/runtime_syscall_exec_test.go new file mode 100644 index 000000000..112bc21e4 --- /dev/null +++ b/internal/oci/runtime_syscall_exec_test.go @@ -0,0 +1,55 @@ +/* +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + +package oci + +import ( + "reflect" + "testing" +) + +func TestEscape(t *testing.T) { + testCases := []struct { + name string + input []string + expected []string + }{ + { + name: "Empty Slice", + input: []string{}, + expected: []string{}, + }, + { + name: "Slice with no Metacharacters", + input: []string{"ls", "-l", "/home/user"}, + expected: []string{"ls", "-l", "/home/user"}, + }, + { + name: "Slice with some Metacharacters", + input: []string{"echo", "Hello World", "and", "goodbye | cat"}, + expected: []string{"echo", `"Hello\ World"`, "and", `"goodbye\ \|\ cat"`}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := Escape(tc.input) + if !reflect.DeepEqual(actual, tc.expected) { + t.Errorf("Escape(%q) = %q; want %q", tc.input, actual, tc.expected) + } + }) + } +} From 9d08eac718fdf4d1f67b4c04e9cd2c1111987967 Mon Sep 17 00:00:00 2001 From: Nate Bracy Date: Thu, 10 Jul 2025 23:45:18 -0400 Subject: [PATCH 2/6] [no-relnote] nit: move metacharRegex to package-level Signed-off-by: Nate Bracy --- internal/oci/runtime_syscall_exec.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/oci/runtime_syscall_exec.go b/internal/oci/runtime_syscall_exec.go index 216dfc050..cce3e0cf9 100644 --- a/internal/oci/runtime_syscall_exec.go +++ b/internal/oci/runtime_syscall_exec.go @@ -31,6 +31,9 @@ import ( // These metacharacters include: | & ; ( ) < > \t \n $ \ ` const shellMetachars = "|&;()<> \t\n$\\`" +// metacharRegex matches any shell metacharcter. +var metacharRegex = regexp.MustCompile(`([` + regexp.QuoteMeta(shellMetachars) + `])`) + type syscallExec struct{} var _ Runtime = (*syscallExec)(nil) @@ -54,7 +57,7 @@ func (r syscallExec) String() string { // Escape1 escapes shell metacharacters in a single command-line argument. func Escape1(arg string) string { if strings.ContainsAny(arg, shellMetachars) { - e := regexp.MustCompile(`([|&;()<> \t\n$\\`+"`"+`])`).ReplaceAllString(arg, `\$1`) + e := metacharRegex.ReplaceAllString(arg, `\$1`) return fmt.Sprintf(`"%s"`, e) } return arg From 8dcdf8328fae7079612d090852c51a4e35962b74 Mon Sep 17 00:00:00 2001 From: Nate Bracy Date: Tue, 15 Jul 2025 14:07:10 -0400 Subject: [PATCH 3/6] [no-relnote] nit: address code review comments Signed-off-by: Nate Bracy --- internal/oci/runtime_syscall_exec.go | 11 +++++------ internal/oci/runtime_syscall_exec_test.go | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/internal/oci/runtime_syscall_exec.go b/internal/oci/runtime_syscall_exec.go index cce3e0cf9..a5feb2c0c 100644 --- a/internal/oci/runtime_syscall_exec.go +++ b/internal/oci/runtime_syscall_exec.go @@ -29,7 +29,7 @@ import ( // properly handled. // // These metacharacters include: | & ; ( ) < > \t \n $ \ ` -const shellMetachars = "|&;()<> \t\n$\\`" +const shellMetachars = "|&;()<> \t\n$\\`'\"" // metacharRegex matches any shell metacharcter. var metacharRegex = regexp.MustCompile(`([` + regexp.QuoteMeta(shellMetachars) + `])`) @@ -54,11 +54,10 @@ func (r syscallExec) String() string { return "exec" } -// Escape1 escapes shell metacharacters in a single command-line argument. -func Escape1(arg string) string { +// escapeArg escapes shell metacharacters in a single command-line argument. +func escapeArg(arg string) string { if strings.ContainsAny(arg, shellMetachars) { - e := metacharRegex.ReplaceAllString(arg, `\$1`) - return fmt.Sprintf(`"%s"`, e) + return metacharRegex.ReplaceAllString(arg, `\$1`) } return arg } @@ -68,7 +67,7 @@ func Escape1(arg string) string { func Escape(args []string) []string { escaped := make([]string, len(args)) for i := range args { - escaped[i] = Escape1(args[i]) + escaped[i] = escapeArg(args[i]) } return escaped } diff --git a/internal/oci/runtime_syscall_exec_test.go b/internal/oci/runtime_syscall_exec_test.go index 112bc21e4..aa0b9a917 100644 --- a/internal/oci/runtime_syscall_exec_test.go +++ b/internal/oci/runtime_syscall_exec_test.go @@ -1,5 +1,5 @@ /* -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From 8c93cd865e6f21af3ba7aa522188c0e35cba426b Mon Sep 17 00:00:00 2001 From: Nate Bracy Date: Tue, 15 Jul 2025 16:14:08 -0400 Subject: [PATCH 4/6] [no-relnote] nit: revert EscapeArg to global per usage outside of package Signed-off-by: Nate Bracy --- internal/oci/runtime_syscall_exec.go | 6 +++--- internal/oci/runtime_syscall_exec_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/oci/runtime_syscall_exec.go b/internal/oci/runtime_syscall_exec.go index a5feb2c0c..64e049da0 100644 --- a/internal/oci/runtime_syscall_exec.go +++ b/internal/oci/runtime_syscall_exec.go @@ -54,8 +54,8 @@ func (r syscallExec) String() string { return "exec" } -// escapeArg escapes shell metacharacters in a single command-line argument. -func escapeArg(arg string) string { +// EscapeArg escapes shell metacharacters in a single command-line argument. +func EscapeArg(arg string) string { if strings.ContainsAny(arg, shellMetachars) { return metacharRegex.ReplaceAllString(arg, `\$1`) } @@ -67,7 +67,7 @@ func escapeArg(arg string) string { func Escape(args []string) []string { escaped := make([]string, len(args)) for i := range args { - escaped[i] = escapeArg(args[i]) + escaped[i] = EscapeArg(args[i]) } return escaped } diff --git a/internal/oci/runtime_syscall_exec_test.go b/internal/oci/runtime_syscall_exec_test.go index aa0b9a917..fa83e5af9 100644 --- a/internal/oci/runtime_syscall_exec_test.go +++ b/internal/oci/runtime_syscall_exec_test.go @@ -40,7 +40,7 @@ func TestEscape(t *testing.T) { { name: "Slice with some Metacharacters", input: []string{"echo", "Hello World", "and", "goodbye | cat"}, - expected: []string{"echo", `"Hello\ World"`, "and", `"goodbye\ \|\ cat"`}, + expected: []string{"echo", `Hello\ World`, `and`, `goodbye\ \|\ cat`}, }, } From 9ab22e5d616d743d67301f1e415de3ce2edbf501 Mon Sep 17 00:00:00 2001 From: Nate Bracy Date: Tue, 15 Jul 2025 16:14:31 -0400 Subject: [PATCH 5/6] [no-relnote] nit: update tests Signed-off-by: Nate Bracy --- cmd/nvidia-container-runtime/main_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/nvidia-container-runtime/main_test.go b/cmd/nvidia-container-runtime/main_test.go index ba706c3f8..206d1608a 100644 --- a/cmd/nvidia-container-runtime/main_test.go +++ b/cmd/nvidia-container-runtime/main_test.go @@ -88,7 +88,7 @@ func TestBadInput(t *testing.T) { t.Fatal(err) } - cmdCreate := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"create", "--bundle"})...) //nolint:gosec + cmdCreate := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"create", "--bundle"})...) //nolint:gosec t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) err = cmdCreate.Run() require.Error(t, err, "runtime should return an error") @@ -106,7 +106,7 @@ func TestGoodInput(t *testing.T) { } //nolint:gosec - cmdRun := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"run", "--bundle", cfg.bundlePath(), "testcontainer"})...) + cmdRun := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"run", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdRun.Args, " ")) output, err := cmdRun.CombinedOutput() require.NoErrorf(t, err, "runtime should not return an error", "output=%v", string(output)) @@ -117,7 +117,7 @@ func TestGoodInput(t *testing.T) { require.Empty(t, spec.Hooks, "there should be no hooks in config.json") //nolint:gosec - cmdCreate := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) + cmdCreate := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) err = cmdCreate.Run() require.NoError(t, err, "runtime should not return an error") @@ -162,7 +162,7 @@ func TestDuplicateHook(t *testing.T) { // Test how runtime handles already existing prestart hook in config.json //nolint:gosec - cmdCreate := exec.Command(oci.Escape1(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) + cmdCreate := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) output, err := cmdCreate.CombinedOutput() require.NoErrorf(t, err, "runtime should not return an error", "output=%v", string(output)) @@ -231,7 +231,7 @@ func (c testConfig) generateNewRuntimeSpec() error { } //nolint:gosec - cmd := exec.Command(oci.Escape1("cp"), oci.Escape([]string{c.unmodifiedSpecFile(), c.specFilePath()})...) + cmd := exec.Command(oci.EscapeArg("cp"), oci.Escape([]string{c.unmodifiedSpecFile(), c.specFilePath()})...) err = cmd.Run() if err != nil { return err From ff28fcc9cf6cc44ea523ef208ecd2b7b45dd9808 Mon Sep 17 00:00:00 2001 From: Nate Bracy Date: Thu, 17 Jul 2025 19:08:03 -0400 Subject: [PATCH 6/6] [no-relnote] nit: revert oci.EscapeArg -> oci.escapeArg Signed-off-by: Nate Bracy --- cmd/nvidia-container-runtime/main_test.go | 10 +++++----- internal/nvsandboxutils/cgo_helpers_static.go | 2 +- internal/oci/runtime_syscall_exec.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/nvidia-container-runtime/main_test.go b/cmd/nvidia-container-runtime/main_test.go index 206d1608a..3a93590ee 100644 --- a/cmd/nvidia-container-runtime/main_test.go +++ b/cmd/nvidia-container-runtime/main_test.go @@ -88,7 +88,7 @@ func TestBadInput(t *testing.T) { t.Fatal(err) } - cmdCreate := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"create", "--bundle"})...) //nolint:gosec + cmdCreate := exec.Command(oci.Escape([]string{nvidiaRuntime})[0], oci.Escape([]string{"create", "--bundle"})...) //nolint:gosec t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) err = cmdCreate.Run() require.Error(t, err, "runtime should return an error") @@ -106,7 +106,7 @@ func TestGoodInput(t *testing.T) { } //nolint:gosec - cmdRun := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"run", "--bundle", cfg.bundlePath(), "testcontainer"})...) + cmdRun := exec.Command(oci.Escape([]string{nvidiaRuntime})[0], oci.Escape([]string{"run", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdRun.Args, " ")) output, err := cmdRun.CombinedOutput() require.NoErrorf(t, err, "runtime should not return an error", "output=%v", string(output)) @@ -117,7 +117,7 @@ func TestGoodInput(t *testing.T) { require.Empty(t, spec.Hooks, "there should be no hooks in config.json") //nolint:gosec - cmdCreate := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) + cmdCreate := exec.Command(oci.Escape([]string{nvidiaRuntime})[0], oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) err = cmdCreate.Run() require.NoError(t, err, "runtime should not return an error") @@ -162,7 +162,7 @@ func TestDuplicateHook(t *testing.T) { // Test how runtime handles already existing prestart hook in config.json //nolint:gosec - cmdCreate := exec.Command(oci.EscapeArg(nvidiaRuntime), oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) + cmdCreate := exec.Command(oci.Escape([]string{nvidiaRuntime})[0], oci.Escape([]string{"create", "--bundle", cfg.bundlePath(), "testcontainer"})...) t.Logf("executing: %s\n", strings.Join(cmdCreate.Args, " ")) output, err := cmdCreate.CombinedOutput() require.NoErrorf(t, err, "runtime should not return an error", "output=%v", string(output)) @@ -231,7 +231,7 @@ func (c testConfig) generateNewRuntimeSpec() error { } //nolint:gosec - cmd := exec.Command(oci.EscapeArg("cp"), oci.Escape([]string{c.unmodifiedSpecFile(), c.specFilePath()})...) + cmd := exec.Command("cp", oci.Escape([]string{c.unmodifiedSpecFile(), c.specFilePath()})...) err = cmd.Run() if err != nil { return err diff --git a/internal/nvsandboxutils/cgo_helpers_static.go b/internal/nvsandboxutils/cgo_helpers_static.go index 5924d6227..34e7d2e17 100644 --- a/internal/nvsandboxutils/cgo_helpers_static.go +++ b/internal/nvsandboxutils/cgo_helpers_static.go @@ -19,7 +19,7 @@ package nvsandboxutils var cgoAllocsUnknown = new(struct{}) func clen(n []byte) int { - for i := 0; i < len(n); i++ { + for i := range n { if n[i] == 0 { return i } diff --git a/internal/oci/runtime_syscall_exec.go b/internal/oci/runtime_syscall_exec.go index 64e049da0..a5feb2c0c 100644 --- a/internal/oci/runtime_syscall_exec.go +++ b/internal/oci/runtime_syscall_exec.go @@ -54,8 +54,8 @@ func (r syscallExec) String() string { return "exec" } -// EscapeArg escapes shell metacharacters in a single command-line argument. -func EscapeArg(arg string) string { +// escapeArg escapes shell metacharacters in a single command-line argument. +func escapeArg(arg string) string { if strings.ContainsAny(arg, shellMetachars) { return metacharRegex.ReplaceAllString(arg, `\$1`) } @@ -67,7 +67,7 @@ func EscapeArg(arg string) string { func Escape(args []string) []string { escaped := make([]string, len(args)) for i := range args { - escaped[i] = EscapeArg(args[i]) + escaped[i] = escapeArg(args[i]) } return escaped }