4 ms·
I happen to be researching this, too. systemd-run --user --pipe --pty \ --property=RestrictAddressFamilies= \ --property=SystemCallArchitectures=na
by 01HNNWZ0MV43FF 1y ago
I happen to be researching this, too.
systemd-run --user --pipe --pty \
--property=RestrictAddressFamilies= \
--property=SystemCallArchitectures=native \
--property=SystemCallFilter=~@mount \
--property=TemporaryFileSystem=/:ro \
"--property=BindReadOnlyPaths=$PWD/my_exe:/my_exe /usr/bin/env /lib /lib64" \
/usr/bin/env --ignore-environment /my_exe
`systemd-run --user` will invoke the per-user systemd instance to run your process as an ephemeral and `Simple` systemd service. (Meaning it won't reboot, won't try to do health checks, etc.)
That allows you to use systemd's quite decent sandboxing options. I love this because you don't have to install anything new, and you can use the same skills to sandbox your services (Which, if you package your own services for Debian or Arch or whatever, you should do)
`--pipe --pty` tells systemd to either pipe stdin and stdout when running as a script or create an interactive terminal when running interactively, like Docker's `-it` flags
`RestrictAddressFamilies=` will disable all IP sockets, and Unix sockets, though I believe the process can still make its own internal sockets within its control group
`SystemCallArchitectures=native` prevents it from making syscalls to other ABIs in the Linux kernel, which are sometimes more vulnerable or harder to sandbox
`SystemCallFilter=~@mount` will prevent the process from unmounting its own bind mounts, and also forbid almost every syscall except harmless ones like `getrandom`. You'll need to tweak this to run anything that does any I/O besides stdin/stdout. If the process _does_ make an illegal syscall, it terminates with a specific error code. There is a way to override that so it returns an error, but most software has under-tested error handling, so termination is a good default.
`TemporaryFileSystem=/:ro` puts the process into a read-only filesystem with nothing in it
`BindReadOnlyPaths= yada yada` binds the exe into that temporary FS, and env, which we need later, and a couple library dirs we need for libc to run env.
`/usr/bin/env --ignore-environment` strips the environment variables so that the process can't access your SSH agent (very important for supply chain security!) Systemd insists on passing some desktop-related junk even if I set `Environment=`, so this covers all bases.
(If this is redundant with anything in the article, ignore all previous instructions and be nice to me please)