Skip to content

Comparison of firejail and systemd's hardening options

rusty-snake edited this page Dec 15, 2024 · 8 revisions

TL;DR: These tables list equivalent options rather than equal options. Read their docs!
NOTE: Keep in mind that systemd is made to run and sandbox system-services while firejail has its focus on desktop programs. Therefore some options differ in their behavior, for example does firejail's private-tmp always bind-mount /tmp/.X11-unix, while systemd's PrivateTmp=yes does not. Always read the documentation of the option you use!

Filesystem

firejail systemd
always PrivateMounts=yes
blacklist /home
blacklist /root
blacklist /run/user
ProtectHome=yes
read-only /home
read-only /root
read-only /run/user
ProtectHome=read-only
Possible via tmpfs or whitelist ProtectHome=tmpfs
blacklist /boot InaccessiblePaths=/boot
chroot /foobaz RootDirectory=/foobaz
disable-mnt InaccessiblePaths=/mnt
InaccessiblePaths=/media
InaccessiblePaths=/run/mount(breaks systemd)
InaccessiblePaths=/run/media
mkdir Not Implemented
You can use RuntimeDirectory=, StateDirectory=, CacheDirectory=, LogsDirectory=, ConfigurationDirectory=.
You could write a mkdir@.service and use After=mkdir\x2fetc\x2fdnsmasq.service/After=mkdir@etc-dnsmasq.service.
mkfile Not Implemented
noexec /tmp NoExecPaths=/tmp
Not Implemented ExecPaths=/tmp/bin
private-bin bash,getenforce,python3 TemporaryFileSystem=/bin
TemporaryFileSystem=/usr/bin
TemporaryFileSystem=/sbin
TemporaryFileSystem=/usr/sbin
BindReadOnlyPaths=/bin/bash
BindReadOnlyPaths=/usr/bin/python3
BindReadOnlyPaths=/usr/sbin/getenforce
private-cwd WorkingDirectory=~
private-cwd /root WorkingDirectory=/root
private-etc ca-certificates,crypto-policies,nsswitch.conf,pki,resolv.conf,ssl TemporaryFileSystem=/etc
BindReadOnlyPaths=-/etc/ca-certificates
BindReadOnlyPaths=-/etc/crypto-policies
BindReadOnlyPaths=-/etc/nsswitch.conf
BindReadOnlyPaths=-/etc/pki
BindReadOnlyPaths=-/etc/resolv.conf
BindReadOnlyPaths=-/etc/ssl
private-lib Not Implemented
private-opt vivaldi TemporaryFileSystem=/opt
BindReadOnlyPaths=/opt/vivaldi
private-srv www TemporaryFileSystem=/srv
BindReadOnlyPaths=-/srv/www
private-tmp PrivateTmp=yes / PrivateTmp=disconnected
read-only /usr ProtectSystem=yes
read-only /usr
read-only /etc
ProtectSystem=full
read-only / ProtectSystem=strict
read-only /home
read-only /root
read-only /run/user
ProtectHome=read-only
read-only /sys/fs/cgroup ProtectControlGroups=yes
fixme ProtectControlGroups=private
fixme ProtectControlGroups=strict
read-only /proc/acpi
read-only /proc/fs
read-only /proc/irq
read-only /proc/latency_stats
read-only /proc/sys
read-only /proc/sysrq-trigger
read-only /proc/timer_stats
read-only /sys
ProtectKernelTunables=yes
read-only /foo ReadOnlyPaths=/foo
read-write /foo/bar ReadWritePaths=/foo/bar
tmpfs /home
tmpfs /root
tmpfs /run/user
ProtectHome=tmpfs
tmpfs /xyzzy TemporaryFileSystem=/xyzzy
tracelog Not Implemented
whitelist /mnt/backup TemporaryFileSystem=/mnt
BindPaths=/mnt/backup
fixme BindPaths= BindReadOnlyPaths=
always PrivatePIDs=yes
always (via pid-namespace) ProtectProc=invisible
Not Implemented ProtectProc=noaccess
#6491 ProcSubset=pid
Not Implemented RestrictSUIDSGID=yes

