Skip to content

Commit 5bdf14b

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 b598826 commit 5bdf14b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+4962
-46
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: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
11
module github.com/NVIDIA/nvidia-container-toolkit
22

3-
go 1.20
3+
go 1.22
44

55
require (
66
github.com/NVIDIA/go-nvlib v0.6.1
77
github.com/NVIDIA/go-nvml v0.12.4-1
88
github.com/fsnotify/fsnotify v1.7.0
99
github.com/moby/sys/symlink v0.3.0
10+
github.com/opencontainers/runc v1.2.5
1011
github.com/opencontainers/runtime-spec v1.2.0
1112
github.com/pelletier/go-toml v1.9.5
1213
github.com/sirupsen/logrus v1.9.3
1314
github.com/stretchr/testify v1.9.0
1415
github.com/urfave/cli/v2 v2.27.5
1516
golang.org/x/mod v0.20.0
16-
golang.org/x/sys v0.26.0
17+
golang.org/x/sys v0.28.0
1718
tags.cncf.io/container-device-interface v0.8.0
1819
tags.cncf.io/container-device-interface/specs-go v0.8.0
1920
)
2021

2122
require (
2223
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
24+
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
2325
github.com/davecgh/go-spew v1.1.1 // 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: 6 additions & 2 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=
@@ -76,8 +80,8 @@ golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
7680
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
7781
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
7882
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
79-
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
80-
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
83+
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
84+
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
8185
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
8286
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
8387
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

0 commit comments

Comments
 (0)