[Python-checkins] bpo-39184: Add audit events to command execution functions in os and pty modules (GH-17824)

Miss Islington (bot) webhook-mailer at python.org
Tue Feb 4 19:32:37 EST 2020


https://github.com/python/cpython/commit/3498ac55bcfc18d698ea605424ec65a6e1457a39
commit: 3498ac55bcfc18d698ea605424ec65a6e1457a39
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020-02-04T16:32:32-08:00
summary:

bpo-39184: Add audit events to command execution functions in os and pty modules (GH-17824)

(cherry picked from commit 95f60010219e142a436fae18e1695cbc45407afe)

Co-authored-by: Saiyang Gou <gousaiyang at 163.com>

files:
A Misc/NEWS.d/next/Security/2020-01-07-00-42-08.bpo-39184.fe7NgK.rst
M Doc/library/os.rst
M Doc/library/pty.rst
M Lib/pty.py
M Modules/posixmodule.c

diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index 7aadbcf773b6a..3a828c5e08563 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -3313,6 +3313,8 @@ to be ignored.
    you can check whether or not it is available using :data:`os.supports_fd`.
    If it is unavailable, using it will raise a :exc:`NotImplementedError`.
 
+   .. audit-event:: os.exec path,args,env os.execl
+
    .. availability:: Unix, Windows.
 
    .. versionadded:: 3.3
@@ -3656,6 +3658,8 @@ written in Python, such as a mail server's external command delivery program.
    :c:data:`POSIX_SPAWN_SETSCHEDPARAM` and :c:data:`POSIX_SPAWN_SETSCHEDULER`
    flags.
 
+   .. audit-event:: os.posix_spawn path,argv,env os.posix_spawn
+
    .. versionadded:: 3.8
 
    .. availability:: Unix.
@@ -3670,6 +3674,8 @@ written in Python, such as a mail server's external command delivery program.
    for the *executable* file in the list of directories specified by the
    :envvar:`PATH` environment variable (in the same way as for ``execvp(3)``).
 
+   .. audit-event:: os.posix_spawn path,argv,env os.posix_spawnp
+
    .. versionadded:: 3.8
 
    .. availability:: See :func:`posix_spawn` documentation.
@@ -3770,6 +3776,8 @@ written in Python, such as a mail server's external command delivery program.
       L = ['cp', 'index.html', '/dev/null']
       os.spawnvpe(os.P_WAIT, 'cp', L, os.environ)
 
+   .. audit-event:: os.spawn mode,path,args,env os.spawnl
+
    .. availability:: Unix, Windows.  :func:`spawnlp`, :func:`spawnlpe`, :func:`spawnvp`
       and :func:`spawnvpe` are not available on Windows.  :func:`spawnle` and
       :func:`spawnve` are not thread-safe on Windows; we advise you to use the
@@ -3839,6 +3847,8 @@ written in Python, such as a mail server's external command delivery program.
    function is not resolved until this function is first called.  If the function
    cannot be resolved, :exc:`NotImplementedError` will be raised.
 
+   .. audit-event:: os.startfile path,operation os.startfile
+
    .. availability:: Windows.
 
 
diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst
index 12268437d07e9..e85d2e239fdbd 100644
--- a/Doc/library/pty.rst
+++ b/Doc/library/pty.rst
@@ -69,6 +69,7 @@ The :mod:`pty` module defines the following functions:
    *select* throws an error on your platform when passed three empty lists. This
    is a bug, documented in `issue 26228 <https://bugs.python.org/issue26228>`_.
 
+   .. audit-event:: pty.spawn argv pty.spawn
 
    .. versionchanged:: 3.4
       :func:`spawn` now returns the status value from :func:`os.waitpid`
diff --git a/Lib/pty.py b/Lib/pty.py
index e841f12f3edb9..a32432041fa1d 100644
--- a/Lib/pty.py
+++ b/Lib/pty.py
@@ -8,6 +8,7 @@
 
 from select import select
 import os
+import sys
 import tty
 
 __all__ = ["openpty","fork","spawn"]
@@ -151,6 +152,7 @@ def spawn(argv, master_read=_read, stdin_read=_read):
     """Create a spawned process."""
     if type(argv) == type(''):
         argv = (argv,)
+    sys.audit('pty.spawn', argv)
     pid, master_fd = fork()
     if pid == CHILD:
         os.execlp(argv[0], *argv)
