Open RobinJadoul opened 9 months ago
- The
_posixsubprocess.fork_exec
function, and its only user in the standard library,multiprocessing.util.spawnv_passfds
perform a
The primary user of that is subprocess
, not just multiprocessing
's spawn start method.
subprocess
already has an audit hook of its own via sys.audit
: https://github.com/python/cpython/blob/main/Lib/subprocess.py#L1827
Along those lines, it'd be simpler and consistent to just call sys.audit from within multiprocessing.util.spawnv_passfds
, but I think your point of this issue was more to see it consistently done at the extension module API level?
There is symmetry in that the private _winapi.CreateProcess
API also triggers an audit hook in addition to subprocess.Popen
before it calls it so I'm okay with the concept of adding a _posixsubprocess.fork_exec
audit event as your PR does.
Ah, yes, I have no idea how I missed subprocess when looking for callers...
It's indeed the goal to have some fewer "holes" or better coverage from the audit hooks here. That includes directly calling into the extension modules or callers that don't do their own hook (like the multiprocessing one). In general, the closer to the actual operation happening, the less chance to miss it.
The new event was indeed based on the winapi ones.
Should _gdbm.open()
also emit an audit event? It can be used to overwrite a file, besides creating a new one.
Looks like a good catch that should probably be covered too. It may need a bit of translation to not confuse existing consumers of the open
event though, as the flags and mode are noticeably different in _gdbm.open
.
Bug report
Bug description:
Several extension modules don't fully emit the relevant audit events, leading to file read or process spawning without any traceability. In particular:
_ctypes.CFuncPtr
does not emitctypes.call_function
. When combined with some known addresses, this can result in arbitrary functions in libc or python getting called. Such addresses could come fromid
,ctypes.pythonapi._handle
, passing abyref
pointer toctypes.cast
, or probably still several other methods. Coincidentally, thectypes.cast
method would by audited by the samectypes.call_function
once it is present. The downside is that it may also result in multiple audit hooks for functions likectypes.string_at
that have their own specialized audit hook event too._ctypes.CFuncPtr
might fall under the audit eventctypes.cdata
, as it is in spirit (though not in implementation) similar to calling a.from_address
. An option might be to introducectypes.cdata/function
similar toctypes.cdata/buffer
for this.readline
module can open and read a file throughreadline.read_history_file
without having anopen
audit hook. Together withreadline.get_history_item
, this can lead to unaudited file reads. A similar situation exists for some other functions in this library._posixsubprocess.fork_exec
function, and its only user in the standard library,multiprocessing.util.spawnv_passfds
perform a fork + exec without any audit hooks. One would expect eitheros.fork
andos.exec
or the functionally similaros.posix_spawn
here.I'm happy to make a quick PR for these and adjust any specific event types to be more consistent or more uniquely identifiable.
Quick example in code:
CPython versions tested on:
3.11, 3.12, 3.13, CPython main branch
Operating systems tested on:
Linux
Linked PRs