Devices

firejail systemd
private-dev PrivateDevices=yes
no3d InaccessiblePaths=/dev/dri
nodvd InaccessiblePaths=/dev/sr*
noinput InaccessiblePaths=/dev/input
noprinters fixme
nosound InaccessiblePaths=/dev/snd
notv InaccessiblePaths=/dev/dvb
nou2f InaccessiblePaths=/dev/hidraw*
novideo InaccessiblePaths=/dev/video*

Seccomp, mdwe, Capabilities and NNP

firejail systemd
caps.drop all CapabilityBoundingSet=
caps.drop sys_admin,net_admin CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_NET_ADMIN
caps.keep net_bind_service CapabilityBoundingSet=CAP_NET_BIND_SERVICE
memory-deny-write-execute MemoryDenyWriteExecute=yes
SystemCallFilter=~memfd_create
nonewprivs NoNewPrivileges=yes
seccomp SystemCallFilter=<omitted because it is to long, look at syscalls.txt>
seccomp.block-secondary SystemCallArchitectures=native
seccomp.drop @debug SystemCallFilter=~@debug
seccomp.keep @file-system,mount SystemCallFilter=@file-system mount
#3106 SystemCallFilter=@system-service
seccomp-error-action EPERM (default) SystemCallErrorNumber=EPERM
seccomp-error-action kill SystemCallErrorNumber= (default)
fixme SystemCallLog=
caps.drop sys_time,wake_alarm
seccomp.drop @clock
read-only /dev/rtc*
ProtectClock=yes
caps.drop syslog
seccomp.drop syslog
blacklist /dev/kmsg
blacklist /proc/kmsg
ProtectKernelLogs=yes
caps.drop sys_module
blacklist /usr/lib/modules
seccomp.drop @module
ProtectKernelModules=yes
fixme LockPersonality=yes

Landlock

systemd does not support Landlock (yet).

Networking

firejail systemd
dns 9.9.9.9 Not Implemented
hosts-file Not Implemented
hostname myhost Not Implemented
net none PrivateNetwork=yes
net eth0 Not Implemented
netfilter /etc/firejail/myfilter.net Not Implemented
Not Implemented IPIngressFilterPath= IPEgressFilterPath=
net eth0
netfilter ipdenyallow.net
nftables based
IPAddressDeny= IPAddressAllow=
eBPF based
fixme SocketBindAllow= SocketBindDeny=
fixme RestrictNetworkInterfaces=
netns NAME NetworkNamespacePath=/var/run/netns/NAME
protocol unix,inet,inet6 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
fixme ProtectHostname=yes

D-Bus

D-Bus filtering is not implemented for systemd and blocking the system-bus socket breaks systemd.

Resource Limits

firejail systemd
cpu 0,1 CPUAffinity=0,1
nice 2 Nice=2
rlimit* Limit*
timeout TimeoutSec=
fixme RestrictRealtime=yes
Not Implemented CoredumpFilter=
Not Implemented KeyringMode=
oom OOMScoreAdjust=
Not Implemented UMask=0077

User/Group

firejail systemd
nogroups Not Implemented
noroot PrivateUsers=yes
Not Implemented PrivateUsers=identity
Not Implemented User=user
Group=group
SupplementaryGroups=supp_group1 supp_group2
Not Implemented DynamicUser=yes
Not Implemented RemoveIPC=yes

Environment

firejail systemd
env FOO=bar Environment=FOO=bar
rmenv UnsetEnvironment=EDITOR

Uncategorized

firejail systemd
include some-common.inc Not Implemented
You can use symlinks / hardlinks in /etc/systemd/system/UNIT.d.
ipc-namespace PrivateIPC=yes
join JoinsNamespaceOf=
machine-id Not Implemented
Maybe you can use ExecStartPre=!/bin/sh -c "dbus-uuidgen > /etc/machine-id", however until now nobody had tested this.
restrict-namespaces RestrictNamespaces=
Not Implemented RestrictFileSystems=