|
|
Subscribe / Log in / New account

The inherent fragility of seccomp()

The inherent fragility of seccomp()

Posted Nov 10, 2017 21:07 UTC (Fri) by juliank (guest, #45896)
Parent article: The inherent fragility of seccomp()

This is why, when designing the seccomp filtering for APT's downloading code [1], I looked at a list of all syscalls and picked all similar ones. So if I pick open(), I also pick openat(), for example. In fact, I broadly categorized it into

(1) base set of permissions (normal file I/O, sysv IPC [if fakeroot is used])
(2) directory reading
(3) sockets

See https://anonscm.debian.org/cgit/apt/apt.git/tree/methods/... and later lines.

This will break eventually if a new syscall is introduced. I consider two ways to solve that:

(1) Keep a list of all syscalls that have been checked in the source code, and regularly (on CI) check if there are new ones. If new ones appear, they have to be compared to the existing set, and if similar enough, added to the list.
(2) make syscalls return ENOSYS instead of aborting the program. This should cause libc to fall back from new optimised syscalls to old syscalls, as it has to maintain a certain base level

Combining the two should yield a maintainable result.

[1] https://juliank.wordpress.com/2017/10/23/apt-1-6-alpha-1-...

Another thing people don't consider are NSS modules and LD_PRELOAD. They could be doing all kind of weird stuff when you call getaddrinfo(). For example, they could use SYSV IPC to talk to another process, like a DNS cache. Evil little bastards. We had the same problem with people running apt in fakeroot: fakeroot needs sysv ipc to talk to its metadata daemon thing, and these were not whitelisted. I hacked in support for that - if FAKED_MODE is set in the environment, it now adds ipc syscalls. Ugly.


to post comments

The inherent fragility of seccomp()

Posted Nov 10, 2017 21:10 UTC (Fri) by juliank (guest, #45896) [Link] (1 responses)

Maybe we could start a libsseccomp-easy where we consolidate groups of syscalls and maintain that in a central place, optimally in libseccomp. It would be similar to pledge, except for the paths component - that would require kernel changes AFAICT.

The inherent fragility of seccomp()

Posted Nov 11, 2017 1:45 UTC (Sat) by pkern (subscriber, #32883) [Link]

Well, systemd does that: https://www.freedesktop.org/software/systemd/man/systemd....

At the same time as stated in the original post AppArmor also leaks the details of the libraries an application loads into the profiles. Or if they exec something you need to account for whatever the exec'ed app does.

The inherent fragility of seccomp()

Posted Nov 11, 2017 0:14 UTC (Sat) by nix (subscriber, #2304) [Link] (2 responses)

(1) Keep a list of all syscalls that have been checked in the source code, and regularly (on CI) check if there are new ones. If new ones appear, they have to be compared to the existing set, and if similar enough, added to the list.
You have to check all libraries your program uses, as well, and all libraries those libraries use, and so on ad infinitum. Oh and don't forget LD_PRELOADed libraries, dynamically loaded plugins, etc etc etc. (Particularly relevant if things like Gtk are in use because of the possibility of accessibility and IM plugins that call out to weird hardware and the like that you have quite possibly never realised even exists: but speech recognition for blind people sometimes relies on LD_PRELOAD to interpose all console I/O, etc etc etc... the list of obscure edge cases crucial to someone that this breaks is endless, and IMHO unmaintainable.)
(2) make syscalls return ENOSYS instead of aborting the program. This should cause libc to fall back from new optimised syscalls to old syscalls, as it has to maintain a certain base level
See my comment below for a case where the affected syscall was getpid(). getpid() is guaranteed to never fail, so nobody ever checks to see if it failed.

I just checked the seccomp filters active in a bunch of programs running on the system on which I'm typing this. Several of them still do not whitelist getpid(), almost a year after glibc 2.25 was released. I guess they're working by luck. The first such example is something that really *needs* seccomp, too: ntpd 4.2.8p10. It calls getpid() multiple times in the very same source file where it sets up a filter list that excludes getpid(): the obscure and out-of-the-way ntpd/ntpd.c. One of its calls does not check for failure, so can easily end up trying to set a process group of (pid_t)-1... it's in a tangle of conditionals that mean that most of the time, if you're lucky, you'll end up not compiling in that code -- but there are several other calls elsewhere in the source tree... and oh yes it also links to OpenSSL's libcrypto. Any bets on whether *that* calls getpid()? Repeat for every other syscall it doesn't allow past, and every syscall it allows past but only with argument checking.

This is not a maintainable strategy for any but the simplest programs.

The inherent fragility of seccomp()

Posted Nov 11, 2017 8:38 UTC (Sat) by alonz (subscriber, #815) [Link]

I believe the OP meant something subtly different: he wasn't planning to check which syscalls the program uses, rather just what syscalls exist in the kernel. When new syscalls are added - he would add them to the appropriate group in the filters (e.g., if it's a new way to open files, it will be filtered the same as all other open* syscalls). And until this update happens, the filters will ensure glibc (or any other library) will get ENOENT for this new syscall, forcing it to fall back to older syscalls.

In a sense, this just implements a poor-man's-pledge, with the CI system ensuring it evolves together with the kernel (or at least trying to).

The inherent fragility of seccomp()

Posted Nov 11, 2017 16:26 UTC (Sat) by marcH (subscriber, #57642) [Link]

Another random example of how seccomp breaks corner cases. This one took a few months to realize

https://bugs.chromium.org/p/chromium/issues/detail?id=772273
sslh seccomp policy blocks ssh to ChromeOS over link-local IPv6 addresses
https://chromium-review.googlesource.com/c/chromiumos/ove...


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds