Repository: opencontainers/runc
File: libcontainer/rootfs_linux.go (Go)

Code before:
	}
	return nil
}

// writeSystemProperty writes the value to a path under /proc/sys as determined from the key.
// For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward.
func writeSystemProperty(key, value string) error {
	keyPath := strings.Replace(key, ".", "/", -1)
	return os.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0o644)
}

func remount(m mountEntry, rootfs string) error {
	return utils.WithProcfd(rootfs, m.Destination, func(dstFD string) error {
		flags := uintptr(m.Flags | unix.MS_REMOUNT)
		err := mountViaFDs(m.Source, m.srcFD, m.Destination, dstFD, m.Device, flags, "")
		if err == nil {
			return nil
		}
		// Check if the source has ro, nodev, noexec, nosuid, noatime, relatime,
		// strictatime, nodiratime flag...
		src := m.src()
		var s unix.Statfs_t
		if err := unix.Statfs(src, &s); err != nil {
			return &os.PathError{Op: "statfs", Path: src, Err: err}
		}
		if s.Flags&(unix.MS_RDONLY|unix.MS_NODEV|unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NOATIME|unix.MS_RELATIME|unix.MS_STRICTATIME|unix.MS_NODIRATIME) == 0 {
			return err
		}
		// ... and retry the mount with flags found above.
		flags |= uintptr(s.Flags & (unix.MS_RDONLY | unix.MS_NODEV | unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NOATIME | unix.MS_RELATIME | unix.MS_STRICTATIME | unix.MS_NODIRATIME))
		return mountViaFDs(m.Source, m.srcFD, m.Destination, dstFD, m.Device, flags, "")
	})
}

// Do the mount operation followed by additional mounts required to take care
// of propagation flags. This will always be scoped inside the container rootfs.
func mountPropagate(m mountEntry, rootfs string, mountLabel string) error {
	var (
		data  = label.FormatMountLabel(m.Data, mountLabel)
		flags = m.Flags
	)
	// Delay mounting the filesystem read-only if we need to do further
	// operations on it. We need to set up files in "/dev", and other tmpfs
	// mounts may need to be chmod-ed after mounting. These mounts will be
	// remounted ro later in finalizeRootfs(), if necessary.
	if m.Device == "tmpfs" || utils.CleanPath(m.Destination) == "/dev" {
		flags &= ^unix.MS_RDONLY
	}

	// Because the destination is inside a container path which might be
	// mutating underneath us, we verify that we are actually going to mount

Review comment (suggestion):
Move these flags to a const, i.e.
```go
// Check if the source mount has any of these flags...
const retryFlags = unix.MS_NODEV|unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NOATIME|unix.MS_RELATIME|unix.MS_STRICTATIME|unix.MS_NODIRATIME
...
// ... and retry the mount with these flags set.
flags |= uintptr(s.Flags & retryFlags)

Code after:
// remountReadonly will remount an existing mount point and ensure that it is read-only.
func remountReadonly(m *configs.Mount) error {
	var (
		dest  = m.Destination
		flags = m.Flags
	)
	for i := 0; i < 5; i++ {
		// There is a special case in the kernel for
		// MS_REMOUNT | MS_BIND, which allows us to change only the
		// flags even as an unprivileged user (i.e. user namespace)
		// assuming we don't drop any security related flags (nodev,
		// nosuid, etc.). So, let's use that case so that we can do
		// this re-mount without failing in a userns.
		flags |= unix.MS_REMOUNT | unix.MS_BIND | unix.MS_RDONLY
		if err := mount("", dest, "", uintptr(flags), ""); err != nil {
			if errors.Is(err, unix.EBUSY) {
				time.Sleep(100 * time.Millisecond)
				continue
			}
			return err
		}
		return nil
	}
	return fmt.Errorf("unable to mount %s as readonly max retries reached", dest)
}

// maskPath masks the top of the specified path inside a container to avoid
// security issues from processes reading information from non-namespace aware
// mounts ( proc/kcore ).
// For files, maskPath bind mounts /dev/null over the top of the specified path.
// For directories, maskPath mounts read-only tmpfs over the top of the specified path.
func maskPath(path string, mountLabel string) error {
	if err := mount("/dev/null", path, "", unix.MS_BIND, ""); err != nil && !errors.Is(err, os.ErrNotExist) {
		if errors.Is(err, unix.ENOTDIR) {
			return mount("tmpfs", path, "tmpfs", unix.MS_RDONLY, label.FormatMountLabel("", mountLabel))
		}
		return err
	}
	return nil
}

// writeSystemProperty writes the value to a path under /proc/sys as determined from the key.
// For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward.
func writeSystemProperty(key, value string) error {
	keyPath := strings.Replace(key, ".", "/", -1)
	return os.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0o644)
}

func remount(m mountEntry, rootfs string, noMountFallback bool) error {
	return utils.WithProcfd(rootfs, m.Destination, func(dstFD string) error {
		flags := uintptr(m.Flags | unix.MS_REMOUNT)