-
-
Notifications
You must be signed in to change notification settings - Fork 269
Description
systemd has a hardening flag for services MemoryDenyWriteExecute, described in the manpage as folllows:
Takes a boolean argument. If set, attempts to create memory mappings that are writable and executable at the same time, or to change existing memory mappings to become executable, or mapping shared memory segments as executable, are prohibited. Specifically, a system call filter is added (or preferably, an equivalent kernel check is enabled with prctl(2)) that rejects mmap(2) system calls with both PROT_EXEC and PROT_WRITE set, mprotect(2) or pkey_mprotect(2) system calls with PROT_EXEC set and shmat(2) system calls with SHM_EXEC set. Note that this option is incompatible with programs and libraries that generate program code dynamically at runtime, including JIT execution engines, executable stacks, and code "trampoline" feature of various C compilers. This option improves service security, as it makes harder for software exploits to change running code dynamically. [...]
When using this option with uv's python (3.14, Linux, x86-64, gnu), thread creation from Python fails:
$ systemd-run -p MemoryDenyWriteExecute=true -t ~/.local/share/uv/python/cpython-3.14.0-linux-x86_64-gnu/bin/python -c 'import threading; threading.Thread().start()'
Running as unit: run-p344916-i344917.service
Press ^] three times within 1s to disconnect TTY.
Traceback (most recent call last):
File "<string>", line 1, in <module>
import threading; threading.Thread().start()
~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/home/ran/.local/share/uv/python/cpython-3.14.0-linux-x86_64-gnu/lib/python3.14/threading.py", line 1004, in start
_start_joinable_thread(self._bootstrap, handle=self._os_thread_handle,
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
daemon=self.daemon)
^^^^^^^^^^^^^^^^^^^
RuntimeError: can't start new thread
This doesn't happen with system Python (tested on Arch Linux with Python 3.14 and Debian trixie with Python 3.13):
$ systemd-run -p MemoryDenyWriteExecute=true -t python -c 'import threading; threading.Thread().start()'
Running as unit: run-p345006-i345007.service
Press ^] three times within 1s to disconnect TTY.
My initial thought was that this is due to JIT but sys._jit.is_enabled() returns false, and also has nothing to do with threads.
I will try to investigate why this happens when I have some time, but maybe someone has an idea.