diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-08-03 19:18:53 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-08-03 19:18:53 +0900 |
| commit | 38245559dca0833dc078b982d59490eee53e168c (patch) | |
| tree | ffe415b5db8fd21b3a75600428f167eeef018591 | |
| parent | 7b416d47dcb830aab5daa432cf79af5f8bbacaef (diff) | |
container/ops: mount dev readonly
There is usually no good reason to write to /dev. This however doesn't work in internal/app because FilesystemConfig supplied by ContainerConfig might add entries to /dev, so internal/app follows DevWritable with Remount instead.
Signed-off-by: Ophestra <cat@gensokyo.uk>
| -rw-r--r-- | container/container_test.go | 4 | ||||
| -rw-r--r-- | container/ops.go | 21 | ||||
| -rw-r--r-- | internal/app/app_nixos_linux_test.go | 3 | ||||
| -rw-r--r-- | internal/app/app_pd_linux_test.go | 6 | ||||
| -rw-r--r-- | internal/app/container_linux.go | 7 | ||||
| -rw-r--r-- | test/sandbox/case/mapuid.nix | 2 | ||||
| -rw-r--r-- | test/sandbox/case/pd.nix | 2 | ||||
| -rw-r--r-- | test/sandbox/case/pdlike.nix | 2 | ||||
| -rw-r--r-- | test/sandbox/case/preset.nix | 2 | ||||
| -rw-r--r-- | test/sandbox/case/tty.nix | 2 |
10 files changed, 36 insertions, 15 deletions
diff --git a/container/container_test.go b/container/container_test.go index 861a4dbd..2db2c08e 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -74,7 +74,7 @@ var containerTestCases = []struct { new(container.Ops). Dev("/dev", true), []*vfs.MountInfoEntry{ - ent("/", "/dev", "rw,nosuid,nodev,relatime", "tmpfs", "devtmpfs", ignore), + ent("/", "/dev", "ro,nosuid,nodev,relatime", "tmpfs", "devtmpfs", ignore), ent("/null", "/dev/null", "rw,nosuid", "devtmpfs", "devtmpfs", ignore), ent("/zero", "/dev/zero", "rw,nosuid", "devtmpfs", "devtmpfs", ignore), ent("/full", "/dev/full", "rw,nosuid", "devtmpfs", "devtmpfs", ignore), @@ -90,7 +90,7 @@ var containerTestCases = []struct { new(container.Ops). Dev("/dev", false), []*vfs.MountInfoEntry{ - ent("/", "/dev", "rw,nosuid,nodev,relatime", "tmpfs", "devtmpfs", ignore), + ent("/", "/dev", "ro,nosuid,nodev,relatime", "tmpfs", "devtmpfs", ignore), ent("/null", "/dev/null", "rw,nosuid", "devtmpfs", "devtmpfs", ignore), ent("/zero", "/dev/zero", "rw,nosuid", "devtmpfs", "devtmpfs", ignore), ent("/full", "/dev/full", "rw,nosuid", "devtmpfs", "devtmpfs", ignore), diff --git a/container/ops.go b/container/ops.go index d64235fc..e3eb45f8 100644 --- a/container/ops.go +++ b/container/ops.go @@ -181,13 +181,21 @@ func init() { gob.Register(new(MountDevOp)) } // Dev appends an [Op] that mounts a subset of host /dev. func (f *Ops) Dev(dest string, mqueue bool) *Ops { - *f = append(*f, &MountDevOp{dest, mqueue}) + *f = append(*f, &MountDevOp{dest, mqueue, false}) + return f +} + +// DevWritable appends an [Op] that mounts a writable subset of host /dev. +// There is usually no good reason to write to /dev, so this should always be followed by a [RemountOp]. +func (f *Ops) DevWritable(dest string, mqueue bool) *Ops { + *f = append(*f, &MountDevOp{dest, mqueue, true}) return f } type MountDevOp struct { Target string Mqueue bool + Write bool } func (d *MountDevOp) early(*Params) error { return nil } @@ -271,11 +279,16 @@ func (d *MountDevOp) apply(params *Params) error { if err := os.Mkdir(mqueueTarget, params.ParentPerm); err != nil { return wrapErrSelf(err) } - return wrapErrSuffix(Mount(SourceMqueue, mqueueTarget, FstypeMqueue, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString), - "cannot mount mqueue:") + if err := Mount(SourceMqueue, mqueueTarget, FstypeMqueue, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString); err != nil { + return wrapErrSuffix(err, "cannot mount mqueue:") + } } - return nil + if d.Write { + return nil + } + return wrapErrSuffix(hostProc.remount(target, MS_RDONLY), + fmt.Sprintf("cannot remount %q:", target)) } func (d *MountDevOp) Is(op Op) bool { vd, ok := op.(*MountDevOp); return ok && *d == *vd } diff --git a/internal/app/app_nixos_linux_test.go b/internal/app/app_nixos_linux_test.go index 2db3bf8a..a0da52c0 100644 --- a/internal/app/app_nixos_linux_test.go +++ b/internal/app/app_nixos_linux_test.go @@ -118,7 +118,7 @@ var testCasesNixos = []sealTestCase{ Ops: new(container.Ops). Proc("/proc"). Tmpfs(hst.Tmp, 4096, 0755). - Dev("/dev", true). + DevWritable("/dev", true). Bind("/bin", "/bin", 0). Bind("/usr/bin", "/usr/bin", 0). Bind("/nix/store", "/nix/store", 0). @@ -131,6 +131,7 @@ var testCasesNixos = []sealTestCase{ Bind("/run/opengl-driver", "/run/opengl-driver", 0). Bind("/dev/dri", "/dev/dri", container.BindDevice|container.BindWritable|container.BindOptional). Etc("/etc", "8e2c76b066dabe574cf073bdb46eb5c1"). + Remount("/dev", syscall.MS_RDONLY). Tmpfs("/run/user", 4096, 0755). Bind("/tmp/hakurei.1971/runtime/1", "/run/user/1971", container.BindWritable). Bind("/tmp/hakurei.1971/tmpdir/1", "/tmp", container.BindWritable). diff --git a/internal/app/app_pd_linux_test.go b/internal/app/app_pd_linux_test.go index b3d03f03..31a99f87 100644 --- a/internal/app/app_pd_linux_test.go +++ b/internal/app/app_pd_linux_test.go @@ -46,12 +46,13 @@ var testCasesPd = []sealTestCase{ Root("/", "4a450b6596d7bc15bd01780eb9a607ac", container.BindWritable). Proc("/proc"). Tmpfs(hst.Tmp, 4096, 0755). - Dev("/dev", true). + DevWritable("/dev", true). Bind("/dev/kvm", "/dev/kvm", container.BindWritable|container.BindDevice|container.BindOptional). Readonly("/var/run/nscd", 0755). Tmpfs("/run/user/1971", 8192, 0755). Tmpfs("/run/dbus", 8192, 0755). Etc("/etc", "4a450b6596d7bc15bd01780eb9a607ac"). + Remount("/dev", syscall.MS_RDONLY). Tmpfs("/run/user", 4096, 0755). Bind("/tmp/hakurei.1971/runtime/0", "/run/user/65534", container.BindWritable). Bind("/tmp/hakurei.1971/tmpdir/0", "/tmp", container.BindWritable). @@ -180,13 +181,14 @@ var testCasesPd = []sealTestCase{ Root("/", "ebf083d1b175911782d413369b64ce7c", container.BindWritable). Proc("/proc"). Tmpfs(hst.Tmp, 4096, 0755). - Dev("/dev", true). + DevWritable("/dev", true). Bind("/dev/dri", "/dev/dri", container.BindWritable|container.BindDevice|container.BindOptional). Bind("/dev/kvm", "/dev/kvm", container.BindWritable|container.BindDevice|container.BindOptional). Readonly("/var/run/nscd", 0755). Tmpfs("/run/user/1971", 8192, 0755). Tmpfs("/run/dbus", 8192, 0755). Etc("/etc", "ebf083d1b175911782d413369b64ce7c"). + Remount("/dev", syscall.MS_RDONLY). Tmpfs("/run/user", 4096, 0755). Bind("/tmp/hakurei.1971/runtime/9", "/run/user/65534", container.BindWritable). Bind("/tmp/hakurei.1971/tmpdir/9", "/tmp", container.BindWritable). diff --git a/internal/app/container_linux.go b/internal/app/container_linux.go index 35483018..a0c81d7a 100644 --- a/internal/app/container_linux.go +++ b/internal/app/container_linux.go @@ -85,7 +85,7 @@ func newContainer(s *hst.ContainerConfig, os sys.State, prefix string, uid, gid Tmpfs(hst.Tmp, 1<<12, 0755) if !s.Device { - params.Dev("/dev", true) + params.DevWritable("/dev", true) } else { params.Bind("/dev", "/dev", container.BindWritable|container.BindDevice) } @@ -239,6 +239,11 @@ func newContainer(s *hst.ContainerConfig, os sys.State, prefix string, uid, gid params.Etc(etcPath, prefix) } + // no more ContainerConfig paths beyond this point + if !s.Device { + params.Remount("/dev", syscall.MS_RDONLY) + } + return params, maps.Clone(s.Env), nil } diff --git a/test/sandbox/case/mapuid.nix b/test/sandbox/case/mapuid.nix index 945cfb49..fe5dad88 100644 --- a/test/sandbox/case/mapuid.nix +++ b/test/sandbox/case/mapuid.nix @@ -229,7 +229,7 @@ in (ent "/sysroot" "/" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000003,gid=1000003") (ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw") (ent "/" "/.hakurei" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000003,gid=1000003") - (ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000003,gid=1000003") + (ent "/" "/dev" "ro,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000003,gid=1000003") (ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) diff --git a/test/sandbox/case/pd.nix b/test/sandbox/case/pd.nix index 2b87290c..79400f53 100644 --- a/test/sandbox/case/pd.nix +++ b/test/sandbox/case/pd.nix @@ -170,7 +170,7 @@ (ent "/var" "/var" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw") (ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw") (ent "/" "/.hakurei" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000000,gid=1000000") - (ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000000,gid=1000000") + (ent "/" "/dev" "ro,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000000,gid=1000000") (ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) diff --git a/test/sandbox/case/pdlike.nix b/test/sandbox/case/pdlike.nix index febf1d39..4f0e71c4 100644 --- a/test/sandbox/case/pdlike.nix +++ b/test/sandbox/case/pdlike.nix @@ -229,7 +229,7 @@ in (ent "/sysroot" "/" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000005,gid=1000005") (ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw") (ent "/" "/.hakurei" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000005,gid=1000005") - (ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000005,gid=1000005") + (ent "/" "/dev" "ro,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000005,gid=1000005") (ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) diff --git a/test/sandbox/case/preset.nix b/test/sandbox/case/preset.nix index ecab2da0..60257ad0 100644 --- a/test/sandbox/case/preset.nix +++ b/test/sandbox/case/preset.nix @@ -228,7 +228,7 @@ in (ent "/sysroot" "/" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000001,gid=1000001") (ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw") (ent "/" "/.hakurei" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000001,gid=1000001") - (ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000001,gid=1000001") + (ent "/" "/dev" "ro,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000001,gid=1000001") (ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) diff --git a/test/sandbox/case/tty.nix b/test/sandbox/case/tty.nix index 689101fc..af2bfe98 100644 --- a/test/sandbox/case/tty.nix +++ b/test/sandbox/case/tty.nix @@ -230,7 +230,7 @@ in (ent "/sysroot" "/" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000002,gid=1000002") (ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw") (ent "/" "/.hakurei" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000002,gid=1000002") - (ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000002,gid=1000002") + (ent "/" "/dev" "ro,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000002,gid=1000002") (ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) (ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore) |
