Skip to content

Commit 599ab62

Browse files
committed
Switch to go 1.25 os.Root
Signed-off-by: Evan Lezar <[email protected]>
1 parent 8a85cad commit 599ab62

File tree

7 files changed

+46
-89
lines changed

7 files changed

+46
-89
lines changed

cmd/nvidia-cdi-hook/disable-device-node-modification/disable-device-node-modification.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,13 @@ func run(_ context.Context, _ *cli.Command, cfg *options) error {
9090
return fmt.Errorf("failed to determined container root: %w", err)
9191
}
9292

93-
return createParamsFileInContainer(containerRootDirPath, modifiedParamsFileContents)
93+
containerRoot, err := os.OpenRoot(containerRootDirPath)
94+
if err != nil {
95+
return fmt.Errorf("failed to open root: %w", err)
96+
}
97+
defer containerRoot.Close()
98+
99+
return createParamsFileInContainer(containerRoot, modifiedParamsFileContents)
94100
}
95101

96102
func getModifiedNVIDIAParamsContents() ([]byte, error) {

cmd/nvidia-cdi-hook/disable-device-node-modification/params_linux.go

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@
2020
package disabledevicenodemodification
2121

2222
import (
23-
"errors"
2423
"fmt"
2524
"os"
2625
"path/filepath"
2726

28-
securejoin "github.com/cyphar/filepath-securejoin"
2927
"github.com/opencontainers/runc/libcontainer/utils"
3028
"golang.org/x/sys/unix"
3129
)
3230

33-
func createParamsFileInContainer(containerRootDirPath string, contents []byte) error {
31+
func createParamsFileInContainer(containerRoot *os.Root, contents []byte) error {
32+
containerRootDirPath := containerRoot.Name()
33+
3434
hookScratchDirPath := "/var/run/nvidia-ctk-hook"
35-
if err := utils.MkdirAllInRoot(containerRootDirPath, hookScratchDirPath, 0755); err != nil {
35+
if err := containerRoot.MkdirAll(hookScratchDirPath[1:], 0755); err != nil {
3636
return fmt.Errorf("error creating hook scratch folder: %w", err)
3737
}
3838

@@ -45,7 +45,7 @@ func createParamsFileInContainer(containerRootDirPath string, contents []byte) e
4545
}
4646

4747
modifiedParamsFilePath := filepath.Join(hookScratchDirPath, "nvct-params")
48-
if _, err := createFileInRoot(containerRootDirPath, modifiedParamsFilePath, 0444); err != nil {
48+
if _, err := containerRoot.OpenFile(modifiedParamsFilePath[1:], os.O_CREATE|os.O_RDONLY|os.O_TRUNC, unix.S_IFREG|0444); err != nil {
4949
return fmt.Errorf("error creating modified params file: %w", err)
5050
}
5151

@@ -79,32 +79,3 @@ func createParamsFileInContainer(containerRootDirPath string, contents []byte) e
7979
func createTmpFs(target string, size int) error {
8080
return unix.Mount("tmpfs", target, "tmpfs", 0, fmt.Sprintf("size=%d", size))
8181
}
82-
83-
// TODO(ArangoGutierrez): This function also exists in internal/ldconfig we should move this to a separate package.
84-
func createFileInRoot(containerRootDirPath string, destinationPath string, mode os.FileMode) (string, error) {
85-
dest, err := securejoin.SecureJoin(containerRootDirPath, destinationPath)
86-
if err != nil {
87-
return "", err
88-
}
89-
// Make the parent directory.
90-
destDir, destBase := filepath.Split(dest)
91-
destDirFd, err := utils.MkdirAllInRootOpen(containerRootDirPath, destDir, 0755)
92-
if err != nil {
93-
return "", fmt.Errorf("error creating parent dir: %w", err)
94-
}
95-
defer destDirFd.Close()
96-
// Make the target file. We want to avoid opening any file that is
97-
// already there because it could be a "bad" file like an invalid
98-
// device or hung tty that might cause a DoS, so we use mknodat.
99-
// destBase does not contain any "/" components, and mknodat does
100-
// not follow trailing symlinks, so we can safely just call mknodat
101-
// here.
102-
if err := unix.Mknodat(int(destDirFd.Fd()), destBase, unix.S_IFREG|uint32(mode), 0); err != nil {
103-
// If we get EEXIST, there was already an inode there and
104-
// we can consider that a success.
105-
if !errors.Is(err, unix.EEXIST) {
106-
return "", fmt.Errorf("error creating empty file: %w", err)
107-
}
108-
}
109-
return dest, nil
110-
}

cmd/nvidia-cdi-hook/disable-device-node-modification/params_other.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919

2020
package disabledevicenodemodification
2121

22-
import "fmt"
22+
import (
23+
"fmt"
24+
"os"
25+
)
2326

24-
func createParamsFileInContainer(containerRootDirPath string, contents []byte) error {
27+
func createParamsFileInContainer(containerRootDirPath *os.Root, contents []byte) error {
2528
return fmt.Errorf("not supported")
2629
}

go.mod

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
module github.com/NVIDIA/nvidia-container-toolkit
22

3-
go 1.24.0
4-
5-
toolchain go1.24.4
3+
go 1.25.0
64

75
require (
86
github.com/NVIDIA/go-nvlib v0.8.1
97
github.com/NVIDIA/go-nvml v0.13.0-1
10-
github.com/cyphar/filepath-securejoin v0.5.0
118
github.com/moby/sys/reexec v0.1.0
129
github.com/moby/sys/symlink v0.3.0
1310
github.com/opencontainers/runc v1.3.2
@@ -24,6 +21,7 @@ require (
2421
)
2522

2623
require (
24+
github.com/cyphar/filepath-securejoin v0.5.0 // indirect
2725
github.com/davecgh/go-spew v1.1.1 // indirect
2826
github.com/fsnotify/fsnotify v1.7.0 // indirect
2927
github.com/google/go-cmp v0.6.0 // indirect

internal/ldconfig/ldconfig.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,18 @@ func NewRunner(id string, ldconfigPath string, containerRoot string, additionala
5656
// New creates an Ldconfig struct that is used to perform operations on the
5757
// ldcache and libraries in a particular root (e.g. a container).
5858
func New(ldconfigPath string, inRoot string) (*Ldconfig, error) {
59-
l := &Ldconfig{
60-
ldconfigPath: ldconfigPath,
61-
inRoot: inRoot,
62-
}
6359
if ldconfigPath == "" {
6460
return nil, fmt.Errorf("an ldconfig path must be specified")
6561
}
6662
if inRoot == "" || inRoot == "/" {
6763
return nil, fmt.Errorf("ldconfig must be run in the non-system root")
6864
}
65+
66+
l := &Ldconfig{
67+
ldconfigPath: ldconfigPath,
68+
inRoot: inRoot,
69+
}
70+
6971
return l, nil
7072
}
7173

@@ -91,22 +93,28 @@ func (l *Ldconfig) UpdateLDCache(directories ...string) error {
9193
}
9294

9395
func (l *Ldconfig) prepareRoot() (string, error) {
96+
root, err := os.OpenRoot(l.inRoot)
97+
if err != nil {
98+
return "", fmt.Errorf("failed to open root: %w", err)
99+
}
100+
defer root.Close()
101+
94102
// To prevent leaking the parent proc filesystem, we create a new proc mount
95103
// in the specified root.
96-
if err := mountProc(l.inRoot); err != nil {
104+
if err := mountProc(root); err != nil {
97105
return "", fmt.Errorf("error mounting /proc: %w", err)
98106
}
99107

100108
// We mount the host ldconfig before we pivot root since host paths are not
101109
// visible after the pivot root operation.
102-
ldconfigPath, err := mountLdConfig(l.ldconfigPath, l.inRoot)
110+
ldconfigPath, err := mountLdConfig(l.ldconfigPath, root)
103111
if err != nil {
104112
return "", fmt.Errorf("error mounting host ldconfig: %w", err)
105113
}
106114

107115
// We pivot to the container root for the new process, this further limits
108116
// access to the host.
109-
if err := pivotRoot(l.inRoot); err != nil {
117+
if err := pivotRoot(root.Name()); err != nil {
110118
return "", fmt.Errorf("error running pivot_root: %w", err)
111119
}
112120

internal/ldconfig/ldconfig_linux.go

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@
2020
package ldconfig
2121

2222
import (
23-
"errors"
2423
"fmt"
2524
"os"
2625
"os/exec"
2726
"path/filepath"
2827
"strconv"
2928
"syscall"
3029

31-
securejoin "github.com/cyphar/filepath-securejoin"
3230
"github.com/moby/sys/reexec"
3331

3432
"github.com/opencontainers/runc/libcontainer/utils"
@@ -102,15 +100,17 @@ func pivotRoot(rootfs string) error {
102100
// mountLdConfig mounts the host ldconfig to the mount namespace of the hook.
103101
// We use WithProcfd to perform the mount operations to ensure that the changes
104102
// are persisted across the pivot root.
105-
func mountLdConfig(hostLdconfigPath string, containerRootDirPath string) (string, error) {
103+
func mountLdConfig(hostLdconfigPath string, containerRoot *os.Root) (string, error) {
104+
containerRootDirPath := containerRoot.Name()
105+
106106
hostLdconfigInfo, err := os.Stat(hostLdconfigPath)
107107
if err != nil {
108108
return "", fmt.Errorf("error reading host ldconfig: %w", err)
109109
}
110110

111111
hookScratchDirPath := "/var/run/nvidia-ctk-hook"
112112
ldconfigPath := filepath.Join(hookScratchDirPath, "ldconfig")
113-
if err := utils.MkdirAllInRoot(containerRootDirPath, hookScratchDirPath, 0755); err != nil {
113+
if err := containerRoot.MkdirAll(hookScratchDirPath[1:], 0755); err != nil {
114114
return "", fmt.Errorf("error creating hook scratch folder: %w", err)
115115
}
116116

@@ -122,7 +122,7 @@ func mountLdConfig(hostLdconfigPath string, containerRootDirPath string) (string
122122
return "", fmt.Errorf("error creating tmpfs: %w", err)
123123
}
124124

125-
if _, err := createFileInRoot(containerRootDirPath, ldconfigPath, hostLdconfigInfo.Mode()); err != nil {
125+
if _, err := containerRoot.OpenFile(ldconfigPath[1:], os.O_CREATE|os.O_RDWR|os.O_TRUNC, unix.S_IFREG|hostLdconfigInfo.Mode()); err != nil {
126126
return "", fmt.Errorf("error creating ldconfig: %w", err)
127127
}
128128

@@ -136,43 +136,13 @@ func mountLdConfig(hostLdconfigPath string, containerRootDirPath string) (string
136136
return ldconfigPath, nil
137137
}
138138

139-
func createFileInRoot(containerRootDirPath string, destinationPath string, mode os.FileMode) (string, error) {
140-
dest, err := securejoin.SecureJoin(containerRootDirPath, destinationPath)
141-
if err != nil {
142-
return "", err
143-
}
144-
// Make the parent directory.
145-
destDir, destBase := filepath.Split(dest)
146-
destDirFd, err := utils.MkdirAllInRootOpen(containerRootDirPath, destDir, 0755)
147-
if err != nil {
148-
return "", fmt.Errorf("error creating parent dir: %w", err)
149-
}
150-
defer destDirFd.Close()
151-
// Make the target file. We want to avoid opening any file that is
152-
// already there because it could be a "bad" file like an invalid
153-
// device or hung tty that might cause a DoS, so we use mknodat.
154-
// destBase does not contain any "/" components, and mknodat does
155-
// not follow trailing symlinks, so we can safely just call mknodat
156-
// here.
157-
if err := unix.Mknodat(int(destDirFd.Fd()), destBase, unix.S_IFREG|uint32(mode), 0); err != nil {
158-
// If we get EEXIST, there was already an inode there and
159-
// we can consider that a success.
160-
if !errors.Is(err, unix.EEXIST) {
161-
return "", fmt.Errorf("error creating empty file: %w", err)
162-
}
163-
}
164-
return dest, nil
165-
}
166-
167139
// mountProc mounts a clean proc filesystem in the new root.
168-
func mountProc(newroot string) error {
169-
target, err := securejoin.SecureJoin(newroot, "proc")
170-
if err != nil {
171-
return err
172-
}
173-
if err := utils.MkdirAllInRoot(newroot, target, 0755); err != nil {
140+
func mountProc(newroot *os.Root) error {
141+
if err := newroot.MkdirAll("proc", 0755); err != nil {
174142
return err
175143
}
144+
145+
target := filepath.Join(newroot.Name(), "proc")
176146
return unix.Mount("proc", target, "proc", 0, "")
177147
}
178148

internal/ldconfig/ldconfig_other.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,19 @@ package ldconfig
2121

2222
import (
2323
"fmt"
24+
"os"
2425
"os/exec"
2526
)
2627

2728
func pivotRoot(newroot string) error {
2829
return fmt.Errorf("not supported")
2930
}
3031

31-
func mountLdConfig(hostLdconfigPath string, containerRootDirPath string) (string, error) {
32+
func mountLdConfig(hostLdconfigPath string, containerRoot *os.Root) (string, error) {
3233
return "", fmt.Errorf("not supported")
3334
}
3435

35-
func mountProc(newroot string) error {
36+
func mountProc(newroot *os.Root) error {
3637
return fmt.Errorf("not supported")
3738
}
3839

0 commit comments

Comments
 (0)