mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
s4 librpc rpc pyrpc: Ensure tevent_context deleted last
Ensure that the tevent_context is deleted after the connection, to prevent a use after free. Note: Py_DECREF calls dcerpc_interface_dealloc so the TALLOC_FREE(ret->mem_ctx) calls in the error paths of py_dcerpc_interface_init_helper needed removal. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13932 Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
165025a56e
commit
d65b7641c8
@ -300,9 +300,27 @@ static PyMethodDef dcerpc_interface_methods[] = {
|
|||||||
static void dcerpc_interface_dealloc(PyObject* self)
|
static void dcerpc_interface_dealloc(PyObject* self)
|
||||||
{
|
{
|
||||||
dcerpc_InterfaceObject *interface = (dcerpc_InterfaceObject *)self;
|
dcerpc_InterfaceObject *interface = (dcerpc_InterfaceObject *)self;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This can't fail, and if it did talloc_unlink(NULL, NULL) is
|
||||||
|
* harmless below
|
||||||
|
*/
|
||||||
|
struct tevent_context *ev_save = talloc_reparent(
|
||||||
|
NULL, interface->mem_ctx, interface->ev);
|
||||||
|
|
||||||
interface->binding_handle = NULL;
|
interface->binding_handle = NULL;
|
||||||
interface->pipe = NULL;
|
interface->pipe = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free everything *except* the event context, which must go
|
||||||
|
* away last
|
||||||
|
*/
|
||||||
TALLOC_FREE(interface->mem_ctx);
|
TALLOC_FREE(interface->mem_ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now wish a fond goodbye to the event context itself
|
||||||
|
*/
|
||||||
|
talloc_unlink(NULL, ev_save);
|
||||||
self->ob_type->tp_free(self);
|
self->ob_type->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ typedef struct {
|
|||||||
TALLOC_CTX *mem_ctx;
|
TALLOC_CTX *mem_ctx;
|
||||||
struct dcerpc_pipe *pipe;
|
struct dcerpc_pipe *pipe;
|
||||||
struct dcerpc_binding_handle *binding_handle;
|
struct dcerpc_binding_handle *binding_handle;
|
||||||
|
struct tevent_context *ev;
|
||||||
} dcerpc_InterfaceObject;
|
} dcerpc_InterfaceObject;
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,6 +123,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
|
|
||||||
ret->pipe = NULL;
|
ret->pipe = NULL;
|
||||||
ret->binding_handle = NULL;
|
ret->binding_handle = NULL;
|
||||||
|
ret->ev = NULL;
|
||||||
ret->mem_ctx = talloc_new(NULL);
|
ret->mem_ctx = talloc_new(NULL);
|
||||||
if (ret->mem_ctx == NULL) {
|
if (ret->mem_ctx == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
@ -130,30 +131,26 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(binding_string, "irpc:", 5) == 0) {
|
if (strncmp(binding_string, "irpc:", 5) == 0) {
|
||||||
struct tevent_context *event_ctx;
|
|
||||||
struct loadparm_context *lp_ctx;
|
struct loadparm_context *lp_ctx;
|
||||||
|
|
||||||
event_ctx = s4_event_context_init(ret->mem_ctx);
|
ret->ev = s4_event_context_init(ret->mem_ctx);
|
||||||
if (event_ctx == NULL) {
|
if (ret->ev == NULL) {
|
||||||
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_ctx = lpcfg_from_py_object(event_ctx, py_lp_ctx);
|
lp_ctx = lpcfg_from_py_object(ret->ev, py_lp_ctx);
|
||||||
if (lp_ctx == NULL) {
|
if (lp_ctx == NULL) {
|
||||||
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = pyrpc_irpc_connect(ret->mem_ctx, binding_string+5, table,
|
status = pyrpc_irpc_connect(ret->mem_ctx, binding_string+5, table,
|
||||||
event_ctx, lp_ctx, &ret->binding_handle);
|
ret->ev, lp_ctx, &ret->binding_handle);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
PyErr_SetNTSTATUS(status);
|
PyErr_SetNTSTATUS(status);
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -164,7 +161,6 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
|
|
||||||
py_base = PyImport_ImportModule("samba.dcerpc.base");
|
py_base = PyImport_ImportModule("samba.dcerpc.base");
|
||||||
if (py_base == NULL) {
|
if (py_base == NULL) {
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -172,7 +168,6 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
ClientConnection_Type = (PyTypeObject *)PyObject_GetAttrString(py_base, "ClientConnection");
|
ClientConnection_Type = (PyTypeObject *)PyObject_GetAttrString(py_base, "ClientConnection");
|
||||||
if (ClientConnection_Type == NULL) {
|
if (ClientConnection_Type == NULL) {
|
||||||
PyErr_SetNone(PyExc_TypeError);
|
PyErr_SetNone(PyExc_TypeError);
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
Py_DECREF(py_base);
|
Py_DECREF(py_base);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -180,7 +175,6 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
|
|
||||||
if (!PyObject_TypeCheck(py_basis, ClientConnection_Type)) {
|
if (!PyObject_TypeCheck(py_basis, ClientConnection_Type)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "basis_connection must be a DCE/RPC connection");
|
PyErr_SetString(PyExc_TypeError, "basis_connection must be a DCE/RPC connection");
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
Py_DECREF(py_base);
|
Py_DECREF(py_base);
|
||||||
Py_DECREF(ClientConnection_Type);
|
Py_DECREF(ClientConnection_Type);
|
||||||
@ -191,7 +185,17 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
((dcerpc_InterfaceObject *)py_basis)->pipe);
|
((dcerpc_InterfaceObject *)py_basis)->pipe);
|
||||||
if (base_pipe == NULL) {
|
if (base_pipe == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
Py_DECREF(ret);
|
||||||
|
Py_DECREF(py_base);
|
||||||
|
Py_DECREF(ClientConnection_Type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->ev = talloc_reference(
|
||||||
|
ret->mem_ctx,
|
||||||
|
((dcerpc_InterfaceObject *)py_basis)->ev);
|
||||||
|
if (ret->ev == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
Py_DECREF(py_base);
|
Py_DECREF(py_base);
|
||||||
Py_DECREF(ClientConnection_Type);
|
Py_DECREF(ClientConnection_Type);
|
||||||
@ -201,7 +205,6 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
status = dcerpc_secondary_context(base_pipe, &ret->pipe, table);
|
status = dcerpc_secondary_context(base_pipe, &ret->pipe, table);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
PyErr_SetNTSTATUS(status);
|
PyErr_SetNTSTATUS(status);
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
Py_DECREF(py_base);
|
Py_DECREF(py_base);
|
||||||
Py_DECREF(ClientConnection_Type);
|
Py_DECREF(ClientConnection_Type);
|
||||||
@ -212,22 +215,19 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
Py_XDECREF(ClientConnection_Type);
|
Py_XDECREF(ClientConnection_Type);
|
||||||
Py_XDECREF(py_base);
|
Py_XDECREF(py_base);
|
||||||
} else {
|
} else {
|
||||||
struct tevent_context *event_ctx;
|
|
||||||
struct loadparm_context *lp_ctx;
|
struct loadparm_context *lp_ctx;
|
||||||
struct cli_credentials *credentials;
|
struct cli_credentials *credentials;
|
||||||
|
|
||||||
event_ctx = s4_event_context_init(ret->mem_ctx);
|
ret->ev = s4_event_context_init(ret->mem_ctx);
|
||||||
if (event_ctx == NULL) {
|
if (ret->ev == NULL) {
|
||||||
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_ctx = lpcfg_from_py_object(event_ctx, py_lp_ctx);
|
lp_ctx = lpcfg_from_py_object(ret->ev, py_lp_ctx);
|
||||||
if (lp_ctx == NULL) {
|
if (lp_ctx == NULL) {
|
||||||
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -235,24 +235,16 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
|
|||||||
credentials = cli_credentials_from_py_object(py_credentials);
|
credentials = cli_credentials_from_py_object(py_credentials);
|
||||||
if (credentials == NULL) {
|
if (credentials == NULL) {
|
||||||
PyErr_SetString(PyExc_TypeError, "Expected credentials");
|
PyErr_SetString(PyExc_TypeError, "Expected credentials");
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
status = dcerpc_pipe_connect(ret->mem_ctx, &ret->pipe, binding_string,
|
status = dcerpc_pipe_connect(ret->mem_ctx, &ret->pipe, binding_string,
|
||||||
table, credentials, event_ctx, lp_ctx);
|
table, credentials, ret->ev, lp_ctx);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
PyErr_SetNTSTATUS(status);
|
PyErr_SetNTSTATUS(status);
|
||||||
TALLOC_FREE(ret->mem_ctx);
|
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* the event context is cached under the connection,
|
|
||||||
* so let it be a child of it.
|
|
||||||
*/
|
|
||||||
talloc_steal(ret->pipe->conn, event_ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret->pipe) {
|
if (ret->pipe) {
|
||||||
|
Loading…
Reference in New Issue
Block a user