Skip to content

Commit a60933b

Browse files
committed
libct/rootfs: introduce and use mountEntry
Adding fd field to mountConfig was not a good thing since mountConfig contains data that is not specific to a particular mount, while fd is a mount entry attribute. Introduce mountEntry structure, which embeds configs.Mount and adds srcFd to replace the removed mountConfig.fd. Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 976748e commit a60933b

File tree

2 files changed

+47
-50
lines changed

2 files changed

+47
-50
lines changed

libcontainer/container_linux.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,9 +1277,8 @@ func (c *Container) makeCriuRestoreMountpoints(m *configs.Mount) error {
12771277
case "bind":
12781278
// The prepareBindMount() function checks if source
12791279
// exists. So it cannot be used for other filesystem types.
1280-
// TODO: pass something else than nil? Not sure if criu is
1281-
// impacted by issue #2484
1282-
if err := prepareBindMount(m, c.config.Rootfs, nil); err != nil {
1280+
// TODO: pass srcFD? Not sure if criu is impacted by issue #2484.
1281+
if err := prepareBindMount(mountEntry{Mount: m}, c.config.Rootfs); err != nil {
12831282
return err
12841283
}
12851284
default:

libcontainer/rootfs_linux.go

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,26 @@ import (
2828

2929
const defaultMountFlags = unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV
3030

31+
// mountConfig contains mount data not specific to a mount point.
3132
type 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

Comments
 (0)