diff --git a/Misc/NEWS.d/next/Security/2020-01-07-00-42-08.bpo-39184.fe7NgK.rst b/Misc/NEWS.d/next/Security/2020-01-07-00-42-08.bpo-39184.fe7NgK.rst
new file mode 100644
index 0000000000000..1ab5d4d70eec5
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2020-01-07-00-42-08.bpo-39184.fe7NgK.rst
@@ -0,0 +1 @@
+Add audit events to command execution functions in os and pty modules.
\ No newline at end of file
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 850769fd95eef..88b47164bca09 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -5156,6 +5156,12 @@ os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
         return NULL;
     }
 
+    if (PySys_Audit("os.exec", "OOO", path->object ? path->object : Py_None,
+                    argv, Py_None) < 0) {
+        free_string_array(argvlist, argc);
+        return NULL;
+    }
+
     _Py_BEGIN_SUPPRESS_IPH
 #ifdef HAVE_WEXECV
     _wexecv(path->wide, argvlist);
@@ -5199,7 +5205,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
         PyErr_SetString(PyExc_TypeError,
                         "execve: argv must be a tuple or list");
-        goto fail;
+        goto fail_0;
     }
     argc = PySequence_Size(argv);
     if (argc < 1) {
@@ -5210,22 +5216,27 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
     if (!PyMapping_Check(env)) {
         PyErr_SetString(PyExc_TypeError,
                         "execve: environment must be a mapping object");
-        goto fail;
+        goto fail_0;
     }
 
     argvlist = parse_arglist(argv, &argc);
     if (argvlist == NULL) {
-        goto fail;
+        goto fail_0;
     }
     if (!argvlist[0][0]) {
         PyErr_SetString(PyExc_ValueError,
             "execve: argv first element cannot be empty");
-        goto fail;
+        goto fail_0;
     }
 
     envlist = parse_envlist(env, &envc);
     if (envlist == NULL)
-        goto fail;
+        goto fail_0;
+
+    if (PySys_Audit("os.exec", "OOO", path->object ? path->object : Py_None,
+                    argv, env) < 0) {
+        goto fail_1;
+    }
 
     _Py_BEGIN_SUPPRESS_IPH
 #ifdef HAVE_FEXECVE
@@ -5243,9 +5254,9 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
     /* If we get here it's definitely an error */
 
     posix_path_error(path);
-
+  fail_1:
     free_string_array(envlist, envc);
-  fail:
+  fail_0:
     if (argvlist)
         free_string_array(argvlist, argc);
     return NULL;
@@ -5576,6 +5587,11 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
     }
     attrp = &attr;
 
+    if (PySys_Audit("os.posix_spawn", "OOO",
+                    path->object ? path->object : Py_None, argv, env) < 0) {
+        goto exit;
+    }
+
     _Py_BEGIN_SUPPRESS_IPH
 #ifdef HAVE_POSIX_SPAWNP
     if (use_posix_spawnp) {
@@ -5816,6 +5832,13 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
         mode = _P_OVERLAY;
 #endif
 
+    if (PySys_Audit("os.spawn", "iOOO", mode,
+                    path->object ? path->object : Py_None, argv,
+                    Py_None) < 0) {
+        free_string_array(argvlist, argc);
+        return NULL;
+    }
+
     Py_BEGIN_ALLOW_THREADS
     _Py_BEGIN_SUPPRESS_IPH
 #ifdef HAVE_WSPAWNV
@@ -5925,6 +5948,11 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
         mode = _P_OVERLAY;
 #endif
 
+    if (PySys_Audit("os.spawn", "iOOO", mode,
+                    path->object ? path->object : Py_None, argv, env) < 0) {
+        goto fail_2;
+    }
+
     Py_BEGIN_ALLOW_THREADS
     _Py_BEGIN_SUPPRESS_IPH
 #ifdef HAVE_WSPAWNV
@@ -5943,6 +5971,7 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
     else
         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
 
+  fail_2:
     while (--envc >= 0)
         PyMem_DEL(envlist[envc]);
     PyMem_DEL(envlist);
@@ -11608,6 +11637,12 @@ os_startfile_impl(PyObject *module, path_t *filepath,
             "startfile not available on this platform");
     }
 
+    if (PySys_Audit("os.startfile", "Ou",
+                    filepath->object ? filepath->object : Py_None,
+                    operation) < 0) {
+        return NULL;
+    }
+
     Py_BEGIN_ALLOW_THREADS
     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
                           NULL, NULL, SW_SHOWNORMAL);



More information about the Python-checkins mailing list