@@ -28,13 +28,26 @@ import (
2828
2929const defaultMountFlags = unix .MS_NOEXEC | unix .MS_NOSUID | unix .MS_NODEV
3030
31+ // mountConfig contains mount data not specific to a mount point.
3132type mountConfig struct {
3233 root string
3334 label string
3435 cgroup2Path string
3536 rootlessCgroups bool
3637 cgroupns bool
37- fd * int
38+ }
39+
40+ // mountEntry contains mount data specific to a mount point.
41+ type mountEntry struct {
42+ * configs.Mount
43+ srcFD string
44+ }
45+
46+ func (m * mountEntry ) src () string {
47+ if m .srcFD != "" {
48+ return m .srcFD
49+ }
50+ return m .Source
3851}
3952
4053// needsSetupDev returns true if /dev needs to be set up.
@@ -67,21 +80,20 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig, mountFds []int) (err
6780 rootlessCgroups : iConfig .RootlessCgroups ,
6881 cgroupns : config .Namespaces .Contains (configs .NEWCGROUP ),
6982 }
70- setupDev := needsSetupDev (config )
7183 for i , m := range config .Mounts {
84+ entry := mountEntry {Mount : m }
7285 // Just before the loop we checked that if not empty, len(mountFds) == len(config.Mounts).
7386 // Therefore, we can access mountFds[i] without any concerns.
7487 if mountFds != nil && mountFds [i ] != - 1 {
75- mountConfig .fd = & mountFds [i ]
76- } else {
77- mountConfig .fd = nil
88+ entry .srcFD = "/proc/self/fd/" + strconv .Itoa (mountFds [i ])
7889 }
7990
80- if err := mountToRootfs (m , mountConfig ); err != nil {
91+ if err := mountToRootfs (mountConfig , entry ); err != nil {
8192 return fmt .Errorf ("error mounting %q to rootfs at %q: %w" , m .Source , m .Destination , err )
8293 }
8394 }
8495
96+ setupDev := needsSetupDev (config )
8597 if setupDev {
8698 if err := createDevices (config ); err != nil {
8799 return fmt .Errorf ("error creating device nodes: %w" , err )
@@ -201,12 +213,8 @@ func cleanupTmp(tmpdir string) {
201213 _ = os .RemoveAll (tmpdir )
202214}
203215
204- func prepareBindMount (m * configs.Mount , rootfs string , mountFd * int ) error {
205- source := m .Source
206- if mountFd != nil {
207- source = "/proc/self/fd/" + strconv .Itoa (* mountFd )
208- }
209-
216+ func prepareBindMount (m mountEntry , rootfs string ) error {
217+ source := m .src ()
210218 stat , err := os .Stat (source )
211219 if err != nil {
212220 // error out if the source of a bind mount does not exist as we will be
@@ -252,7 +260,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
252260 PropagationFlags : m .PropagationFlags ,
253261 }
254262
255- if err := mountToRootfs (tmpfs , c ); err != nil {
263+ if err := mountToRootfs (c , mountEntry { Mount : tmpfs } ); err != nil {
256264 return err
257265 }
258266
@@ -280,7 +288,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
280288 return err
281289 }
282290 } else {
283- if err := mountToRootfs (b , c ); err != nil {
291+ if err := mountToRootfs (c , mountEntry { Mount : b } ); err != nil {
284292 return err
285293 }
286294 }
@@ -328,8 +336,8 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
328336 bindM .Source = c .cgroup2Path
329337 }
330338 // mountToRootfs() handles remounting for MS_RDONLY.
331- // No need to set c.fd here, because mountToRootfs() calls utils.WithProcfd() by itself in mountPropagate().
332- err = mountToRootfs (bindM , c )
339+ // No need to set mountEntry.srcFD here, because mountToRootfs() calls utils.WithProcfd() by itself in mountPropagate().
340+ err = mountToRootfs (c , mountEntry { Mount : bindM } )
333341 if c .rootlessCgroups && errors .Is (err , unix .ENOENT ) {
334342 // ENOENT (for `src = c.cgroup2Path`) happens when rootless runc is being executed
335343 // outside the userns+mountns.
@@ -343,7 +351,7 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
343351 return err
344352}
345353
346- func doTmpfsCopyUp (m * configs. Mount , rootfs , mountLabel string ) (Err error ) {
354+ func doTmpfsCopyUp (m mountEntry , rootfs , mountLabel string ) (Err error ) {
347355 // Set up a scratch dir for the tmpfs on the host.
348356 tmpdir , err := prepareTmp ("/tmp" )
349357 if err != nil {
@@ -360,7 +368,7 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) {
360368 // m.Destination since we are going to mount *on the host*.
361369 oldDest := m .Destination
362370 m .Destination = tmpDir
363- err = mountPropagate (m , "/" , mountLabel , nil )
371+ err = mountPropagate (m , "/" , mountLabel )
364372 m .Destination = oldDest
365373 if err != nil {
366374 return err
@@ -388,7 +396,7 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) {
388396 })
389397}
390398
391- func mountToRootfs (m * configs. Mount , c * mountConfig ) error {
399+ func mountToRootfs (c * mountConfig , m mountEntry ) error {
392400 rootfs := c .root
393401
394402 // procfs and sysfs are special because we need to ensure they are actually
@@ -416,11 +424,10 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
416424 return err
417425 }
418426 // Selinux kernels do not support labeling of /proc or /sys.
419- return mountPropagate (m , rootfs , "" , nil )
427+ return mountPropagate (m , rootfs , "" )
420428 }
421429
422430 mountLabel := c .label
423- mountFd := c .fd
424431 dest , err := securejoin .SecureJoin (rootfs , m .Destination )
425432 if err != nil {
426433 return err
@@ -431,7 +438,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
431438 if err := os .MkdirAll (dest , 0o755 ); err != nil {
432439 return err
433440 }
434- if err := mountPropagate (m , rootfs , "" , nil ); err != nil {
441+ if err := mountPropagate (m , rootfs , "" ); err != nil {
435442 return err
436443 }
437444 return label .SetFileLabel (dest , mountLabel )
@@ -446,7 +453,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
446453 if m .Extensions & configs .EXT_COPYUP == configs .EXT_COPYUP {
447454 err = doTmpfsCopyUp (m , rootfs , mountLabel )
448455 } else {
449- err = mountPropagate (m , rootfs , mountLabel , nil )
456+ err = mountPropagate (m , rootfs , mountLabel )
450457 }
451458
452459 if err != nil {
@@ -460,17 +467,17 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
460467 }
461468 return nil
462469 case "bind" :
463- if err := prepareBindMount (m , rootfs , mountFd ); err != nil {
470+ if err := prepareBindMount (m , rootfs ); err != nil {
464471 return err
465472 }
466- if err := mountPropagate (m , rootfs , mountLabel , mountFd ); err != nil {
473+ if err := mountPropagate (m , rootfs , mountLabel ); err != nil {
467474 return err
468475 }
469476 // bind mount won't change mount options, we need remount to make mount options effective.
470477 // first check that we have non-default options required before attempting a remount
471478 if m .Flags &^(unix .MS_REC | unix .MS_REMOUNT | unix .MS_BIND ) != 0 {
472479 // only remount if unique mount options are set
473- if err := remount (m , rootfs , mountFd ); err != nil {
480+ if err := remount (m , rootfs ); err != nil {
474481 return err
475482 }
476483 }
@@ -484,20 +491,20 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
484491 return err
485492 }
486493 }
487- return setRecAttr (m , rootfs )
494+ return setRecAttr (m . Mount , rootfs )
488495 case "cgroup" :
489496 if cgroups .IsCgroup2UnifiedMode () {
490- return mountCgroupV2 (m , c )
497+ return mountCgroupV2 (m . Mount , c )
491498 }
492- return mountCgroupV1 (m , c )
499+ return mountCgroupV1 (m . Mount , c )
493500 default :
494501 if err := checkProcMount (rootfs , dest , m .Source ); err != nil {
495502 return err
496503 }
497504 if err := os .MkdirAll (dest , 0o755 ); err != nil {
498505 return err
499506 }
500- return mountPropagate (m , rootfs , mountLabel , mountFd )
507+ return mountPropagate (m , rootfs , mountLabel )
501508 }
502509}
503510
@@ -1059,35 +1066,31 @@ func writeSystemProperty(key, value string) error {
10591066 return os .WriteFile (path .Join ("/proc/sys" , keyPath ), []byte (value ), 0o644 )
10601067}
10611068
1062- func remount (m * configs.Mount , rootfs string , mountFd * int ) error {
1063- srcFD := ""
1064- if mountFd != nil {
1065- srcFD = "/proc/self/fd/" + strconv .Itoa (* mountFd )
1066- }
1067-
1069+ func remount (m mountEntry , rootfs string ) error {
10681070 return utils .WithProcfd (rootfs , m .Destination , func (dstFD string ) error {
10691071 flags := uintptr (m .Flags | unix .MS_REMOUNT )
1070- err := mountViaFDs (m .Source , srcFD , m .Destination , dstFD , m .Device , flags , "" )
1072+ err := mountViaFDs (m .Source , m . srcFD , m .Destination , dstFD , m .Device , flags , "" )
10711073 if err == nil {
10721074 return nil
10731075 }
10741076 // Check if the source has ro flag...
1077+ src := m .src ()
10751078 var s unix.Statfs_t
1076- if err := unix .Statfs (m . Source , & s ); err != nil {
1077- return & os.PathError {Op : "statfs" , Path : m . Source , Err : err }
1079+ if err := unix .Statfs (src , & s ); err != nil {
1080+ return & os.PathError {Op : "statfs" , Path : src , Err : err }
10781081 }
10791082 if s .Flags & unix .MS_RDONLY != unix .MS_RDONLY {
10801083 return err
10811084 }
10821085 // ... and retry the mount with ro flag set.
10831086 flags |= unix .MS_RDONLY
1084- return mountViaFDs (m .Source , srcFD , m .Destination , dstFD , m .Device , flags , "" )
1087+ return mountViaFDs (m .Source , m . srcFD , m .Destination , dstFD , m .Device , flags , "" )
10851088 })
10861089}
10871090
10881091// Do the mount operation followed by additional mounts required to take care
10891092// of propagation flags. This will always be scoped inside the container rootfs.
1090- func mountPropagate (m * configs. Mount , rootfs string , mountLabel string , mountFd * int ) error {
1093+ func mountPropagate (m mountEntry , rootfs string , mountLabel string ) error {
10911094 var (
10921095 data = label .FormatMountLabel (m .Data , mountLabel )
10931096 flags = m .Flags
@@ -1100,17 +1103,12 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string, mountFd
11001103 flags &= ^ unix .MS_RDONLY
11011104 }
11021105
1103- srcFD := ""
1104- if mountFd != nil {
1105- srcFD = "/proc/self/fd/" + strconv .Itoa (* mountFd )
1106- }
1107-
11081106 // Because the destination is inside a container path which might be
11091107 // mutating underneath us, we verify that we are actually going to mount
11101108 // inside the container with WithProcfd() -- mounting through a procfd
11111109 // mounts on the target.
11121110 if err := utils .WithProcfd (rootfs , m .Destination , func (dstFD string ) error {
1113- return mountViaFDs (m .Source , srcFD , m .Destination , dstFD , m .Device , uintptr (flags ), data )
1111+ return mountViaFDs (m .Source , m . srcFD , m .Destination , dstFD , m .Device , uintptr (flags ), data )
11141112 }); err != nil {
11151113 return err
11161114 }
0 commit comments