-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document issue with multiple threads #9
Comments
These API-impacting changes are no true work-around for the `setxid`-style issue of `landlock_restrict_self` and `prctl`, but instead cause the `landlock` function to throw an exception when used with the threaded RTS, until a real fix can be put in place. Fixes: #9
After some more research, it turns out the GHC threaded RTS and There's a work-around: wrapping |
It's possible to use Turns out the version of Hence, this won't work unless
|
This is an optional feature, behind a flag, whose default is however `True`, since `libpsx` as shipped on current Ubuntu and Debian is broken: these ship with `libcap` 2.44, a version of the software in which `libpsx`'s `psx_syscall6` incorrectly handles syscall arguments. This was fixed in `libcap` 2.46 and later only. Furthermore, this old version of `libpsx` uses `SIGRTMAX` instead of `SIGSYS` as the signaling signal, which isn't handled in our `sigfillset` wrapper. The "currect" signal isn't exposed in any of the `libpsx` header files, so being compatible is difficult. Hence, this library now, by default, compiles and links in a bundled version of `libpsx`. A system-installed one can still be used (e.g., on Fedora systems) by disabling the flag. See: #9 (comment) See: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=e7e0e1b9e2cf3378d329174ed5b0c716b0539c72
This is an optional feature, behind a flag, whose default is however `True`, since `libpsx` as shipped on current Ubuntu and Debian is broken: these ship with `libcap` 2.44, a version of the software in which `libpsx`'s `psx_syscall6` incorrectly handles syscall arguments. This was fixed in `libcap` 2.46 and later only. Furthermore, this old version of `libpsx` uses `SIGRTMAX` instead of `SIGSYS` as the signaling signal, which isn't handled in our `sigfillset` wrapper. The "currect" signal isn't exposed in any of the `libpsx` header files, so being compatible is difficult. Hence, this library now, by default, compiles and links in a bundled version of `libpsx`. A system-installed one can still be used (e.g., on Fedora systems) by disabling the flag. See: #9 (comment) See: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=e7e0e1b9e2cf3378d329174ed5b0c716b0539c72
This is an optional feature, behind a flag, whose default is however `True`, since `libpsx` as shipped on current Ubuntu and Debian is broken: these ship with `libcap` 2.44, a version of the software in which `libpsx`'s `psx_syscall6` incorrectly handles syscall arguments. This was fixed in `libcap` 2.46 and later only. Furthermore, this old version of `libpsx` uses `SIGRTMAX` instead of `SIGSYS` as the signaling signal, which isn't handled in our `sigfillset` wrapper. The "currect" signal isn't exposed in any of the `libpsx` header files, so being compatible is difficult. Hence, this library now, by default, compiles and links in a bundled version of `libpsx`. A system-installed one can still be used (e.g., on Fedora systems) by disabling the flag. See: #9 (comment) See: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=e7e0e1b9e2cf3378d329174ed5b0c716b0539c72
This is an optional feature, behind a flag, whose default is however `True`, since `libpsx` as shipped on current Ubuntu and Debian is broken: these ship with `libcap` 2.44, a version of the software in which `libpsx`'s `psx_syscall6` incorrectly handles syscall arguments. This was fixed in `libcap` 2.46 and later only. Furthermore, this old version of `libpsx` uses `SIGRTMAX` instead of `SIGSYS` as the signaling signal, which isn't handled in our `sigfillset` wrapper. The "currect" signal isn't exposed in any of the `libpsx` header files, so being compatible is difficult. Hence, this library now, by default, compiles and links in a bundled version of `libpsx`. A system-installed one can still be used (e.g., on Fedora systems) by disabling the flag. See: #9 (comment) See: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=e7e0e1b9e2cf3378d329174ed5b0c716b0539c72
In order to be resilient against `setxid`-style issues when invoking `prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)` or `landlock_restrict_self`, whilst still be compatible with the threaded GHC RTS, the `landlock` library now depends on the `psx` library which embeds `libpsx` in the running process. The relevant library functions are then used to ensure the necessary syscalls are invoked in all process threads. This reverts the "throw-in-threaded-rts"-behaviour of before (which was never in a released version of the library). The `psx` library is a non-optional dependency. Even though it's not strictly required when using the single-threaded RTS, it's more simple to have it enabled in all cases. See: #9 See: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/tree/psx See: https://hackage.haskell.org/package/psx (eventually)
In Linux, security contexts and related things are kept per-thread by the kernel, even though users (and POSIX) expect many of them to be per-process. As an example, when one calls
setuid(...)
, one expects the whole process, including all its threads (some the application author may not even know to exist) to now run as the new UID, not only the thread performing the syscall.Within Glibc and other libc's, there's code in place to make
setuid
,setgid
and other calls to behave as expected/required: instead of simply invoking the syscall in the calling thread, the syscall is invoked in all threads of the process, through a bunch of highly tricky code involving signals and whatnot. This is known as thesetxid
issue.The Landlock API has the very same problem with
landlock_restrict_self
(and its prerequisiteprctl(PR_SET_NO_NEW_PRIVS, ...)
): the restrictions are applied only to the thread invokinglandlock_restrict_self
, not all pre-existing threads in a process. Hence, even after invokinglandlock_restrict_self
, some other threads would still be able to access files etc. which were supposed to be restricted.The Glibc machinery to run some syscall in all threads is not exposed, and can hence not be repurposed. There's a library,
libpsx
, part oflibcap
(which struggles from the exact samesetxid
problem) which provides a user-facing API to run some syscalls in all pre-existing threads, relying on some linker functionality to hook intopthread_create
. However, when attempting to uselibpsx
with a GHC Haskell program, things don't work out, potentially due to howlibpsx
and the GHC RTS interact, or maybe some bug(s) in the RTS, not expecting some function calls to be interrupted bySIGSYS
.In Golang, the
syscall.AllThreadsSyscall
function was added to invoke some syscall in all OS threads managed by the Go runtime. If GHC were to have a similar feature, thesetxid
problem oflandlock_restrict_self
could be fixed trivially (assuming no OS threads were created using other means).Alternatively, if Glibc gets built-in bindings for
landlock_restrict_self
which uses thesetxid
functionality under the hood, we could use this instead of invoking the syscall directly.For now, this issue is documented in the API docs, and the library will throw an exception when using
landlock
with the threaded RTS.See https://github.com/NicolasT/landlock-hs/blob/f22b7e4450991f7cdbec37271f56550c1d747b10/test/ThreadedScenario.hs for a scenario exposing the issue (when using the threaded RTS).
See also a related article by Kazu Yamamoto at https://kazu-yamamoto.hatenablog.jp/entry/2020/12/04/141308.
See: golang/go#1435
See: https://ewontfix.com/17/
See: https://sites.google.com/site/fullycapable/who-ordered-libpsx
See: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/tree/psx
The text was updated successfully, but these errors were encountered: