Skip to content

Commit a06d66d

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 42e3c24 commit a06d66d

File tree

2 files changed

+45
-48
lines changed

2 files changed

+45
-48
lines changed

libcontainer/container_linux.go

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

libcontainer/rootfs_linux.go

Lines changed: 43 additions & 45 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,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

Comments
 (0)