Compare commits

...

8 Commits

Author SHA1 Message Date
371dd5b938
nix: create current-system symlink
All checks were successful
Test / Create distribution (push) Successful in 20s
Release / Create release (push) Successful in 27s
Test / Fpkg (push) Successful in 35s
Test / Fortify (push) Successful in 40s
Test / Data race detector (push) Successful in 40s
Test / Flake checks (push) Successful in 58s
This is copied at runtime because it appears to be impossible to obtain this path in nix.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-26 02:06:11 +09:00
4836d570ae
test: raise long timeout to 15 seconds
All checks were successful
Test / Create distribution (push) Successful in 26s
Test / Fpkg (push) Successful in 34s
Test / Fortify (push) Successful in 2m20s
Test / Data race detector (push) Successful in 3m4s
Test / Flake checks (push) Successful in 57s
The race detector really slows down container tooling.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-26 01:59:05 +09:00
985f9442e6
sandbox: copy symlink with magic prefix
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Fortify (push) Successful in 2m39s
Test / Fpkg (push) Successful in 3m31s
Test / Data race detector (push) Successful in 2m40s
Test / Flake checks (push) Successful in 59s
This does not dereference the symlink, but only reads one level of it. This is useful for symlink targets that are not yet known at the time the configuration is emitted.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-26 01:42:39 +09:00
67eb28466d
nix: create opengl-driver symlink
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Fpkg (push) Successful in 33s
Test / Fortify (push) Successful in 2m18s
Test / Data race detector (push) Successful in 3m3s
Test / Flake checks (push) Successful in 53s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-25 20:52:20 +09:00
c326c3f97d
fst/sandbox: do not create /etc in advance
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Fortify (push) Successful in 2m43s
Test / Fpkg (push) Successful in 3m36s
Test / Data race detector (push) Successful in 4m31s
Test / Flake checks (push) Successful in 56s
This is now handled by the setup op. This also gets rid of the hardcoded /etc path.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-25 20:00:34 +09:00
971c79bb80
sandbox: remove hardcoded parent perm
All checks were successful
Test / Create distribution (push) Successful in 27s
Test / Fortify (push) Successful in 2m43s
Test / Fpkg (push) Successful in 3m41s
Test / Data race detector (push) Successful in 4m32s
Test / Flake checks (push) Successful in 59s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-25 19:49:51 +09:00
f86d868274
sandbox: wrap error with its own text message
All checks were successful
Test / Create distribution (push) Successful in 26s
Test / Fortify (push) Successful in 2m40s
Test / Fpkg (push) Successful in 3m33s
Test / Data race detector (push) Successful in 4m24s
Test / Flake checks (push) Successful in 57s
PathError has a pretty good text message, many of them are wrapped with its own text message. This change adds a function to do just that to improve readability.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-25 19:42:20 +09:00
33940265a6
sandbox: do not ensure symlink target
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Fortify (push) Successful in 2m40s
Test / Fpkg (push) Successful in 3m29s
Test / Data race detector (push) Successful in 4m31s
Test / Flake checks (push) Successful in 1m4s
This masks EEXIST on target and might clobber filesystems and lead to other confusing behaviour. Create its parent instead.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-03-25 19:30:53 +09:00
14 changed files with 110 additions and 71 deletions

View File

