Skip to content

Commit 95f6001

Browse files
authored
bpo-39184: Add audit events to command execution functions in os and pty modules (pythonGH-17824)
1 parent 40e547d commit 95f6001

File tree

5 files changed

+56
-7
lines changed

5 files changed

+56
-7
lines changed

Doc/library/os.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,6 +3314,8 @@ to be ignored.
33143314
you can check whether or not it is available using :data:`os.supports_fd`.
33153315
If it is unavailable, using it will raise a :exc:`NotImplementedError`.
33163316

3317+
.. audit-event:: os.exec path,args,env os.execl
3318+
33173319
.. availability:: Unix, Windows.
33183320

33193321
.. versionadded:: 3.3
@@ -3670,6 +3672,8 @@ written in Python, such as a mail server's external command delivery program.
36703672
:c:data:`POSIX_SPAWN_SETSCHEDPARAM` and :c:data:`POSIX_SPAWN_SETSCHEDULER`
36713673
flags.
36723674

3675+
.. audit-event:: os.posix_spawn path,argv,env os.posix_spawn
3676+
36733677
.. versionadded:: 3.8
36743678

36753679
.. availability:: Unix.
@@ -3684,6 +3688,8 @@ written in Python, such as a mail server's external command delivery program.
36843688
for the *executable* file in the list of directories specified by the
36853689
:envvar:`PATH` environment variable (in the same way as for ``execvp(3)``).
36863690

3691+
.. audit-event:: os.posix_spawn path,argv,env os.posix_spawnp
3692+
36873693
.. versionadded:: 3.8
36883694

36893695
.. availability:: See :func:`posix_spawn` documentation.
@@ -3784,6 +3790,8 @@ written in Python, such as a mail server's external command delivery program.
37843790
L = ['cp', 'index.html', '/dev/null']
37853791
os.spawnvpe(os.P_WAIT, 'cp', L, os.environ)
37863792

3793+
.. audit-event:: os.spawn mode,path,args,env os.spawnl
3794+
37873795
.. availability:: Unix, Windows. :func:`spawnlp`, :func:`spawnlpe`, :func:`spawnvp`
37883796
and :func:`spawnvpe` are not available on Windows. :func:`spawnle` and
37893797
:func:`spawnve` are not thread-safe on Windows; we advise you to use the
@@ -3853,6 +3861,8 @@ written in Python, such as a mail server's external command delivery program.
38533861
function is not resolved until this function is first called. If the function
38543862
cannot be resolved, :exc:`NotImplementedError` will be raised.
38553863

3864+
.. audit-event:: os.startfile path,operation os.startfile
3865+
38563866
.. availability:: Windows.
38573867

38583868

Doc/library/pty.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ The :mod:`pty` module defines the following functions:
6969
*select* throws an error on your platform when passed three empty lists. This
7070
is a bug, documented in `issue 26228 <https://bugs.python.org/issue26228>`_.
7171

72+
.. audit-event:: pty.spawn argv pty.spawn
7273

7374
.. versionchanged:: 3.4
7475
:func:`spawn` now returns the status value from :func:`os.waitpid`

Lib/pty.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from select import select
1010
import os
11+
import sys
1112
import tty
1213

1314
__all__ = ["openpty","fork","spawn"]
@@ -151,6 +152,7 @@ def spawn(argv, master_read=_read, stdin_read=_read):
151152
"""Create a spawned process."""
152153
if type(argv) == type(''):
153154
argv = (argv,)
155+
sys.audit('pty.spawn', argv)
154156
pid, master_fd = fork()
155157
if pid == CHILD:
156158
os.execlp(argv[0], *argv)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add audit events to command execution functions in os and pty modules.

Modules/posixmodule.c

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5234,6 +5234,12 @@ os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
52345234
return NULL;
52355235
}
52365236

