Skip to content

Commit 241edc9

Browse files
[no-relnote] Replace deprecated runc utils.WithProcfd with local helper function
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
1 parent 6e26bac commit 241edc9

File tree

4 files changed

+69
-9
lines changed

4 files changed

+69
-9
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ import (
2525
"path/filepath"
2626

2727
"github.com/google/uuid"
28-
"github.com/opencontainers/runc/libcontainer/utils"
2928
"golang.org/x/sys/unix"
29+
30+
"github.com/NVIDIA/nvidia-container-toolkit/internal/system"
3031
)
3132

3233
func createParamsFileInContainer(containerRoot *os.Root, contents []byte) error {
@@ -37,7 +38,7 @@ func createParamsFileInContainer(containerRoot *os.Root, contents []byte) error
3738
return fmt.Errorf("error creating hook scratch folder: %w", err)
3839
}
3940

40-
err := utils.WithProcfd(containerRootDirPath, hookScratchDirPath, func(hookScratchDirFdPath string) error {
41+
err := system.WithProcfd(containerRootDirPath, hookScratchDirPath, func(hookScratchDirFdPath string) error {
4142
return createTmpFs(hookScratchDirFdPath, len(contents))
4243
})
4344
if err != nil {
@@ -49,7 +50,7 @@ func createParamsFileInContainer(containerRoot *os.Root, contents []byte) error
4950
return fmt.Errorf("error creating modified params file: %w", err)
5051
}
5152

52-
err = utils.WithProcfd(containerRootDirPath, modifiedParamsFilePath, func(modifiedParamsFileFdPath string) error {
53+
err = system.WithProcfd(containerRootDirPath, modifiedParamsFilePath, func(modifiedParamsFileFdPath string) error {
5354
modifiedParamsFile, err := os.OpenFile(modifiedParamsFileFdPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0444)
5455
if err != nil {
5556
return fmt.Errorf("failed to open modified params file: %w", err)
@@ -60,7 +61,7 @@ func createParamsFileInContainer(containerRoot *os.Root, contents []byte) error
6061
return fmt.Errorf("failed to write temporary params file: %w", err)
6162
}
6263

63-
err = utils.WithProcfd(containerRootDirPath, nvidiaDriverParamsPath, func(nvidiaDriverParamsFdPath string) error {
64+
err = system.WithProcfd(containerRootDirPath, nvidiaDriverParamsPath, func(nvidiaDriverParamsFdPath string) error {
6465
return unix.Mount(modifiedParamsFileFdPath, nvidiaDriverParamsFdPath, "", unix.MS_BIND|unix.MS_RDONLY|unix.MS_NODEV|unix.MS_PRIVATE|unix.MS_NOSYMFOLLOW, "")
6566
})
6667
if err != nil {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.25.0
55
require (
66
github.com/NVIDIA/go-nvlib v0.8.1
77
github.com/NVIDIA/go-nvml v0.13.0-1
8+
github.com/cyphar/filepath-securejoin v0.6.1
89
github.com/google/uuid v1.6.0
910
github.com/moby/sys/mountinfo v0.7.2
1011
github.com/moby/sys/reexec v0.1.0
@@ -25,7 +26,6 @@ require (
2526

2627
require (
2728
cyphar.com/go-pathrs v0.2.1 // indirect
28-
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
2929
github.com/davecgh/go-spew v1.1.1 // indirect
3030
github.com/fsnotify/fsnotify v1.7.0 // indirect
3131
github.com/hashicorp/errwrap v1.1.0 // indirect

internal/ldconfig/ldconfig_linux.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ import (
3232
"github.com/google/uuid"
3333
"github.com/moby/sys/mountinfo"
3434
"github.com/moby/sys/reexec"
35-
36-
"github.com/opencontainers/runc/libcontainer/utils"
3735
"golang.org/x/sys/unix"
36+
37+
"github.com/NVIDIA/nvidia-container-toolkit/internal/system"
3838
)
3939

4040
// pivotRoot will call pivot_root such that rootfs becomes the new root
@@ -198,7 +198,7 @@ func mountLdConfig(hostLdconfigPath string, containerRoot *os.Root) (string, err
198198
return "", fmt.Errorf("error creating hook scratch folder: %w", err)
199199
}
200200

201-
err = utils.WithProcfd(containerRootDirPath, hookScratchDirPath, func(hookScratchDirFdPath string) error {
201+
err = system.WithProcfd(containerRootDirPath, hookScratchDirPath, func(hookScratchDirFdPath string) error {
202202
return createTmpFs(hookScratchDirFdPath, int(hostLdconfigInfo.Size()))
203203
})
204204
if err != nil {
@@ -209,7 +209,7 @@ func mountLdConfig(hostLdconfigPath string, containerRoot *os.Root) (string, err
209209
return "", fmt.Errorf("error creating ldconfig: %w", err)
210210
}
211211

212-
err = utils.WithProcfd(containerRootDirPath, ldconfigPath, func(ldconfigFdPath string) error {
212+
err = system.WithProcfd(containerRootDirPath, ldconfigPath, func(ldconfigFdPath string) error {
213213
return unix.Mount(hostLdconfigPath, ldconfigFdPath, "", unix.MS_BIND|unix.MS_RDONLY|unix.MS_NODEV|unix.MS_PRIVATE|unix.MS_NOSYMFOLLOW, "")
214214
})
215215
if err != nil {

internal/system/procfd_linux.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//go:build linux
2+
3+
/**
4+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5+
# SPDX-License-Identifier: Apache-2.0
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 system
21+
22+
import (
23+
"fmt"
24+
"os"
25+
"strconv"
26+
27+
securejoin "github.com/cyphar/filepath-securejoin"
28+
"golang.org/x/sys/unix"
29+
)
30+
31+
// WithProcfd opens a file descriptor to the specified path and invokes the
32+
// provided function with a /proc/self/fd path.
33+
func WithProcfd(root, unsafePath string, fn func(fdPath string) error) error {
34+
// Securely join paths to prevent directory traversal attacks
35+
fullPath, err := securejoin.SecureJoin(root, unsafePath)
36+
if err != nil {
37+
return fmt.Errorf("resolving path inside rootfs failed: %w", err)
38+
}
39+
40+
// Open the target path with O_PATH to get a file descriptor without
41+
// actually opening the file for reading or writing
42+
fd, err := unix.Open(fullPath, unix.O_PATH|unix.O_CLOEXEC, 0)
43+
if err != nil {
44+
return fmt.Errorf("failed to open path %q: %w", fullPath, err)
45+
}
46+
defer unix.Close(fd)
47+
48+
// Construct the /proc/self/fd path
49+
procFdPath := "/proc/self/fd/" + strconv.Itoa(fd)
50+
51+
// Double-check the path is the one we expected to prevent TOCTOU attacks
52+
if realpath, err := os.Readlink(procFdPath); err != nil {
53+
return fmt.Errorf("procfd verification failed: %w", err)
54+
} else if realpath != fullPath {
55+
return fmt.Errorf("possibly malicious path detected -- refusing to operate on %s", realpath)
56+
}
57+
58+
return fn(procFdPath)
59+
}

0 commit comments

Comments
 (0)