The Debian security team received a report that using --seccomp together with --chroot does not work as one would expect.
If the libpostexecseccomp.so library is missing inside the chroot, the syscalls are not actually filtered.
For example:
$ touch /srv/chroot/autopkgtest/tmp/foo
$ ls -l /srv/chroot/autopkgtest/tmp/foo
-rw-r--r-- 1 reiner reiner 0 Aug 29 18:11 /srv/chroot/autopkgtest/tmp/foo
$ firejail --seccomp.drop=unlinkat --chroot=/srv/chroot/autopkgtest rm /tmp/foo
Warning: default profile disabled by --chroot option
Parent pid 13096, child pid 13097
Warning: cannot find home directory
Dropping all Linux capabilities and enforcing default seccomp filter
Warning: failed to unmount /sys
Post-exec seccomp protector enabled
Child process initialized in 4.49 ms
ERROR: ld.so: object '/usr/lib/x86_64-linux-gnu/firejail/libpostexecseccomp.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object '/usr/lib/x86_64-linux-gnu/firejail/libpostexecseccomp.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Parent is shutting down, bye...
$ ls -l /srv/chroot/autopkgtest/tmp/foo
ls: cannot access '/srv/chroot/autopkgtest/tmp/foo': No such file or directory
As firejail is already checking that a certain directory hierarchy is present inside the chroot (/dev, /etc, /var/tmp, ...), it should also check that the required libraries it (pre)loads are there.
It should also be documented how the chroot should look like if one wants to use all firejail features.
I was also thinking if we maybe can expect from users to actually turn chroot on in firejail.config (and ship firejail with it turned off by default). That's a different topic though.
It is a different bug! By default for --chroot, --overlay-* and --appimage we do the following:
If any of these fail, we don't start the sandbox. For example it will fail on kenel 3.2 where there is no seccomp available. For --chroot sandboxes seccomp will always run. This can be easily checked from firetools or with --seccomp.print. Example:
$ firejail --name=test --seccomp.drop=unlinkat --chroot=/chroot/sid
Warning: default profile disabled by --chroot option
Parent pid 8766, child pid 8767
Dropping all Linux capabilities and enforcing default seccomp filter
Post-exec seccomp protector enabled
Child process initialized in 5.79 ms
ERROR: ld.so: object '/usr/lib/firejail/libpostexecseccomp.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object '/usr/lib/firejail/libpostexecseccomp.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object '/usr/lib/firejail/libpostexecseccomp.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
In a different terminal I check the test sandbox:
`````
$ firejail --seccomp.print=test
Switching to pid 8767, the first child process inside the sandbox
0000: 20 00 00 00000004 ld data.architecture
0001: 15 01 00 c000003e jeq ARCH_64 0003 (false 0002)
0002: 06 00 00 7fff0000 ret ALLOW
0003: 20 00 00 00000000 ld data.syscall-number
0004: 35 01 00 40000000 jge X32_ABI 0006 (false 0005)
0005: 35 01 00 00000000 jge read 0007 (false 0006)
0006: 06 00 00 00050001 ret ERRNO(1)
0007: 15 41 00 0000009a jeq modify_ldt 0049 (false 0008)
0008: 15 40 00 000000d4 jeq lookup_dcookie 0049 (false 0009)
0009: 15 3f 00 0000012a jeq perf_event_open 0049 (false 000a)
000a: 15 3e 00 00000137 jeq process_vm_writev 0049 (false 000b)
000b: 15 3d 00 0000009c jeq _sysctl 0049 (false 000c)
000c: 15 3c 00 000000b7 jeq afs_syscall 0049 (false 000d)
000d: 15 3b 00 000000ae jeq create_module 0049 (false 000e)
000e: 15 3a 00 000000b1 jeq get_kernel_syms 0049 (false 000f)
000f: 15 39 00 000000b5 jeq getpmsg 0049 (false 0010)
0010: 15 38 00 000000b6 jeq putpmsg 0049 (false 0011)
0011: 15 37 00 000000b2 jeq query_module 0049 (false 0012)
0012: 15 36 00 000000b9 jeq security 0049 (false 0013)
0013: 15 35 00 0000008b jeq sysfs 0049 (false 0014)
0014: 15 34 00 000000b8 jeq tuxcall 0049 (false 0015)
0015: 15 33 00 00000086 jeq uselib 0049 (false 0016)
[...]
`````
We have two bugs:
Document everything in the man pages
Get rid of the ld.so messages. Somehow the sandbox still tries to install the postexec seccomp filter, but this filter is an empty file (it was replaced by the regular seccomp filter), and the postexec loader is missing anyway.
I'll bring in the fixes.
@netblue30 I think firejail shouldn't start the program if it was explicitely requested that some syscalls are dropped, instead of running it with default filters.
It won't work. Most of the time the user has no idea where the filters are coming from (profile files), and some profiles are modifying the seccomp filter. For example in --overlay and --appimage (firejail --overlay firefox). It is better just to leave it running and put a big message on the screen, something like this:
`````
$ firejail --chroot=/chroot/sid
Warning: default profile disabled by --chroot option
Parent pid 7994, child pid 7995
* Warning: dropping all Linux capabilities and enforcing *
* default seccomp filter *
Child process initialized in 5.26 ms
`````
I removed libpostexec.so functionality and modified the man pages: https://github.com/netblue30/firejail/commit/07384ab64a4a98ff920e7667795282ae9ad21322
I'll do some testing over the weekend, probably there is more to come.
OK, this is another bug: default profiles are not applied by default for --chroot. Fix in https://github.com/netblue30/firejail/commit/ba2e5f55ed8b3bd83b15fc51ae5ef6050b8f8dca
`````
$ firejail --chroot=/chroot/sid
Reading profile /etc/firejail/default.profile
Reading profile /etc/firejail/globals.local
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-passwdmgr.inc
Reading profile /etc/firejail/disable-programs.inc
* Note: you can use --noprofile to disable default.profile *
Warning: --chroot and --noroot are mutually exclusive, noroot disabled
Parent pid 19028, child pid 19029
* Warning: dropping all Linux capabilities and enforcing *
* default seccomp filter *
Child process initialized in 23.15 ms
`````
Hm, I still think that firejail should not allow the program to run if the user explicitely requests for syscalls to be dropped (on the command line), but for some reason (also using --chroot) firejail would have to use the default seccomp filter (which would allow again the syscall that was requested to be dropped).
Maybe --seccomp.drop etc should be disallowed from using together with --chroot.
Done! (https://github.com/netblue30/firejail/commit/55cd5c1d8f4007bc28d50c4324d2f1ff8dbef14a)
I'll be doing more testing and cleanup this week. This is what I have for chroot in this moment:
if seccomp.drop, seccomp.keep or seccomp= is configured on command line we don't start the sandbox
if seccomp.drop, seccomp,keep or seccomp= is configured in a profile file, we replace the filter, print a big warning on the screen, and start the sandbox
protocol, seccomp.block-secondary and memory-deny-write-execute are handled independently and are not affected
Similar scheme is in effect for caps command line options under chroot.
Most helpful comment
Done! (https://github.com/netblue30/firejail/commit/55cd5c1d8f4007bc28d50c4324d2f1ff8dbef14a)
I'll be doing more testing and cleanup this week. This is what I have for chroot in this moment:
if seccomp.drop, seccomp.keep or seccomp= is configured on command line we don't start the sandbox
if seccomp.drop, seccomp,keep or seccomp= is configured in a profile file, we replace the filter, print a big warning on the screen, and start the sandbox
protocol, seccomp.block-secondary and memory-deny-write-execute are handled independently and are not affected
Similar scheme is in effect for caps command line options under chroot.