Here's a simplified Python script (henceforth app.py
) that forks a child which then runs a subprocess:
import os
import subprocess
if os.fork() > 0:
os._exit(0)
subprocess.run(["/bin/true"])
When run as a normal user, it works:
$ python3 app.py
$ echo $?
0
When run as root from a sudo-launched parent shell, it works:
$ sudo bash
# python3 app.py
#
However when the parent is sudo, it fails in a bizarre way:
$ sudo python3 app.py
$ Traceback (most recent call last):
File "/tmp/app.py", line 7, in <module>
subprocess.run(["/bin/true"])
File "/usr/lib/python3.11/subprocess.py", line 548, in run
with Popen(*popenargs, **kwargs) as process:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/subprocess.py", line 1026, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/usr/lib/python3.11/subprocess.py", line 1955, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 38] Function not implemented: '/bin/true'
and:
$ sudo bash
# exec python3 app.py
$ Traceback ... (same error message as above)
Apparently something in the child process created by subprocess.run it getting ENOSYS, but it's a mystery to me how having sudo as the parent can cause this.
Update: The system in question is TrueNAS SCALE (Debian-derived Linux) with Python 3.11.9. Since posting I discovered that this does not repro on another Linux system, so I now suspect it is somehow related to sudo configuration or kernel security options.
The culprit for this was the log_subcmds
option in sudoers
, which itself uses ptrace and seccomp and has some documented limitations.
Thanks to DymOK on the TrueNAS forum who figured this out.