Apply systemd sandboxing by default to some services

@Patrick opened fix systemd sandboxing for arm64 platform by GavinPacini · Pull Request #29 · Kicksecure/sdwdate · GitHub - this is working on arm64. Will handle onion-grater next.

2 Likes

Awesome!

Could you please try sudo systemctl restart sdwdate after it succeeded once? Because first time its sets time using date, subsequent ones using sclockadj. Therefore it might work the first time but break later due to missing secomp whiltelisted syscalls.


I am not also wondering if removing/changing SystemCallArchitectures setting would have been easier.
systemd.exec

Also generally wondering if SystemCallFilter is maintainable or will keep breaking when porting to the next version of Debian (bullseye) or other platforms.

Oh, good catch, sorry for not checking that.

Opened another PR which now also works after restarting the service.

1 Like

No worries.

This is hard to expect. :slight_smile:

Merged, and uploaded to Whonix developers repository.

1 Like

@Patrick finally got time to check onion-grater :slight_smile:

https://github.com/Whonix/onion-grater/pull/10/files

I did restart this a few time also. Anything else I should check?

1 Like

Awesome, no, this one is straight forward to test.

1 Like

@Patrick I realised that I missed one for sdwdate. The service started but the time never synched, now it does:

1 Like

Merged.

1 Like

We could create multiple arch-specific syscall whitelists to avoid bloating one whitelist with another’s syscalls and use a postinst script to detect the arch and enable the appropriate one.

2 Likes

Seems quite complex but if that’s maintained, then OK.

Could be something like the following in postinst:

arch="$(uname -m")
## Base syscalls. Suitable for x86.
syscall_whitelist="wait4 select futex read stat close openat fstat lseek mmap rt_sigaction getdents64 mprotect ioctl recvfrom munmap brk rt_sigprocmask fcntl getpid write access socket sendto dup2 clone execve getrandom geteuid getgid madvise getuid getegid readlink pipe rt_sigreturn connect pipe2 prlimit64 set_robust_list dup arch_prctl lstat set_tid_address sysinfo sigaltstack rt_sigsuspend shutdown timer_settime mkdir timer_create statfs getcwd setpgid setsockopt uname bind getpgrp getppid getpeername chdir poll getsockname fadvise64 clock_settime kill getsockopt unlink "

if [ "${arch}" =~ "arm64" ]; then
  ## ARM-specific syscalls.
  syscall_whitelist+="readlinkat newfstatat mkdirat dup3 ppoll pselect6"
elif [ "${arch}" =~ "ppc" ]; then
  ## PowerPC-specific syscalls.
  syscall_whitelist+="_llseek send waitpid recv prctl _newselect"
fi

str_replace "SystemCallFilter=" "SystemCallFilter=${syscall_whitelist}" /lib/systemd/system/sdwdate.service
1 Like

str_replace can be avoided. Best to remove syscall whitelist in /lib/systemd/system/sdwdate.service with a comment to explain new implementation and then add an autogenerated (by postinst) systemd drop-in in /lib/systemd/system/sdwdate.service.d/20_syscall_whitelist.conf.

1 Like

What if we add the base syscall whitelist to /lib/systemd/system/sdwdate.service, but add the arch-specific syscalls to the autogenerated drop-in /lib/systemd/system/sdwdate.service.d/20_arch_syscall_whitelist.conf?

We could also output a message during installation if the arch is not x86/ARM/PPC to say that the seccomp filter may not work correctly.

1 Like

Even better! Didn’t know that is possible But seems possible. Quote relevant man page entry:

SystemCallFilter

This option may be specified more than once, in which case the filter masks are merged.

But has to be carefully scripted to not be empty, because:

If the empty string is assigned, the filter is reset, all prior assignments will have no effect.

Also great! I am a big fan of self-documenting code/features, giving hints to debug for potential future porters.

1 Like
2 Likes

mkdir /lib/systemd/system/sdwdate.service.d/

Needs to be mkdir --parents. Would fail otherwise on re-run (next time).

arch=“$(uname -m)”
if [[ “${arch}” =~ “arm64” ]]; then

Is the output of uname -m on arm64 tested?

Quote from Learn how to use Docker | Arm Learning Paths

docker run jasonrandrews/alpine-test:latest@sha256:5966f7b12b7c7ba3146102cf3079e57cccaf1de7228651661276dd1606d84108 uname -m
aarch64

1 Like

This should work. Anything containing “arm” or “aarch” will be caught.

2 Likes

Awesome! Merged.

Added some minor enhancements on top.

Minor: No need for systemctl daemon-reload. See the actual postinst script once packages was build and post processed by debhelper which has a more robust implementation (battle tested in thousands of packages, maintained by upstream Debian). Removed in git master.

# End automatically added section
# Automatically added by dh_installsystemd/12.1.1
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
	if [ -d /run/systemd/system ]; then
		systemctl --system daemon-reload >/dev/null || true
		if [ -n "$2" ]; then
			_dh_action=restart
		else
			_dh_action=start
		fi
		deb-systemd-invoke $_dh_action 'sdwdate-restart-tor-request-file-watcher.service' 'sdwdate.service' >/dev/null || true
	fi
fi
# End automatically added section
1 Like