5237+
if (PySys_Audit("os.exec", "OOO", path->object ? path->object : Py_None,
5238+
argv, Py_None) < 0) {
5239+
free_string_array(argvlist, argc);
5240+
return NULL;
5241+
}
5242+
52375243
_Py_BEGIN_SUPPRESS_IPH
52385244
#ifdef HAVE_WEXECV
52395245
_wexecv(path->wide, argvlist);
@@ -5277,7 +5283,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
52775283
if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
52785284
PyErr_SetString(PyExc_TypeError,
52795285
"execve: argv must be a tuple or list");
5280-
goto fail;
5286+
goto fail_0;
52815287
}
52825288
argc = PySequence_Size(argv);
52835289
if (argc < 1) {
@@ -5288,22 +5294,27 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
52885294
if (!PyMapping_Check(env)) {
52895295
PyErr_SetString(PyExc_TypeError,
52905296
"execve: environment must be a mapping object");
5291-
goto fail;
5297+
goto fail_0;
52925298
}
52935299

52945300
argvlist = parse_arglist(argv, &argc);
52955301
if (argvlist == NULL) {
5296-
goto fail;
5302+
goto fail_0;
52975303
}
52985304
if (!argvlist[0][0]) {
52995305
PyErr_SetString(PyExc_ValueError,
53005306
"execve: argv first element cannot be empty");
5301-
goto fail;
5307+
goto fail_0;
53025308
}
53035309

53045310
envlist = parse_envlist(env, &envc);
53055311
if (envlist == NULL)
5306-
goto fail;
5312+
goto fail_0;
5313+
5314+
if (PySys_Audit("os.exec", "OOO", path->object ? path->object : Py_None,
5315+
argv, env) < 0) {
5316+
goto fail_1;
5317+
}
53075318

53085319
_Py_BEGIN_SUPPRESS_IPH
53095320
#ifdef HAVE_FEXECVE
@@ -5321,9 +5332,9 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
53215332
/* If we get here it's definitely an error */
53225333

53235334
posix_path_error(path);
5324-
5335+
fail_1:
53255336
free_string_array(envlist, envc);
5326-
fail:
5337+
fail_0:
53275338
if (argvlist)
53285339
free_string_array(argvlist, argc);
53295340
return NULL;
@@ -5654,6 +5665,11 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
56545665
}
56555666
attrp = &attr;
56565667

5668+
if (PySys_Audit("os.posix_spawn", "OOO",
5669+
path->object ? path->object : Py_None, argv, env) < 0) {
5670+
goto exit;
5671+
}
5672+
56575673
_Py_BEGIN_SUPPRESS_IPH
56585674
#ifdef HAVE_POSIX_SPAWNP
56595675
if (use_posix_spawnp) {
@@ -5894,6 +5910,13 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
58945910
mode = _P_OVERLAY;
58955911
#endif
58965912

5913+
if (PySys_Audit("os.spawn", "iOOO", mode,
5914+
path->object ? path->object : Py_None, argv,
5915+
Py_None) < 0) {
5916+
free_string_array(argvlist, argc);
5917+
return NULL;
5918+
}
5919+
58975920
Py_BEGIN_ALLOW_THREADS
58985921
_Py_BEGIN_SUPPRESS_IPH
58995922
#ifdef HAVE_WSPAWNV
@@ -6003,6 +6026,11 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
60036026
mode = _P_OVERLAY;
60046027
#endif
60056028

6029+
if (PySys_Audit("os.spawn", "iOOO", mode,
6030+
path->object ? path->object : Py_None, argv, env) < 0) {
6031+
goto fail_2;
6032+
}
6033+
60066034
Py_BEGIN_ALLOW_THREADS
60076035
_Py_BEGIN_SUPPRESS_IPH
60086036
#ifdef HAVE_WSPAWNV
@@ -6021,6 +6049,7 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
60216049
else
60226050
res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
60236051

6052+
fail_2:
60246053
while (--envc >= 0)
60256054
PyMem_DEL(envlist[envc]);
60266055
PyMem_DEL(envlist);
@@ -11701,6 +11730,12 @@ os_startfile_impl(PyObject *module, path_t *filepath,
1170111730
"startfile not available on this platform");
1170211731
}
1170311732

11733+
if (PySys_Audit("os.startfile", "Ou",
11734+
filepath->object ? filepath->object : Py_None,
11735+
operation) < 0) {
11736+
return NULL;
11737+
}
11738+
1170411739
Py_BEGIN_ALLOW_THREADS
1170511740
rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
1170611741
NULL, NULL, SW_SHOWNORMAL);

0 commit comments

Comments
 (0)