@@ -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,7 +336,7 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
328336 })
329337}
330338
331- func doTmpfsCopyUp (m * configs. Mount , rootfs , mountLabel string ) (Err error ) {
339+ func doTmpfsCopyUp (m mountEntry , rootfs , mountLabel string ) (Err error ) {
332340 // Set up a scratch dir for the tmpfs on the host.
333341 tmpdir , err := prepareTmp ("/tmp" )
334342 if err != nil {
@@ -345,7 +353,7 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) {
345353 // m.Destination since we are going to mount *on the host*.
346354 oldDest := m .Destination
347355 m .Destination = tmpDir
348- err = mountPropagate (m , "/" , mountLabel , nil )
356+ err = mountPropagate (m , "/" , mountLabel )
349357 m .Destination = oldDest
350358 if err != nil {
351359 return err
@@ -373,10 +381,9 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) {
373381 })
374382}
375383
376- func mountToRootfs (m * configs. Mount , c * mountConfig ) error {
384+ func mountToRootfs (c * mountConfig , m mountEntry ) error {
377385 rootfs := c .root
378386 mountLabel := c .label
379- mountFd := c .fd
380387 dest , err := securejoin .SecureJoin (rootfs , m .Destination )
381388 if err != nil {
382389 return err
@@ -400,12 +407,12 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
400407 return err
401408 }
402409 // Selinux kernels do not support labeling of /proc or /sys
403- return mountPropagate (m , rootfs , "" , nil )
410+ return mountPropagate (m , rootfs , "" )
404411 case "mqueue" :
405412 if err := os .MkdirAll (dest , 0o755 ); err != nil {
406413 return err
407414 }
408- if err := mountPropagate (m , rootfs , "" , nil ); err != nil {
415+ if err := mountPropagate (m , rootfs , "" ); err != nil {
409416 return err
410417 }
411418 return label .SetFileLabel (dest , mountLabel )
@@ -420,7 +427,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
420427 if m .Extensions & configs .EXT_COPYUP == configs .EXT_COPYUP {
421428 err = doTmpfsCopyUp (m , rootfs , mountLabel )
422429 } else {
423- err = mountPropagate (m , rootfs , mountLabel , nil )
430+ err = mountPropagate (m , rootfs , mountLabel )
424431 }
425432
426433 if err != nil {
@@ -434,17 +441,17 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
434441 }
435442 return nil
436443 case "bind" :
437- if err := prepareBindMount (m , rootfs , mountFd ); err != nil {
444+ if err := prepareBindMount (m , rootfs ); err != nil {
438445 return err
439446 }
440- if err := mountPropagate (m , rootfs , mountLabel , mountFd ); err != nil {
447+ if err := mountPropagate (m , rootfs , mountLabel ); err != nil {
441448 return err
442449 }
443450 // bind mount won't change mount options, we need remount to make mount options effective.
444451 // first check that we have non-default options required before attempting a remount
445452 if m .Flags &^(unix .MS_REC | unix .MS_REMOUNT | unix .MS_BIND ) != 0 {
446453 // only remount if unique mount options are set
447- if err := remount (m , rootfs , mountFd ); err != nil {
454+ if err := remount (m , rootfs ); err != nil {
448455 return err
449456 }
450457 }
@@ -460,19 +467,19 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
460467 }
461468 case "cgroup" :
462469 if cgroups .IsCgroup2UnifiedMode () {
463- return mountCgroupV2 (m , c )
470+ return mountCgroupV2 (m . Mount , c )
464471 }
465- return mountCgroupV1 (m , c )
472+ return mountCgroupV1 (m . Mount , c )
466473 default :
467474 if err := checkProcMount (rootfs , dest , m .Source ); err != nil {
468475 return err
469476 }
470477 if err := os .MkdirAll (dest , 0o755 ); err != nil {
471478 return err
472479 }
473- return mountPropagate (m , rootfs , mountLabel , mountFd )
480+ return mountPropagate (m , rootfs , mountLabel )
474481 }
475- if err := setRecAttr (m , rootfs ); err != nil {
482+ if err := setRecAttr (m . Mount , rootfs ); err != nil {
476483 return err
477484 }
478485 return nil
@@ -1036,35 +1043,31 @@ func writeSystemProperty(key, value string) error {
10361043 return os .WriteFile (path .Join ("/proc/sys" , keyPath ), []byte (value ), 0o644 )
10371044}
10381045
1039- func remount (m * configs.Mount , rootfs string , mountFd * int ) error {
1040- srcFD := ""
1041- if mountFd != nil {
1042- srcFD = "/proc/self/fd/" + strconv .Itoa (* mountFd )
1043- }
1044-
1046+ func remount (m mountEntry , rootfs string ) error {
10451047 return utils .WithProcfd (rootfs , m .Destination , func (dstFD string ) error {
10461048 flags := uintptr (m .Flags | unix .MS_REMOUNT )
1047- err := mountViaFDs (m .Source , srcFD , m .Destination , dstFD , m .Device , flags , "" )
1049+ err := mountViaFDs (m .Source , m . srcFD , m .Destination , dstFD , m .Device , flags , "" )
10481050 if err == nil {
10491051 return nil
10501052 }
10511053 // Check if the source has ro flag...
1054+ src := m .src ()
10521055 var s unix.Statfs_t
1053- if err := unix .Statfs (m . Source , & s ); err != nil {
1054- return & os.PathError {Op : "statfs" , Path : m . Source , Err : err }
1056+ if err := unix .Statfs (src , & s ); err != nil {
1057+ return & os.PathError {Op : "statfs" , Path : src , Err : err }
10551058 }
10561059 if s .Flags & unix .MS_RDONLY != unix .MS_RDONLY {
10571060 return err
10581061 }
10591062 // ... and retry the mount with ro flag set.
10601063 flags |= unix .MS_RDONLY
1061- return mountViaFDs (m .Source , srcFD , m .Destination , dstFD , m .Device , flags , "" )
1064+ return mountViaFDs (m .Source , m . srcFD , m .Destination , dstFD , m .Device , flags , "" )
10621065 })
10631066}
10641067
10651068// Do the mount operation followed by additional mounts required to take care
10661069// of propagation flags. This will always be scoped inside the container rootfs.
1067- func mountPropagate (m * configs. Mount , rootfs string , mountLabel string , mountFd * int ) error {
1070+ func mountPropagate (m mountEntry , rootfs string , mountLabel string ) error {
10681071 var (
10691072 data = label .FormatMountLabel (m .Data , mountLabel )
10701073 flags = m .Flags
@@ -1077,17 +1080,12 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string, mountFd
10771080 flags &= ^ unix .MS_RDONLY
10781081 }
10791082
1080- srcFD := ""
1081- if mountFd != nil {
1082- srcFD = "/proc/self/fd/" + strconv .Itoa (* mountFd )
1083- }
1084-
10851083 // Because the destination is inside a container path which might be
10861084 // mutating underneath us, we verify that we are actually going to mount
10871085 // inside the container with WithProcfd() -- mounting through a procfd
10881086 // mounts on the target.
10891087 if err := utils .WithProcfd (rootfs , m .Destination , func (dstFD string ) error {
1090- return mountViaFDs (m .Source , srcFD , m .Destination , dstFD , m .Device , uintptr (flags ), data )
1088+ return mountViaFDs (m .Source , m . srcFD , m .Destination , dstFD , m .Device , uintptr (flags ), data )
10911089 }); err != nil {
10921090 return err
10931091 }
0 commit comments