@ -245,9 +245,7 @@ func (s *SandboxConfig) ToContainer(sys SandboxSys, uid, gid *int) (*sandbox.Par
if etcPath == "" {
etcPath = "/etc"
}
container.
Bind(etcPath, Tmp+"/etc", 0).
Mkdir("/etc", 0700)
container.Bind(etcPath, Tmp+"/etc", 0)
// link host /etc contents to prevent dropping passwd/group bind mounts
if d, err := sys.ReadDir(etcPath); err != nil {

View File

@ -124,7 +124,6 @@ var testCasesNixos = []sealTestCase{
Bind("/run/opengl-driver", "/run/opengl-driver", 0).
Bind("/dev/dri", "/dev/dri", sandbox.BindDevice|sandbox.BindWritable|sandbox.BindOptional).
Bind("/etc", fst.Tmp+"/etc", 0).
Mkdir("/etc", 0700).
Link(fst.Tmp+"/etc/alsa", "/etc/alsa").
Link(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
Link(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").

View File

@ -67,7 +67,6 @@ var testCasesPd = []sealTestCase{
Tmpfs("/run/user/1971", 8192, 0755).
Tmpfs("/run/dbus", 8192, 0755).
Bind("/etc", fst.Tmp+"/etc", 0).
Mkdir("/etc", 0700).
Link(fst.Tmp+"/etc/alsa", "/etc/alsa").
Link(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
Link(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
@ -288,7 +287,6 @@ var testCasesPd = []sealTestCase{
Tmpfs("/run/user/1971", 8192, 0755).
Tmpfs("/run/dbus", 8192, 0755).
Bind("/etc", fst.Tmp+"/etc", 0).
Mkdir("/etc", 0700).
Link(fst.Tmp+"/etc/alsa", "/etc/alsa").
Link(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
Link(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").

View File

@ -84,6 +84,8 @@ in
command = if app.command == null then app.name else app.command;
script = if app.script == null then ("exec " + command + " $@") else app.script;
enablements = with app.capability; (if wayland then 1 else 0) + (if x11 then 2 else 0) + (if dbus then 4 else 0) + (if pulse then 8 else 0);
isGraphical = if app.gpu != null then app.gpu else app.capability.wayland || app.capability.x11;
conf = {
inherit (app) id;
path = pkgs.writeScript "${app.name}-start" ''
@ -91,6 +93,7 @@ in
${script}
'';
args = [ "${app.name}-start" ];
confinement = {
app_id = aid;
inherit (app) groups;
@ -108,6 +111,7 @@ in
;
map_real_uid = app.mapRealUid;
direct_wayland = app.insecureWayland;
filesystem =
let
bind = src: { inherit src; };
@ -124,7 +128,6 @@ in
(mustBind "/bin")
(mustBind "/usr/bin")
(mustBind "/nix/store")
(mustBind "/run/current-system")
(bind "/sys/block")
(bind "/sys/bus")
(bind "/sys/class")
@ -135,8 +138,7 @@ in
(mustBind "/nix/var")
(bind "/var/db/nix-channels")
]
++ optionals (if app.gpu != null then app.gpu else app.capability.wayland || app.capability.x11) [
(bind "/run/opengl-driver")
++ optionals isGraphical [
(devBind "/dev/dri")
(devBind "/dev/nvidiactl")
(devBind "/dev/nvidia-modeset")
@ -147,7 +149,30 @@ in
++ app.extraPaths;
auto_etc = true;
cover = [ "/var/run/nscd" ];
symlink =
[
[
"*/run/current-system"
"/run/current-system"
]
]
++ optionals (isGraphical && config.hardware.graphics.enable) (
[
[
config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver"."L+".argument
"/run/opengl-driver"
]
]
++ optionals (app.multiarch && config.hardware.graphics.enable32Bit) [
[
config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver-32"."L+".argument
/run/opengl-driver-32
]
]
);
};
inherit enablements;
inherit (dbusConfig) session_bus system_bus;
};

View File

@ -96,6 +96,9 @@ type (
*Ops
// Extra seccomp options.
Seccomp seccomp.SyscallOpts
// Permission bits of newly created parent directories.
// The zero value is interpreted as 0755.
ParentPerm os.FileMode
Flags HardeningFlags
}

View File

@ -68,6 +68,9 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
if params.Ops == nil {
log.Fatal("invalid setup parameters")
}
if params.ParentPerm == 0 {
params.ParentPerm = 0755
}
setVerbose(params.Verbose)
msg.Verbose("received setup parameters")

View File

@ -25,7 +25,7 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
var targetFinal string
if v, err := filepath.EvalSymlinks(target); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else {
targetFinal = v
if targetFinal != target {
@ -45,7 +45,7 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
fmt.Sprintf("cannot open %q:", targetFinal))
}
if v, err := os.Readlink(p.fd(destFd)); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else if err = syscall.Close(destFd); err != nil {
return wrapErrSuffix(err,
fmt.Sprintf("cannot close %q:", targetFinal))
@ -102,7 +102,7 @@ func remountWithFlags(n *vfs.MountInfoNode, mf uintptr) error {
func mountTmpfs(fsname, name string, size int, perm os.FileMode) error {
target := toSysroot(name)
if err := os.MkdirAll(target, parentPerm(perm)); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
opt := fmt.Sprintf("mode=%#o", perm)
if size > 0 {

View File

@ -17,3 +17,10 @@ func wrapErrSuffix(err error, a ...any) error {
}
return msg.WrapErr(err, append(a, err)...)
}
func wrapErrSelf(err error) error {
if err == nil {
return nil
}
return msg.WrapErr(err, err.Error())
}

View File

@ -32,16 +32,16 @@ func toHost(name string) string {
func createFile(name string, perm, pperm os.FileMode, content []byte) error {
if err := os.MkdirAll(path.Dir(name), pperm); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
f, err := os.OpenFile(name, syscall.O_CREAT|syscall.O_EXCL|syscall.O_WRONLY, perm)
if err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
if content != nil {
_, err = f.Write(content)
if err != nil {
err = msg.WrapErr(err, err.Error())
err = wrapErrSelf(err)
}
}
return errors.Join(f.Close(), err)
@ -78,7 +78,7 @@ func (p *procPaths) stdout() string { return p.self + "/fd/1" }
func (p *procPaths) fd(fd int) string { return p.self + "/fd/" + strconv.Itoa(fd) }
func (p *procPaths) mountinfo(f func(d *vfs.MountInfoDecoder) error) error {
if r, err := os.Open(p.self + "/mountinfo"); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else {
d := vfs.NewMountInfoDecoder(r)
err0 := f(d)

View File

@ -8,6 +8,7 @@ import (
"path"
"path/filepath"
"slices"
"strings"
"syscall"
"unsafe"
)
@ -38,7 +39,7 @@ func (b *BindMount) early(*Params) error {
b.SourceFinal = "\x00"
return nil
}
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else {
b.SourceFinal = v
return nil
@ -65,10 +66,10 @@ func (b *BindMount) apply(*Params) error {
// this perm value emulates bwrap behaviour as it clears bits from 0755 based on
// op->perms which is never set for any bind setup op so always results in 0700
if fi, err := os.Stat(source); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else if fi.IsDir() {
if err = os.MkdirAll(target, 0700); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
} else if err = ensureFile(target, 0444, 0700); err != nil {
return err
@ -104,7 +105,7 @@ func init() { gob.Register(new(MountProc)) }
type MountProc string
func (p MountProc) early(*Params) error { return nil }
func (p MountProc) apply(*Params) error {
func (p MountProc) apply(params *Params) error {
v := string(p)
if !path.IsAbs(v) {
@ -113,8 +114,8 @@ func (p MountProc) apply(*Params) error {
}
target := toSysroot(v)
if err := os.MkdirAll(target, 0755); err != nil {
return msg.WrapErr(err, err.Error())
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
return wrapErrSelf(err)
}
return wrapErrSuffix(syscall.Mount("proc", target, "proc",
syscall.MS_NOSUID|syscall.MS_NOEXEC|syscall.MS_NODEV, ""),
@ -144,13 +145,13 @@ func (d MountDev) apply(params *Params) error {
}
target := toSysroot(v)
if err := mountTmpfs("devtmpfs", v, 0, 0755); err != nil {
if err := mountTmpfs("devtmpfs", v, 0, params.ParentPerm); err != nil {
return err
}
for _, name := range []string{"null", "zero", "full", "random", "urandom", "tty"} {
targetPath := toSysroot(path.Join(v, name))
if err := ensureFile(targetPath, 0444, 0755); err != nil {
if err := ensureFile(targetPath, 0444, params.ParentPerm); err != nil {
return err
}
if err := hostProc.bindMount(
@ -167,7 +168,7 @@ func (d MountDev) apply(params *Params) error {
"/proc/self/fd/"+string(rune(i+'0')),
path.Join(target, name),
); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
}
for _, pair := range [][2]string{
@ -176,14 +177,14 @@ func (d MountDev) apply(params *Params) error {
{"pts/ptmx", "ptmx"},
} {
if err := os.Symlink(pair[0], path.Join(target, pair[1])); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
}
devPtsPath := path.Join(target, "pts")
for _, name := range []string{path.Join(target, "shm"), devPtsPath} {
if err := os.Mkdir(name, 0755); err != nil {
return msg.WrapErr(err, err.Error())
if err := os.Mkdir(name, params.ParentPerm); err != nil {
return wrapErrSelf(err)
}
}
@ -201,11 +202,11 @@ func (d MountDev) apply(params *Params) error {
uintptr(unsafe.Pointer(&buf[0])),
); errno == 0 {
consolePath := toSysroot(path.Join(v, "console"))
if err := ensureFile(consolePath, 0444, 0755); err != nil {
if err := ensureFile(consolePath, 0444, params.ParentPerm); err != nil {
return err
}
if name, err := os.Readlink(hostProc.stdout()); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else if err = hostProc.bindMount(
toHost(name),
consolePath,
@ -234,7 +235,7 @@ func init() { gob.Register(new(MountMqueue)) }
type MountMqueue string
func (m MountMqueue) early(*Params) error { return nil }
func (m MountMqueue) apply(*Params) error {
func (m MountMqueue) apply(params *Params) error {
v := string(m)
if !path.IsAbs(v) {
@ -243,8 +244,8 @@ func (m MountMqueue) apply(*Params) error {
}
target := toSysroot(v)
if err := os.MkdirAll(target, 0755); err != nil {
return msg.WrapErr(err, err.Error())
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
return wrapErrSelf(err)
}
return wrapErrSuffix(syscall.Mount("mqueue", target, "mqueue",
syscall.MS_NOSUID|syscall.MS_NOEXEC|syscall.MS_NODEV, ""),
@ -294,8 +295,22 @@ func init() { gob.Register(new(Symlink)) }
// Symlink creates a symlink in the container filesystem.
type Symlink [2]string
func (l *Symlink) early(*Params) error { return nil }
func (l *Symlink) apply(*Params) error {
func (l *Symlink) early(*Params) error {
if strings.HasPrefix(l[0], "*") {
l[0] = l[0][1:]
if !path.IsAbs(l[0]) {
return msg.WrapErr(syscall.EBADE,
fmt.Sprintf("path %q is not absolute", l[0]))
}
if name, err := os.Readlink(l[0]); err != nil {
return wrapErrSelf(err)
} else {
l[0] = name
}
}
return nil
}
func (l *Symlink) apply(params *Params) error {
// symlink target is an arbitrary path value, so only validate link name here
if !path.IsAbs(l[1]) {
return msg.WrapErr(syscall.EBADE,
@ -303,14 +318,11 @@ func (l *Symlink) apply(*Params) error {
}
target := toSysroot(l[1])
if err := ensureFile(target, 0444, 0755); err != nil {
return err
}
if err := os.Remove(target); err != nil {
return msg.WrapErr(err, err.Error())
if err := os.MkdirAll(path.Dir(target), params.ParentPerm); err != nil {
return wrapErrSelf(err)
}
if err := os.Symlink(l[0], target); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
return nil
}
@ -339,7 +351,7 @@ func (m *Mkdir) apply(*Params) error {
}
if err := os.MkdirAll(toSysroot(m.Path), m.Perm); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
return nil
}
@ -361,7 +373,7 @@ type Tmpfile struct {
}
func (t *Tmpfile) early(*Params) error { return nil }
func (t *Tmpfile) apply(*Params) error {
func (t *Tmpfile) apply(params *Params) error {
if !path.IsAbs(t.Path) {
return msg.WrapErr(syscall.EBADE,
fmt.Sprintf("path %q is not absolute", t.Path))
@ -369,7 +381,7 @@ func (t *Tmpfile) apply(*Params) error {
var tmpPath string
if f, err := os.CreateTemp("/", "tmp.*"); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
} else if _, err = f.Write(t.Data); err != nil {
return wrapErrSuffix(err,
"cannot write to intermediate file:")
@ -381,7 +393,7 @@ func (t *Tmpfile) apply(*Params) error {
}
target := toSysroot(t.Path)
if err := ensureFile(target, 0444, 0755); err != nil {
if err := ensureFile(target, 0444, params.ParentPerm); err != nil {
return err
} else if err = hostProc.bindMount(
tmpPath,
@ -391,7 +403,7 @@ func (t *Tmpfile) apply(*Params) error {
); err != nil {
return err
} else if err = os.Remove(tmpPath); err != nil {
return msg.WrapErr(err, err.Error())
return wrapErrSelf(err)
}
return nil
}

View File

@ -39,7 +39,7 @@
urandom = fs "42001b6" null null;
zero = fs "42001b6" null null;
} null;
etc = fs "800001c0" {
etc = fs "800001ed" {
".clean" = fs "80001ff" null null;
".updated" = fs "80001ff" null null;
"NIXOS" = fs "80001ff" null null;
@ -111,9 +111,9 @@
} null;
nix = fs "800001c0" { store = fs "801001fd" null null; } null;
proc = fs "8000016d" null null;
run = fs "800001c0" {
current-system = fs "8000016d" null null;
opengl-driver = fs "8000016d" null null;
run = fs "800001ed" {
current-system = fs "80001ff" null null;
opengl-driver = fs "80001ff" null null;
user = fs "800001ed" {
"1000" = fs "800001ed" {
bus = fs "10001fd" null null;
@ -195,13 +195,11 @@
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent ignore "/run/current-system" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent "/block" "/sys/block" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/bus" "/sys/bus" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/class" "/sys/class" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/dev" "/sys/dev" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000003,gid=1000003")

View File

@ -39,7 +39,7 @@
urandom = fs "42001b6" null null;
zero = fs "42001b6" null null;
} null;
etc = fs "800001c0" {
etc = fs "800001ed" {
".clean" = fs "80001ff" null null;
".updated" = fs "80001ff" null null;
"NIXOS" = fs "80001ff" null null;
@ -111,9 +111,9 @@
} null;
nix = fs "800001c0" { store = fs "801001fd" null null; } null;
proc = fs "8000016d" null null;
run = fs "800001c0" {
current-system = fs "8000016d" null null;
opengl-driver = fs "8000016d" null null;
run = fs "800001ed" {
current-system = fs "80001ff" null null;
opengl-driver = fs "80001ff" null null;
user = fs "800001ed" {
"65534" = fs "800001ed" {
bus = fs "10001fd" null null;
@ -195,13 +195,11 @@
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent ignore "/run/current-system" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent "/block" "/sys/block" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/bus" "/sys/bus" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/class" "/sys/class" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/dev" "/sys/dev" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000001,gid=1000001")

View File

@ -40,7 +40,7 @@
urandom = fs "42001b6" null null;
zero = fs "42001b6" null null;
} null;
etc = fs "800001c0" {
etc = fs "800001ed" {
".clean" = fs "80001ff" null null;
".updated" = fs "80001ff" null null;
"NIXOS" = fs "80001ff" null null;
@ -112,9 +112,9 @@
} null;
nix = fs "800001c0" { store = fs "801001fd" null null; } null;
proc = fs "8000016d" null null;
run = fs "800001c0" {
current-system = fs "8000016d" null null;
opengl-driver = fs "8000016d" null null;
run = fs "800001ed" {
current-system = fs "80001ff" null null;
opengl-driver = fs "80001ff" null null;
user = fs "800001ed" {
"65534" = fs "800001ed" {
bus = fs "10001fd" null null;
@ -197,13 +197,11 @@
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent ignore "/run/current-system" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent "/block" "/sys/block" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/bus" "/sys/bus" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/class" "/sys/class" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/dev" "/sys/dev" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000002,gid=1000002")

View File

@ -141,7 +141,7 @@ def silent_output_interrupt(flags):
wait_for_window("alice@machine")
# aid 0 does not have home-manager
machine.send_chars(f"exec fortify run {flags}-a 0 sh -c 'export PATH=/run/current-system/sw/bin:$PATH && touch /tmp/pd-silent-ready && sleep infinity' &>/tmp/pd-silent\n")
machine.wait_for_file("/tmp/fortify.1000/tmpdir/0/pd-silent-ready", timeout=10)
machine.wait_for_file("/tmp/fortify.1000/tmpdir/0/pd-silent-ready", timeout=15)
machine.succeed("rm /tmp/fortify.1000/tmpdir/0/pd-silent-ready")
machine.send_key("ctrl-c")
machine.wait_until_fails("pgrep foot", timeout=5)
@ -172,18 +172,18 @@ fortify("-v run --wayland -X --dbus --pulse -u p1 foot && touch /tmp/p1-exit-ok"
wait_for_window("p1@machine")
print(machine.succeed("getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep 1000000"))
machine.send_chars("exit\n")
machine.wait_for_file("/tmp/p1-exit-ok", timeout=10)
machine.wait_for_file("/tmp/p1-exit-ok", timeout=15)
# Verify acl is kept alive:
print(machine.succeed("getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep 1000000"))
machine.send_chars("exit\n")
machine.wait_for_file("/tmp/p0-exit-ok", timeout=10)
machine.wait_for_file("/tmp/p0-exit-ok", timeout=15)
machine.fail("getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep 1000000")
# Start app (foot) with Wayland enablement:
swaymsg("exec ne-foot")
wait_for_window(f"u0_a{aid(0)}@machine")
machine.send_chars("clear; wayland-info && touch /tmp/client-ok\n")
machine.wait_for_file(tmpdir_path(0, "client-ok"), timeout=10)
machine.wait_for_file(tmpdir_path(0, "client-ok"), timeout=15)
collect_state_ui("foot_wayland")
check_state("ne-foot", 1)
# Verify acl on XDG_RUNTIME_DIR:
@ -197,7 +197,7 @@ machine.wait_until_fails(f"getfacl --absolute-names --omit-header --numeric /run
swaymsg("exec foot $SHELL -c '(ne-foot) & sleep 1 && fortify show $(fortify ps --short) && touch /tmp/ps-show-ok && cat'")
wait_for_window(f"u0_a{aid(0)}@machine")
machine.send_chars("clear; wayland-info && touch /tmp/term-ok\n")
machine.wait_for_file(tmpdir_path(0, "term-ok"), timeout=10)
machine.wait_for_file(tmpdir_path(0, "term-ok"), timeout=15)
machine.wait_for_file("/tmp/ps-show-ok", timeout=5)
collect_state_ui("foot_wayland_term")
check_state("ne-foot", 1)
@ -220,7 +220,7 @@ machine.wait_until_fails("pgrep foot", timeout=5)
swaymsg("exec x11-alacritty")
wait_for_window(f"u0_a{aid(2)}@machine")
machine.send_chars("clear; glinfo && touch /tmp/x11-ok\n")
machine.wait_for_file(tmpdir_path(2, "x11-ok"), timeout=10)
machine.wait_for_file(tmpdir_path(2, "x11-ok"), timeout=15)
collect_state_ui("alacritty_x11")
check_state("x11-alacritty", 2)
machine.send_chars("exit\n")
@ -231,7 +231,7 @@ swaymsg("exec da-foot")
wait_for_window(f"u0_a{aid(3)}@machine")
machine.send_chars("clear; wayland-info && touch /tmp/direct-ok\n")
collect_state_ui("foot_direct")
machine.wait_for_file(tmpdir_path(3, "direct-ok"), timeout=10)
machine.wait_for_file(tmpdir_path(3, "direct-ok"), timeout=15)
check_state("da-foot", 1)
# Verify acl on XDG_RUNTIME_DIR:
print(machine.succeed(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {aid(3) + 1000000}"))