Move SafeExec logic to internal safeexec package

Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
Evan Lezar 2025-02-28 14:38:02 +02:00
parent 715e09fbd4
commit 4088430fc1
No known key found for this signature in database
4 changed files with 49 additions and 8 deletions

View File

@ -27,6 +27,7 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
safeexec "github.com/NVIDIA/nvidia-container-toolkit/internal/safe-exec"
)
const (
@ -39,6 +40,7 @@ const (
)
type command struct {
safeexec.Execer
logger logger.Interface
}
@ -52,6 +54,7 @@ type options struct {
func NewCommand(logger logger.Interface) *cli.Command {
c := command{
logger: logger,
Execer: safeexec.New(logger),
}
return c.build()
}
@ -141,7 +144,7 @@ func (m command) run(c *cli.Context, cfg *options) error {
args = append(args, folders...)
}
return m.SafeExec(ldconfigPath, args, nil)
return m.Exec(ldconfigPath, args, nil)
}
// resolveLDConfigPath determines the LDConfig path to use for the system.

View File

@ -0,0 +1,37 @@
/**
# 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.
# 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 safeexec
import "github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
// An Execer implements an Exec function.
type Execer interface {
Exec(string, []string, []string) error
}
// A safeExecer is used to Exec an application from a memfd to prevent possible
// tampering.
type safeExecer struct {
logger logger.Interface
}
// New creates a safe Execer with the specified logger.
func New(logger logger.Interface) Execer {
return &safeExecer{
logger: logger,
}
}

View File

@ -14,7 +14,7 @@
# limitations under the License.
**/
package ldcache
package safeexec
import (
"fmt"
@ -25,11 +25,11 @@ import (
"github.com/opencontainers/runc/libcontainer/dmz"
)
// SafeExec attempts to clone the specified binary (as an memfd, for example) before executing it.
func (m command) SafeExec(path string, args []string, envv []string) error {
// Exec attempts to clone the specified binary (as an memfd, for example) before executing it.
func (s *safeExecer) Exec(path string, args []string, envv []string) error {
safeExe, err := cloneBinary(path)
if err != nil {
m.logger.Warningf("Failed to clone binary %q: %v; falling back to Exec", path, err)
s.logger.Warningf("Failed to clone binary %q: %v; falling back to Exec", path, err)
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
return syscall.Exec(path, args, envv)
}

View File

@ -17,13 +17,14 @@
# limitations under the License.
**/
package ldcache
package safeexec
import "syscall"
// SafeExec is not implemented on non-linux systems and forwards directly to the
// Exec is not implemented on non-linux systems and forwards directly to the
// Exec syscall.
func (m *command) SafeExec(path string, args []string, envv []string) error {
func (s *safeExecer) Exec(path string, args []string, envv []string) error {
s.logger.Warningf("Cloning binary not implemented for binary %q; falling back to Exec", path)
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
return syscall.Exec(path, args, envv)
}