@@ -25,6 +25,8 @@ import (
2525 "path/filepath"
2626 "strings"
2727
28+ "github.com/prometheus/procfs"
29+
2830 "github.com/NVIDIA/nvidia-container-toolkit/internal/config"
2931)
3032
@@ -40,6 +42,7 @@ const (
4042type Ldconfig struct {
4143 ldconfigPath string
4244 inRoot string
45+ noPivotRoot bool
4346 directories []string
4447}
4548
@@ -50,6 +53,11 @@ func NewRunner(id string, ldconfigPath string, containerRoot string, additionala
5053 "--ldconfig-path" , strings .TrimPrefix (config .NormalizeLDConfigPath ("@" + ldconfigPath ), "@" ),
5154 "--container-root" , containerRoot ,
5255 }
56+
57+ if noPivotRoot () {
58+ args = append (args , "--no-pivot" )
59+ }
60+
5361 args = append (args , additionalargs ... )
5462
5563 return createReexecCommand (args )
@@ -69,6 +77,7 @@ func NewFromArgs(args ...string) (*Ldconfig, error) {
6977 fs := flag .NewFlagSet (args [1 ], flag .ExitOnError )
7078 ldconfigPath := fs .String ("ldconfig-path" , "" , "the path to ldconfig on the host" )
7179 containerRoot := fs .String ("container-root" , "" , "the path in which ldconfig must be run" )
80+ noPivot := fs .Bool ("no-pivot" , false , "don't use pivot_root to perform isolation" )
7281 if err := fs .Parse (args [1 :]); err != nil {
7382 return nil , err
7483 }
@@ -83,6 +92,7 @@ func NewFromArgs(args ...string) (*Ldconfig, error) {
8392 l := & Ldconfig {
8493 ldconfigPath : * ldconfigPath ,
8594 inRoot : * containerRoot ,
95+ noPivotRoot : * noPivot ,
8696 directories : fs .Args (),
8797 }
8898 return l , nil
@@ -159,9 +169,18 @@ func (l *Ldconfig) prepareRoot() (string, error) {
159169 return "" , fmt .Errorf ("error mounting host ldconfig: %w" , err )
160170 }
161171
172+ // We select the function to pivot the root based on whether pivot_root is
173+ // supported.
174+ // See https://github.com/opencontainers/runc/blob/c3d127f6e8d9f6c06d78b8329cafa8dd39f6236e/libcontainer/rootfs_linux.go#L207-L216
175+ var pivotRootFn func (string ) error
176+ if l .noPivotRoot {
177+ pivotRootFn = msMoveRoot
178+ } else {
179+ pivotRootFn = pivotRoot
180+ }
162181 // We pivot to the container root for the new process, this further limits
163182 // access to the host.
164- if err := pivotRoot (l .inRoot ); err != nil {
183+ if err := pivotRootFn (l .inRoot ); err != nil {
165184 return "" , fmt .Errorf ("error running pivot_root: %w" , err )
166185 }
167186
@@ -223,3 +242,39 @@ func createLdsoconfdFile(pattern string, dirs ...string) error {
223242
224243 return nil
225244}
245+
246+ // noPivotRoot checks whether the current root filesystem supports a pivot_root.
247+ // See https://github.com/opencontainers/runc/blob/main/libcontainer/SPEC.md#filesystem
248+ // for a discussion on when this is not the case.
249+ // If we fail to detect whether pivot-root is supported, we assume that it is supported.
250+ // The logic to check for support is adapted from kata-containers:
251+ //
252+ // https://github.com/kata-containers/kata-containers/blob/e7b9eddcede4bbe2edeb9c3af7b2358dc65da76f/src/agent/src/sandbox.rs#L150
253+ //
254+ // and checks whether "/" is mounted as a rootfs.
255+ func noPivotRoot () bool {
256+ rootFsType , err := getRootfsType ("/" )
257+ if err != nil {
258+ return false
259+ }
260+ return rootFsType == "rootfs"
261+ }
262+
263+ func getRootfsType (path string ) (string , error ) {
264+ procSelf , err := procfs .Self ()
265+ if err != nil {
266+ return "" , err
267+ }
268+
269+ mountStats , err := procSelf .MountStats ()
270+ if err != nil {
271+ return "" , err
272+ }
273+
274+ for _ , mountStat := range mountStats {
275+ if mountStat .Mount == path {
276+ return mountStat .Type , nil
277+ }
278+ }
279+ return "" , fmt .Errorf ("mount stats for %q not found" , path )
280+ }
0 commit comments