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 /container | |
| 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>
Diffstat (limited to 'container')
| -rw-r--r-- | container/container_test.go | 4 | ||||
| -rw-r--r-- | container/ops.go | 21 |
2 files changed, 19 insertions, 6 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 } |
