Skip to content

Commit 52b9631

Browse files
committed
Use libcontainer execseal to run ldconfig
This change copies ldconfig into a memfd before executing it from the createContainer hook. Signed-off-by: Evan Lezar <[email protected]>
1 parent 9429fba commit 52b9631

34 files changed

+3939
-6
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
**/
16+
17+
package ldcache
18+
19+
import (
20+
"fmt"
21+
"os"
22+
"strconv"
23+
"syscall"
24+
25+
"github.com/opencontainers/runc/libcontainer/dmz"
26+
)
27+
28+
// SafeExec attempts to clone the specified binary (as an memfd, for example) before executing it.
29+
func (m command) SafeExec(path string, args []string, envv []string) error {
30+
safeExe, err := cloneBinary(path)
31+
if err != nil {
32+
m.logger.Warningf("Failed to clone binary %q: %v; falling back to Exec", path, err)
33+
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
34+
return syscall.Exec(path, args, envv)
35+
}
36+
defer safeExe.Close()
37+
38+
exePath := "/proc/self/fd/" + strconv.Itoa(int(safeExe.Fd()))
39+
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
40+
return syscall.Exec(exePath, args, envv)
41+
}
42+
43+
func cloneBinary(path string) (*os.File, error) {
44+
exe, err := os.Open(path)
45+
if err != nil {
46+
return nil, fmt.Errorf("opening current binary: %w", err)
47+
}
48+
defer exe.Close()
49+
50+
stat, err := exe.Stat()
51+
if err != nil {
52+
return nil, fmt.Errorf("checking %v size: %w", path, err)
53+
}
54+
size := stat.Size()
55+
56+
return dmz.CloneBinary(exe, size, path, os.TempDir())
57+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//go:build !linux
2+
// +build !linux
3+
4+
/**
5+
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
**/
19+
20+
package ldcache
21+
22+
import "syscall"
23+
24+
// SafeExec is not implemented on non-linux systems and forwards directly to the
25+
// Exec syscall.
26+
func (m *command) SafeExec(path string, args []string, envv []string) error {
27+
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
28+
return syscall.Exec(path, args, envv)
29+
}

cmd/nvidia-cdi-hook/update-ldcache/update-ldcache.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"os"
2323
"path/filepath"
2424
"strings"
25-
"syscall"
2625

2726
"github.com/urfave/cli/v2"
2827

@@ -143,8 +142,7 @@ func (m command) run(c *cli.Context, cfg *options) error {
143142
// be configured to use a different config file by default.
144143
args = append(args, "-f", "/etc/ld.so.conf")
145144

146-
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
147-
return syscall.Exec(ldconfigPath, args, nil)
145+
return m.SafeExec(ldconfigPath, args, nil)
148146
}
149147

150148
// resolveLDConfigPath determines the LDConfig path to use for the system.

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/NVIDIA/go-nvlib v0.7.1
77
github.com/NVIDIA/go-nvml v0.12.4-1
88
github.com/moby/sys/symlink v0.3.0
9+
github.com/opencontainers/runc v1.2.5
910
github.com/opencontainers/runtime-spec v1.2.0
1011
github.com/pelletier/go-toml v1.9.5
1112
github.com/sirupsen/logrus v1.9.3
@@ -19,13 +20,13 @@ require (
1920

2021
require (
2122
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
23+
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
2224
github.com/davecgh/go-spew v1.1.1 // indirect
2325
github.com/fsnotify/fsnotify v1.7.0 // indirect
2426
github.com/google/uuid v1.6.0 // indirect
2527
github.com/hashicorp/errwrap v1.1.0 // indirect
2628
github.com/kr/pretty v0.3.1 // indirect
2729
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect
28-
github.com/opencontainers/selinux v1.11.0 // indirect
2930
github.com/pmezard/go-difflib v1.0.0 // indirect
3031
github.com/russross/blackfriday/v2 v2.1.0 // indirect
3132
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y
77
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
88
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
99
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
10+
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
11+
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
1012
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1113
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1214
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -31,6 +33,8 @@ github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34
3133
github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU=
3234
github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0=
3335
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
36+
github.com/opencontainers/runc v1.2.5 h1:8KAkq3Wrem8bApgOHyhRI/8IeLXIfmZ6Qaw6DNSLnA4=
37+
github.com/opencontainers/runc v1.2.5/go.mod h1:dOQeFo29xZKBNeRBI0B19mJtfHv68YgCTh1X+YphA+4=
3438
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
3539
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
3640
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=

0 commit comments

Comments
 (0)