Add free function for sudo Python module.

This reduces the amount of memory leaked on unload.
This commit is contained in:
Todd C. Miller
2023-07-25 09:33:03 -06:00
parent e59c487434
commit 1a00423afd
5 changed files with 30 additions and 5 deletions

View File

@@ -23,7 +23,7 @@
#include "sudo_python_module.h" #include "sudo_python_module.h"
static PyTypeObject *sudo_type_ConvMessage; PyTypeObject *sudo_type_ConvMessage;
static PyObject * static PyObject *
_sudo_ConvMessage__Init(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs) _sudo_ConvMessage__Init(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs)

View File

@@ -130,7 +130,7 @@ static PyMethodDef _sudo_LogHandler_class_methods[] =
int int
sudo_module_set_default_loghandler() sudo_module_set_default_loghandler()
{ {
debug_decl(sudo_module_register_loghandler, PYTHON_DEBUG_INTERNAL); debug_decl(sudo_module_set_default_loghandler, PYTHON_DEBUG_INTERNAL);
PyObject *py_sudo, *py_logging_module = NULL, *py_logger = NULL, PyObject *py_sudo, *py_logging_module = NULL, *py_logger = NULL,
*py_streamhandler = NULL, *py_class = NULL, *py_streamhandler = NULL, *py_class = NULL,

View File

@@ -64,7 +64,7 @@ _append_python_path(const char *module_dir)
{ {
debug_decl(_append_python_path, PYTHON_DEBUG_PLUGIN_LOAD); debug_decl(_append_python_path, PYTHON_DEBUG_PLUGIN_LOAD);
int rc = -1; int rc = -1;
PyObject *py_sys_path = PySys_GetObject("path"); PyObject *py_sys_path = PySys_GetObject("path"); // borrowed
if (py_sys_path == NULL) { if (py_sys_path == NULL) {
PyErr_Format(sudo_exc_SudoException, "Failed to get python 'path'"); PyErr_Format(sudo_exc_SudoException, "Failed to get python 'path'");
debug_return_int(rc); debug_return_int(rc);
@@ -77,7 +77,7 @@ _append_python_path(const char *module_dir)
Py_XDECREF(py_module_dir); Py_XDECREF(py_module_dir);
debug_return_int(rc); debug_return_int(rc);
} }
Py_XDECREF(py_module_dir); Py_DECREF(py_module_dir);
if (sudo_debug_needed(SUDO_DEBUG_INFO)) { if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
char *path = py_join_str_list(py_sys_path, ":"); char *path = py_join_str_list(py_sys_path, ":");

View File

@@ -42,6 +42,9 @@ static PyObject *python_sudo_conversation(PyObject *py_self, PyObject *py_args,
static PyObject *python_sudo_options_as_dict(PyObject *py_self, PyObject *py_args); static PyObject *python_sudo_options_as_dict(PyObject *py_self, PyObject *py_args);
static PyObject *python_sudo_options_from_dict(PyObject *py_self, PyObject *py_args); static PyObject *python_sudo_options_from_dict(PyObject *py_self, PyObject *py_args);
// Called on module teardown.
static void sudo_module_free(void *self);
static PyMethodDef sudo_methods[] = { static PyMethodDef sudo_methods[] = {
{"debug", (PyCFunction)python_sudo_debug, METH_VARARGS, "Debug messages which can be saved to file in sudo.conf."}, {"debug", (PyCFunction)python_sudo_debug, METH_VARARGS, "Debug messages which can be saved to file in sudo.conf."},
{"log_info", (PyCFunction)python_sudo_log_info, METH_VARARGS | METH_KEYWORDS, "Display informational messages."}, {"log_info", (PyCFunction)python_sudo_log_info, METH_VARARGS | METH_KEYWORDS, "Display informational messages."},
@@ -62,7 +65,7 @@ static struct PyModuleDef sudo_module = {
NULL, /* slots */ NULL, /* slots */
NULL, /* traverse */ NULL, /* traverse */
NULL, /* clear */ NULL, /* clear */
NULL /* free */ sudo_module_free
}; };
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
@@ -600,8 +603,29 @@ cleanup:
Py_CLEAR(py_module); Py_CLEAR(py_module);
Py_CLEAR(sudo_exc_SudoException); Py_CLEAR(sudo_exc_SudoException);
Py_CLEAR(sudo_exc_PluginError); Py_CLEAR(sudo_exc_PluginError);
Py_CLEAR(sudo_exc_PluginReject);
Py_CLEAR(sudo_exc_ConversationInterrupted); Py_CLEAR(sudo_exc_ConversationInterrupted);
} }
debug_return_ptr(py_module); debug_return_ptr(py_module);
} }
static void
sudo_module_free(void *self)
{
debug_decl(sudo_module_free, PYTHON_DEBUG_C_CALLS);
// Free exceptions
Py_CLEAR(sudo_exc_SudoException);
Py_CLEAR(sudo_exc_PluginError);
Py_CLEAR(sudo_exc_PluginReject);
Py_CLEAR(sudo_exc_ConversationInterrupted);
// Free base plugin
Py_CLEAR(sudo_type_Plugin);
// Free conversation message type
Py_CLEAR(sudo_type_ConvMessage);
debug_return;
}

View File

@@ -29,6 +29,7 @@ extern PyObject *sudo_exc_PluginReject; // a reject with message
extern PyObject *sudo_exc_PluginError; // an error with message extern PyObject *sudo_exc_PluginError; // an error with message
extern PyTypeObject *sudo_type_Plugin; extern PyTypeObject *sudo_type_Plugin;
extern PyTypeObject *sudo_type_ConvMessage;
PyObject *sudo_module_create_class(const char *class_name, PyMethodDef *class_methods, PyObject *sudo_module_create_class(const char *class_name, PyMethodDef *class_methods,
PyObject *base_class); PyObject *base_class);