diff options
| author | Stefan Metzmacher <metze@samba.org> | 2014-01-05 18:37:41 +0100 |
|---|---|---|
| committer | Stefan Metzmacher <metze@samba.org> | 2014-01-07 08:37:34 +0100 |
| commit | 4cc3388c034fa43c855fba802a30bbd2e78122be (patch) | |
| tree | 29055c58a93f3bf775a3d41b19fb365a13a4fbf3 /source4 | |
| parent | 13ccc5b517e873fe61da4ed7c10b26717aa2fa65 (diff) | |
| download | samba-4cc3388c034fa43c855fba802a30bbd2e78122be.tar.gz samba-4cc3388c034fa43c855fba802a30bbd2e78122be.tar.xz samba-4cc3388c034fa43c855fba802a30bbd2e78122be.zip | |
s4:pyrpc: fix talloc hierachie in dcerpc_InterfaceObject
The tevent_context is cached under the connection,
so we need to make sure it stays arround as long as the connection.
Otherwise it will segfault while dereferencing the tevent_context
on deallocation if a secondary connection is arround.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source4')
| -rw-r--r-- | source4/librpc/rpc/pyrpc.c | 85 |
1 files changed, 48 insertions, 37 deletions
diff --git a/source4/librpc/rpc/pyrpc.c b/source4/librpc/rpc/pyrpc.c index 67462f18f3..0de36810b5 100644 --- a/source4/librpc/rpc/pyrpc.c +++ b/source4/librpc/rpc/pyrpc.c @@ -288,55 +288,39 @@ static PyMethodDef dcerpc_interface_methods[] = { static void dcerpc_interface_dealloc(PyObject* self) { dcerpc_InterfaceObject *interface = (dcerpc_InterfaceObject *)self; - talloc_free(interface->mem_ctx); + interface->binding_handle = NULL; + interface->pipe = NULL; + TALLOC_FREE(interface->mem_ctx); self->ob_type->tp_free(self); } static PyObject *dcerpc_interface_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { dcerpc_InterfaceObject *ret; - const char *binding_string; - struct cli_credentials *credentials; - struct loadparm_context *lp_ctx = NULL; - PyObject *py_lp_ctx = Py_None, *py_credentials = Py_None; - TALLOC_CTX *mem_ctx; - struct tevent_context *event_ctx; - NTSTATUS status; - - PyObject *syntax, *py_basis = Py_None; + const char *binding_string = NULL; + PyObject *py_lp_ctx = Py_None; + PyObject *py_credentials = Py_None; + PyObject *syntax = Py_None; + PyObject *py_basis = Py_None; const char *kwnames[] = { "binding", "syntax", "lp_ctx", "credentials", "basis_connection", NULL }; struct ndr_interface_table *table; + NTSTATUS status; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OOO:connect", discard_const_p(char *, kwnames), &binding_string, &syntax, &py_lp_ctx, &py_credentials, &py_basis)) { return NULL; } - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { + ret = PyObject_New(dcerpc_InterfaceObject, type); + ret->pipe = NULL; + ret->binding_handle = NULL; + ret->mem_ctx = talloc_new(NULL); + if (ret->mem_ctx == NULL) { PyErr_NoMemory(); return NULL; } - lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); - if (lp_ctx == NULL) { - PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); - talloc_free(mem_ctx); - return NULL; - } - - credentials = cli_credentials_from_py_object(py_credentials); - if (credentials == NULL) { - PyErr_SetString(PyExc_TypeError, "Expected credentials"); - talloc_free(mem_ctx); - return NULL; - } - ret = PyObject_New(dcerpc_InterfaceObject, type); - ret->mem_ctx = mem_ctx; - - event_ctx = s4_event_context_init(ret->mem_ctx); - /* Create a dummy interface table struct. TODO: In the future, we should * rather just allow connecting without requiring an interface table. */ @@ -345,24 +329,21 @@ static PyObject *dcerpc_interface_new(PyTypeObject *type, PyObject *args, PyObje if (table == NULL) { PyErr_SetString(PyExc_MemoryError, "Allocating interface table"); - talloc_free(mem_ctx); + TALLOC_FREE(ret->mem_ctx); return NULL; } if (!ndr_syntax_from_py_object(syntax, &table->syntax_id)) { - talloc_free(mem_ctx); + TALLOC_FREE(ret->mem_ctx); return NULL; } - ret->pipe = NULL; - ret->binding_handle = NULL; - if (py_basis != Py_None) { struct dcerpc_pipe *base_pipe; if (!PyObject_TypeCheck(py_basis, &dcerpc_InterfaceType)) { PyErr_SetString(PyExc_ValueError, "basis_connection must be a DCE/RPC connection"); - talloc_free(mem_ctx); + TALLOC_FREE(ret->mem_ctx); return NULL; } @@ -373,13 +354,43 @@ static PyObject *dcerpc_interface_new(PyTypeObject *type, PyObject *args, PyObje ret->pipe = talloc_steal(ret->mem_ctx, ret->pipe); } else { + struct tevent_context *event_ctx; + struct loadparm_context *lp_ctx; + struct cli_credentials *credentials; + + event_ctx = s4_event_context_init(ret->mem_ctx); + if (event_ctx == NULL) { + PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); + TALLOC_FREE(ret->mem_ctx); + return NULL; + } + + lp_ctx = lpcfg_from_py_object(event_ctx, py_lp_ctx); + if (lp_ctx == NULL) { + PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); + TALLOC_FREE(ret->mem_ctx); + return NULL; + } + + credentials = cli_credentials_from_py_object(py_credentials); + if (credentials == NULL) { + PyErr_SetString(PyExc_TypeError, "Expected credentials"); + TALLOC_FREE(ret->mem_ctx); + return NULL; + } status = dcerpc_pipe_connect(ret->mem_ctx, &ret->pipe, binding_string, table, credentials, event_ctx, lp_ctx); + + /* + * the event context is cached under the connection, + * so let it be a child of it. + */ + talloc_steal(ret->pipe->conn, event_ctx); } if (!NT_STATUS_IS_OK(status)) { PyErr_SetDCERPCStatus(ret->pipe, status); - talloc_free(ret->mem_ctx); + TALLOC_FREE(ret->mem_ctx); return NULL; } ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC; |
