From 2cb962fcea2e9b64e1c2635b7c38e0a24f8db8cb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 May 2025 16:58:14 +0200 Subject: [PATCH] s3:pylibsmb: add explicit talloc_stackframes to most functions Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- source3/libsmb/pylibsmb.c | 353 +++++++++++++++++++++++++++++++------- 1 file changed, 288 insertions(+), 65 deletions(-) diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c index 19107f9d7fd..d88b0e12c9e 100644 --- a/source3/libsmb/pylibsmb.c +++ b/source3/libsmb/pylibsmb.c @@ -160,9 +160,11 @@ static void *py_cli_state_poll_thread(void *private_data) gstate = PyGILState_Ensure(); while (!t->do_shutdown) { + TALLOC_CTX *frame = talloc_stackframe(); int ret; ret = tevent_loop_once(self->ev); assert(ret == 0); + TALLOC_FREE(frame); } PyGILState_Release(gstate); return NULL; @@ -624,7 +626,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args, if (py_negotiate_contexts != NULL) { negotiate_contexts = py_cli_get_negotiate_contexts( - talloc_tos(), py_negotiate_contexts); + frame, py_negotiate_contexts); if (negotiate_contexts == NULL) { TALLOC_FREE(frame); return -1; @@ -707,6 +709,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args, static void py_cli_got_oplock_break(struct tevent_req *req) { + TALLOC_CTX *frame = talloc_stackframe(); struct py_cli_state *self = (struct py_cli_state *) tevent_req_callback_data_void(req); struct py_cli_oplock_break b; @@ -719,6 +722,7 @@ static void py_cli_got_oplock_break(struct tevent_req *req) self->oplock_waiter = NULL; if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return; } @@ -726,6 +730,7 @@ static void py_cli_got_oplock_break(struct tevent_req *req) tmp = talloc_realloc(self->ev, self->oplock_breaks, struct py_cli_oplock_break, num_breaks+1); if (tmp == NULL) { + TALLOC_FREE(frame); return; } self->oplock_breaks = tmp; @@ -738,6 +743,7 @@ static void py_cli_got_oplock_break(struct tevent_req *req) self->oplock_waiter = cli_smb_oplock_break_waiter_send( self->ev, self->ev, self->cli); if (self->oplock_waiter == NULL) { + TALLOC_FREE(frame); return; } tevent_req_set_callback(self->oplock_waiter, py_cli_got_oplock_break, @@ -747,9 +753,11 @@ static void py_cli_got_oplock_break(struct tevent_req *req) static PyObject *py_cli_get_oplock_break(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); size_t num_oplock_breaks; if (!PyArg_ParseTuple(args, "")) { + TALLOC_FREE(frame); return NULL; } @@ -757,10 +765,12 @@ static PyObject *py_cli_get_oplock_break(struct py_cli_state *self, PyErr_SetString(PyExc_RuntimeError, "get_oplock_break() only possible on " "a multi_threaded connection"); + TALLOC_FREE(frame); return NULL; } if (self->oplock_cond != NULL) { + TALLOC_FREE(frame); errno = EBUSY; PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; @@ -777,6 +787,7 @@ static PyObject *py_cli_get_oplock_break(struct py_cli_state *self, self->oplock_cond = NULL; if (ret != 0) { + TALLOC_FREE(frame); errno = ret; PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; @@ -799,13 +810,18 @@ static PyObject *py_cli_get_oplock_break(struct py_cli_state *self, NULL, self->oplock_breaks, struct py_cli_oplock_break, num_oplock_breaks - 1); + TALLOC_FREE(frame); return result; } + + TALLOC_FREE(frame); Py_RETURN_NONE; } static void py_cli_state_dealloc(struct py_cli_state *self) { + TALLOC_CTX *frame = talloc_stackframe(); + TALLOC_FREE(self->thread_state); TALLOC_FREE(self->oplock_waiter); TALLOC_FREE(self->ev); @@ -815,46 +831,55 @@ static void py_cli_state_dealloc(struct py_cli_state *self) self->cli = NULL; } Py_TYPE(self)->tp_free((PyObject *)self); + TALLOC_FREE(frame); } static PyObject *py_cli_settimeout(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); unsigned int nmsecs = 0; unsigned int omsecs = 0; if (!PyArg_ParseTuple(args, "I", &nmsecs)) { + TALLOC_FREE(frame); return NULL; } omsecs = cli_set_timeout(self->cli, nmsecs); + TALLOC_FREE(frame); return PyLong_FromLong(omsecs); } static PyObject *py_cli_echo(struct py_cli_state *self, PyObject *Py_UNUSED(ignored)) { + TALLOC_CTX *frame = talloc_stackframe(); DATA_BLOB data = data_blob_string_const("keepalive"); struct tevent_req *req = NULL; NTSTATUS status; - req = cli_echo_send(NULL, self->ev, self->cli, 1, data); + req = cli_echo_send(frame, self->ev, self->cli, 1, data); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_echo_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); char *fname; unsigned CreateFlags = 0; unsigned DesiredAccess = FILE_GENERIC_READ; @@ -878,14 +903,16 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args, &fname, &CreateFlags, &DesiredAccess, &FileAttributes, &ShareAccess, &CreateDisposition, &CreateOptions, &ImpersonationLevel, &SecurityFlags)) { + TALLOC_FREE(frame); return NULL; } - req = cli_ntcreate_send(NULL, self->ev, self->cli, fname, CreateFlags, + req = cli_ntcreate_send(frame, self->ev, self->cli, fname, CreateFlags, DesiredAccess, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, ImpersonationLevel, SecurityFlags); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_ntcreate_recv(req, &fnum, NULL); @@ -893,8 +920,11 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args, if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + + TALLOC_FREE(frame); return Py_BuildValue("I", (unsigned)fnum); } @@ -1053,6 +1083,7 @@ static PyObject *py_cli_create_returns(const struct smb_create_returns *r) static PyObject *py_cli_symlink_error(const struct symlink_reparse_struct *s) { + TALLOC_CTX *frame = talloc_stackframe(); char *subst_utf8 = NULL, *print_utf8 = NULL; size_t subst_utf8_len, print_utf8_len; PyObject *v = NULL; @@ -1064,7 +1095,7 @@ static PyObject *py_cli_symlink_error(const struct symlink_reparse_struct *s) */ ok = convert_string_talloc( - talloc_tos(), + frame, CH_UNIX, CH_UTF8, s->substitute_name, @@ -1076,7 +1107,7 @@ static PyObject *py_cli_symlink_error(const struct symlink_reparse_struct *s) } ok = convert_string_talloc( - talloc_tos(), + frame, CH_UNIX, CH_UTF8, s->print_name, @@ -1099,14 +1130,14 @@ static PyObject *py_cli_symlink_error(const struct symlink_reparse_struct *s) (unsigned long long)s->flags); fail: - TALLOC_FREE(subst_utf8); - TALLOC_FREE(print_utf8); + TALLOC_FREE(frame); return v; } static PyObject *py_cli_get_posix_fs_info( struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; struct tevent_req *req = NULL; uint32_t optimal_transfer_size = 0; @@ -1118,8 +1149,9 @@ static PyObject *py_cli_get_posix_fs_info( uint64_t free_file_nodes = 0; uint64_t fs_identifier = 0; - req = cli_get_posix_fs_info_send(NULL, self->ev, self->cli); + req = cli_get_posix_fs_info_send(frame, self->ev, self->cli); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } @@ -1135,9 +1167,11 @@ static PyObject *py_cli_get_posix_fs_info( TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); return Py_BuildValue("{s:I,s:I,s:I,s:I,s:I,s:I,s:I,s:I}", "optimal_transfer_size", optimal_transfer_size, "block_size", block_size, @@ -1152,6 +1186,7 @@ static PyObject *py_cli_get_posix_fs_info( static PyObject *py_cli_create_ex( struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); char *fname = NULL; unsigned CreateFlags = 0; unsigned DesiredAccess = FILE_GENERIC_READ; @@ -1204,13 +1239,15 @@ static PyObject *py_cli_create_ex( &SecurityFlags, &py_create_contexts_in); if (!ret) { + TALLOC_FREE(frame); return NULL; } if (py_create_contexts_in != NULL) { create_contexts_in = py_cli_get_create_contexts( - NULL, py_create_contexts_in); + frame, py_create_contexts_in); if (create_contexts_in == NULL) { + TALLOC_FREE(frame); errno = EINVAL; PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; @@ -1224,7 +1261,7 @@ static PyObject *py_cli_create_ex( }; req = cli_smb2_create_fnum_send( - NULL, + frame, self->ev, self->cli, fname, @@ -1238,7 +1275,7 @@ static PyObject *py_cli_create_ex( create_contexts_in); } else { req = cli_ntcreate_send( - NULL, + frame, self->ev, self->cli, fname, @@ -1256,6 +1293,7 @@ static PyObject *py_cli_create_ex( ok = py_tevent_req_wait_exc(self, req); if (!ok) { + TALLOC_FREE(frame); return NULL; } @@ -1264,7 +1302,7 @@ static PyObject *py_cli_create_ex( req, &fnum, &cr, - NULL, + frame, &create_contexts_out, &symlink); } else { @@ -1294,6 +1332,7 @@ static PyObject *py_cli_create_ex( (unsigned)fnum, py_cr, py_create_contexts_out); + TALLOC_FREE(frame); return v; nomem: status = NT_STATUS_NO_MEMORY; @@ -1316,22 +1355,27 @@ fail: } else { PyErr_SetNTSTATUS(status); } + + TALLOC_FREE(frame); return NULL; } static PyObject *py_cli_close(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); struct tevent_req *req; int fnum; int flags = 0; NTSTATUS status; if (!PyArg_ParseTuple(args, "i|i", &fnum, &flags)) { + TALLOC_FREE(frame); return NULL; } - req = cli_close_send(NULL, self->ev, self->cli, fnum, flags); + req = cli_close_send(frame, self->ev, self->cli, fnum, flags); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_close_recv(req); @@ -1339,8 +1383,11 @@ static PyObject *py_cli_close(struct py_cli_state *self, PyObject *args) if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + + TALLOC_FREE(frame); Py_RETURN_NONE; } @@ -1382,6 +1429,7 @@ static PyObject *py_unix_mode_to_wire(struct py_cli_state *self, static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); struct tevent_req *req = NULL; int fnum, level; uint16_t recv_flags2; @@ -1391,20 +1439,23 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) NTSTATUS status; if (!PyArg_ParseTuple(args, "ii", &fnum, &level)) { + TALLOC_FREE(frame); return NULL; } req = cli_qfileinfo_send( - NULL, self->ev, self->cli, fnum, level, 0, UINT32_MAX); + frame, self->ev, self->cli, fnum, level, 0, UINT32_MAX); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_qfileinfo_recv( - req, NULL, &recv_flags2, &rdata, &num_rdata); + req, frame, &recv_flags2, &rdata, &num_rdata); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -1415,6 +1466,7 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) if (num_rdata != 8) { PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE); + TALLOC_FREE(frame); return NULL; } @@ -1446,6 +1498,7 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) if (num_rdata < 80) { PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE); + TALLOC_FREE(frame); return NULL; } @@ -1484,12 +1537,14 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) &sid_size); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE); + TALLOC_FREE(frame); return NULL; } if (data_off + sid_size < data_off || data_off + sid_size > num_rdata) { PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE); + TALLOC_FREE(frame); return NULL; } data_off += sid_size; @@ -1502,6 +1557,7 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) &sid_size); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE); + TALLOC_FREE(frame); return NULL; } @@ -1553,7 +1609,7 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) break; } - TALLOC_FREE(rdata); + TALLOC_FREE(frame); return result; } @@ -1561,6 +1617,7 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args) static PyObject *py_cli_rename( struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); char *fname_src = NULL, *fname_dst = NULL; int replace = false; struct tevent_req *req = NULL; @@ -1572,12 +1629,14 @@ static PyObject *py_cli_rename( ok = ParseTupleAndKeywords( args, kwds, "ss|p", kwlist, &fname_src, &fname_dst, &replace); if (!ok) { + TALLOC_FREE(frame); return NULL; } req = cli_rename_send( - NULL, self->ev, self->cli, fname_src, fname_dst, replace); + frame, self->ev, self->cli, fname_src, fname_dst, replace); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_rename_recv(req); @@ -1585,8 +1644,11 @@ static PyObject *py_cli_rename( if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + + TALLOC_FREE(frame); Py_RETURN_NONE; } @@ -1625,6 +1687,7 @@ static size_t push_data(uint8_t *buf, size_t n, void *priv) */ static PyObject *py_smb_savefile(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); uint16_t fnum; const char *filename = NULL; char *data = NULL; @@ -1635,22 +1698,25 @@ static PyObject *py_smb_savefile(struct py_cli_state *self, PyObject *args) if (!PyArg_ParseTuple(args, "s"PYARG_BYTES_LEN":savefile", &filename, &data, &size)) { + TALLOC_FREE(frame); return NULL; } /* create a new file handle for writing to */ - req = cli_ntcreate_send(NULL, self->ev, self->cli, filename, 0, + req = cli_ntcreate_send(frame, self->ev, self->cli, filename, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE, SMB2_IMPERSONATION_IMPERSONATION, 0); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_ntcreate_recv(req, &fnum, NULL); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -1659,36 +1725,42 @@ static PyObject *py_smb_savefile(struct py_cli_state *self, PyObject *args) state.nread = 0; state.total_data = size; - req = cli_push_send(NULL, self->ev, self->cli, fnum, 0, 0, 0, + req = cli_push_send(frame, self->ev, self->cli, fnum, 0, 0, 0, push_data, &state); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_push_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } /* close the file handle */ - req = cli_close_send(NULL, self->ev, self->cli, fnum, 0); + req = cli_close_send(frame, self->ev, self->cli, fnum, 0); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_close_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); int fnum; unsigned mode = 0; char *buf; @@ -1704,12 +1776,14 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args, if (!ParseTupleAndKeywords( args, kwds, "i" PYARG_BYTES_LEN "K|I", kwlist, &fnum, &buf, &buflen, &offset, &mode)) { + TALLOC_FREE(frame); return NULL; } req = cli_write_send(NULL, self->ev, self->cli, fnum, mode, (uint8_t *)buf, offset, buflen); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_write_recv(req, &written); @@ -1717,8 +1791,10 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args, if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); return Py_BuildValue("K", (unsigned long long)written); } @@ -1728,16 +1804,18 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args, static NTSTATUS py_smb_filesize(struct py_cli_state *self, uint16_t fnum, off_t *size) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; struct tevent_req *req = NULL; - req = cli_qfileinfo_basic_send(NULL, self->ev, self->cli, fnum); + req = cli_qfileinfo_basic_send(frame, self->ev, self->cli, fnum); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NT_STATUS_INTERNAL_ERROR; } status = cli_qfileinfo_basic_recv( req, NULL, size, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(req); + TALLOC_FREE(frame); return status; } @@ -1746,6 +1824,7 @@ static NTSTATUS py_smb_filesize(struct py_cli_state *self, uint16_t fnum, */ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; const char *filename = NULL; struct tevent_req *req = NULL; @@ -1756,6 +1835,7 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) PyObject *result = NULL; if (!PyArg_ParseTuple(args, "s:loadfile", &filename)) { + TALLOC_FREE(frame); return NULL; } @@ -1766,12 +1846,14 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) FILE_SHARE_READ, FILE_OPEN, 0, SMB2_IMPERSONATION_IMPERSONATION, 0); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_ntcreate_recv(req, &fnum, NULL); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -1779,11 +1861,13 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) status = py_smb_filesize(self, fnum, &size); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } result = PyBytes_FromStringAndSize(NULL, size); if (result == NULL) { + TALLOC_FREE(frame); return NULL; } @@ -1793,6 +1877,7 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) size, cli_read_sink, &buf); if (!py_tevent_req_wait_exc(self, req)) { Py_XDECREF(result); + TALLOC_FREE(frame); return NULL; } status = cli_pull_recv(req, &nread); @@ -1800,6 +1885,7 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) if (!NT_STATUS_IS_OK(status)) { Py_XDECREF(result); PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -1807,6 +1893,7 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) req = cli_close_send(NULL, self->ev, self->cli, fnum, 0); if (!py_tevent_req_wait_exc(self, req)) { Py_XDECREF(result); + TALLOC_FREE(frame); return NULL; } status = cli_close_recv(req); @@ -1814,6 +1901,7 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) if (!NT_STATUS_IS_OK(status)) { Py_XDECREF(result); PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -1823,21 +1911,25 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) PyErr_Format(PyExc_IOError, "read invalid - got %zu requested %zu", nread, size); + TALLOC_FREE(frame); return NULL; } if (nread < size) { if (_PyBytes_Resize(&result, nread) < 0) { + TALLOC_FREE(frame); return NULL; } } + TALLOC_FREE(frame); return result; } static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); int fnum; unsigned long long offset; unsigned size; @@ -1853,11 +1945,13 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args, if (!ParseTupleAndKeywords( args, kwds, "iKI", kwlist, &fnum, &offset, &size)) { + TALLOC_FREE(frame); return NULL; } result = PyBytes_FromStringAndSize(NULL, size); if (result == NULL) { + TALLOC_FREE(frame); return NULL; } buf = PyBytes_AS_STRING(result); @@ -1866,6 +1960,7 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args, buf, offset, size); if (!py_tevent_req_wait_exc(self, req)) { Py_XDECREF(result); + TALLOC_FREE(frame); return NULL; } status = cli_read_recv(req, &received); @@ -1874,6 +1969,7 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args, if (!NT_STATUS_IS_OK(status)) { Py_XDECREF(result); PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -1882,21 +1978,25 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args, PyErr_Format(PyExc_IOError, "read invalid - got %zu requested %u", received, size); + TALLOC_FREE(frame); return NULL; } if (received < size) { if (_PyBytes_Resize(&result, received) < 0) { + TALLOC_FREE(frame); return NULL; } } + TALLOC_FREE(frame); return result; } static PyObject *py_cli_ftruncate(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); int fnum; unsigned long long size; struct tevent_req *req; @@ -1907,11 +2007,13 @@ static PyObject *py_cli_ftruncate(struct py_cli_state *self, PyObject *args, if (!ParseTupleAndKeywords( args, kwds, "IK", kwlist, &fnum, &size)) { + TALLOC_FREE(frame); return NULL; } - req = cli_ftruncate_send(NULL, self->ev, self->cli, fnum, size); + req = cli_ftruncate_send(frame, self->ev, self->cli, fnum, size); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_ftruncate_recv(req); @@ -1919,8 +2021,11 @@ static PyObject *py_cli_ftruncate(struct py_cli_state *self, PyObject *args, if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + + TALLOC_FREE(frame); Py_RETURN_NONE; } @@ -1928,6 +2033,7 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); unsigned fnum, flag; struct tevent_req *req; NTSTATUS status; @@ -1937,12 +2043,14 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self, if (!ParseTupleAndKeywords( args, kwds, "II", kwlist, &fnum, &flag)) { + TALLOC_FREE(frame); return NULL; } - req = cli_nt_delete_on_close_send(NULL, self->ev, self->cli, fnum, + req = cli_nt_delete_on_close_send(frame, self->ev, self->cli, fnum, flag); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_nt_delete_on_close_recv(req); @@ -1950,8 +2058,11 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self, if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + + TALLOC_FREE(frame); Py_RETURN_NONE; } @@ -1963,9 +2074,13 @@ struct py_cli_notify_state { static void py_cli_notify_state_dealloc(struct py_cli_notify_state *self) { + TALLOC_CTX *frame = talloc_stackframe(); + TALLOC_FREE(self->req); Py_CLEAR(self->py_cli_state); Py_TYPE(self)->tp_free(self); + + TALLOC_FREE(frame); } static PyTypeObject py_cli_notify_state_type; @@ -1974,6 +2089,7 @@ static PyObject *py_cli_notify(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); static const char *kwlist[] = { "fnum", "buffer_size", @@ -2002,6 +2118,7 @@ static PyObject *py_cli_notify(struct py_cli_state *self, &completion_filter, &py_recursive); if (!ok) { + TALLOC_FREE(frame); return NULL; } @@ -2015,9 +2132,18 @@ static PyObject *py_cli_notify(struct py_cli_state *self, completion_filter, recursive); if (req == NULL) { + TALLOC_FREE(frame); PyErr_NoMemory(); return NULL; } + /* + * only reparent to frame, + * if we would pass frame to + * cli_query_security_descriptor_recv() + * we'd leak a potential talloc_stackframe_pool + * via py_return_ndr_struct(). + */ + talloc_reparent(NULL, frame, req); /* * Just wait for the request being submitted to @@ -2028,7 +2154,7 @@ static PyObject *py_cli_notify(struct py_cli_state *self, self->ev, send_queue); if (flush_req == NULL) { - TALLOC_FREE(req); + TALLOC_FREE(frame); PyErr_NoMemory(); return NULL; } @@ -2037,13 +2163,13 @@ static PyObject *py_cli_notify(struct py_cli_state *self, self->ev, endtime); if (!ok) { - TALLOC_FREE(req); + TALLOC_FREE(frame); PyErr_NoMemory(); return NULL; } ok = py_tevent_req_wait_exc(self, flush_req); if (!ok) { - TALLOC_FREE(req); + TALLOC_FREE(frame); return NULL; } TALLOC_FREE(flush_req); @@ -2051,14 +2177,15 @@ static PyObject *py_cli_notify(struct py_cli_state *self, py_notify_state = (struct py_cli_notify_state *) py_cli_notify_state_type.tp_alloc(&py_cli_notify_state_type, 0); if (py_notify_state == NULL) { - TALLOC_FREE(req); + TALLOC_FREE(frame); PyErr_NoMemory(); return NULL; } Py_INCREF(self); py_notify_state->py_cli_state = self; - py_notify_state->req = req; + py_notify_state->req = talloc_move(NULL, &req); + TALLOC_FREE(frame); return (PyObject *)py_notify_state; } @@ -2066,8 +2193,9 @@ static PyObject *py_cli_notify_get_changes(struct py_cli_notify_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); struct py_cli_state *py_cli_state = self->py_cli_state; - struct tevent_req *req = self->req; + struct tevent_req *req = NULL; uint32_t i; uint32_t num_changes = 0; struct notify_change *changes = NULL; @@ -2088,23 +2216,36 @@ static PyObject *py_cli_notify_get_changes(struct py_cli_notify_state *self, kwlist, &py_wait); if (!ok) { + TALLOC_FREE(frame); return NULL; } wait = PyObject_IsTrue(py_wait); - if (req == NULL) { + if (self->req == NULL) { PyErr_SetString(PyExc_RuntimeError, "TODO req == NULL " "- missing change notify request?"); + TALLOC_FREE(frame); return NULL; } - pending = tevent_req_is_in_progress(req); + pending = tevent_req_is_in_progress(self->req); if (pending && !wait) { + TALLOC_FREE(frame); Py_RETURN_NONE; } + /* + * Now we really return success or an exception + * so we move self->req to frame and set + * self->req to NULL. + * + * Below we also call Py_CLEAR(self->py_cli_state) + * as soon as possible. + */ + req = talloc_move(frame, &self->req); + if (pending) { struct timeval endtime; @@ -2113,29 +2254,31 @@ static PyObject *py_cli_notify_get_changes(struct py_cli_notify_state *self, py_cli_state->ev, endtime); if (!ok) { - TALLOC_FREE(req); + TALLOC_FREE(frame); + Py_CLEAR(self->py_cli_state); PyErr_NoMemory(); return NULL; } } ok = py_tevent_req_wait_exc(py_cli_state, req); - self->req = NULL; Py_CLEAR(self->py_cli_state); if (!ok) { + TALLOC_FREE(frame); return NULL; } status = cli_notify_recv(req, req, &num_changes, &changes); + TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(req); + TALLOC_FREE(frame); PyErr_SetNTSTATUS(status); return NULL; } result = Py_BuildValue("[]"); if (result == NULL) { - TALLOC_FREE(req); + TALLOC_FREE(frame); return NULL; } @@ -2148,7 +2291,7 @@ static PyObject *py_cli_notify_get_changes(struct py_cli_notify_state *self, "action", changes[i].action); if (change == NULL) { Py_XDECREF(result); - TALLOC_FREE(req); + TALLOC_FREE(frame); return NULL; } @@ -2156,12 +2299,12 @@ static PyObject *py_cli_notify_get_changes(struct py_cli_notify_state *self, Py_DECREF(change); if (ret == -1) { Py_XDECREF(result); - TALLOC_FREE(req); + TALLOC_FREE(frame); return NULL; } } - TALLOC_FREE(req); + TALLOC_FREE(frame); return result; } @@ -2332,15 +2475,17 @@ struct do_listing_state { static void do_listing_cb(struct tevent_req *subreq) { + TALLOC_CTX *frame = talloc_stackframe(); struct do_listing_state *state = tevent_req_callback_data_void(subreq); struct file_info *finfo = NULL; - state->status = cli_list_recv(subreq, NULL, &finfo); + state->status = cli_list_recv(subreq, frame, &finfo); if (!NT_STATUS_IS_OK(state->status)) { + TALLOC_FREE(frame); return; } state->callback_fn(finfo, state->mask, state->private_data); - TALLOC_FREE(finfo); + TALLOC_FREE(frame); } static NTSTATUS do_listing(struct py_cli_state *self, @@ -2351,6 +2496,7 @@ static NTSTATUS do_listing(struct py_cli_state *self, const char *, void *), void *priv) { + TALLOC_CTX *frame = talloc_stackframe(); char *mask = NULL; struct do_listing_state state = { .mask = mask, @@ -2361,17 +2507,18 @@ static NTSTATUS do_listing(struct py_cli_state *self, NTSTATUS status; if (user_mask == NULL) { - mask = talloc_asprintf(NULL, "%s\\*", base_dir); + mask = talloc_asprintf(frame, "%s\\*", base_dir); } else { - mask = talloc_asprintf(NULL, "%s\\%s", base_dir, user_mask); + mask = talloc_asprintf(frame, "%s\\%s", base_dir, user_mask); } if (mask == NULL) { + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } dos_format(mask); - req = cli_list_send(NULL, self->ev, self->cli, mask, attribute, + req = cli_list_send(frame, self->ev, self->cli, mask, attribute, info_level); if (req == NULL) { status = NT_STATUS_NO_MEMORY; @@ -2391,8 +2538,7 @@ static NTSTATUS do_listing(struct py_cli_state *self, } done: - TALLOC_FREE(mask); - TALLOC_FREE(req); + TALLOC_FREE(frame); return status; } @@ -2400,6 +2546,7 @@ static PyObject *py_cli_list(struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); char *base_dir; char *user_mask = NULL; unsigned int attribute = LIST_ATTRIBUTE_MASK; @@ -2415,11 +2562,13 @@ static PyObject *py_cli_list(struct py_cli_state *self, if (!ParseTupleAndKeywords(args, kwds, "z|sII:list", kwlist, &base_dir, &user_mask, &attribute, &info_level)) { + TALLOC_FREE(frame); return NULL; } result = Py_BuildValue("[]"); if (result == NULL) { + TALLOC_FREE(frame); return NULL; } @@ -2440,58 +2589,70 @@ static PyObject *py_cli_list(struct py_cli_state *self, if (!NT_STATUS_IS_OK(status)) { Py_XDECREF(result); PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); return result; } static PyObject *py_smb_unlink(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; const char *filename = NULL; struct tevent_req *req = NULL; const uint32_t attrs = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); if (!PyArg_ParseTuple(args, "s:unlink", &filename)) { + TALLOC_FREE(frame); return NULL; } - req = cli_unlink_send(NULL, self->ev, self->cli, filename, attrs); + req = cli_unlink_send(frame, self->ev, self->cli, filename, attrs); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_unlink_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } static PyObject *py_smb_rmdir(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; struct tevent_req *req = NULL; const char *dirname = NULL; if (!PyArg_ParseTuple(args, "s:rmdir", &dirname)) { + TALLOC_FREE(frame); return NULL; } - req = cli_rmdir_send(NULL, self->ev, self->cli, dirname); + req = cli_rmdir_send(frame, self->ev, self->cli, dirname); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_rmdir_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } @@ -2500,25 +2661,30 @@ static PyObject *py_smb_rmdir(struct py_cli_state *self, PyObject *args) */ static PyObject *py_smb_mkdir(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; const char *dirname = NULL; struct tevent_req *req = NULL; if (!PyArg_ParseTuple(args, "s:mkdir", &dirname)) { + TALLOC_FREE(frame); return NULL; } - req = cli_mkdir_send(NULL, self->ev, self->cli, dirname); + req = cli_mkdir_send(frame, self->ev, self->cli, dirname); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_mkdir_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } @@ -2636,29 +2802,35 @@ fail: */ static bool check_dir_path(struct py_cli_state *self, const char *path) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; struct tevent_req *req = NULL; - req = cli_chkpath_send(NULL, self->ev, self->cli, path); + req = cli_chkpath_send(frame, self->ev, self->cli, path); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return false; } status = cli_chkpath_recv(req); TALLOC_FREE(req); + TALLOC_FREE(frame); return NT_STATUS_IS_OK(status); } static PyObject *py_smb_chkpath(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); const char *path = NULL; bool dir_exists; if (!PyArg_ParseTuple(args, "s:chkpath", &path)) { + TALLOC_FREE(frame); return NULL; } dir_exists = check_dir_path(self, path); + TALLOC_FREE(frame); return PyBool_FromLong(dir_exists); } @@ -2683,34 +2855,50 @@ static PyObject *py_smb_protocol(struct py_cli_state *self, static PyObject *py_smb_get_sd(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); int fnum; unsigned sinfo; struct tevent_req *req = NULL; struct security_descriptor *sd = NULL; + PyObject *py_sd = NULL; NTSTATUS status; if (!PyArg_ParseTuple(args, "iI:get_acl", &fnum, &sinfo)) { + TALLOC_FREE(frame); return NULL; } req = cli_query_security_descriptor_send( - NULL, self->ev, self->cli, fnum, sinfo); + frame, self->ev, self->cli, fnum, sinfo); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_query_security_descriptor_recv(req, NULL, &sd); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + /* + * only reparent to frame, + * if we would pass frame to + * cli_query_security_descriptor_recv() + * we'd leak a potential talloc_stackframe_pool + * via py_return_ndr_struct(). + */ + talloc_reparent(NULL, frame, sd); - return py_return_ndr_struct( - "samba.dcerpc.security", "descriptor", sd, sd); + py_sd = py_return_ndr_struct("samba.dcerpc.security", "descriptor", + sd, sd); + TALLOC_FREE(frame); + return py_sd; } static PyObject *py_smb_set_sd(struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); PyObject *py_sd = NULL; struct tevent_req *req = NULL; struct security_descriptor *sd = NULL; @@ -2719,6 +2907,7 @@ static PyObject *py_smb_set_sd(struct py_cli_state *self, PyObject *args) NTSTATUS status; if (!PyArg_ParseTuple(args, "iOI:set_sd", &fnum, &py_sd, &sinfo)) { + TALLOC_FREE(frame); return NULL; } @@ -2727,12 +2916,14 @@ static PyObject *py_smb_set_sd(struct py_cli_state *self, PyObject *args) PyErr_Format(PyExc_TypeError, "Expected dcerpc.security.descriptor as argument, got %s", pytalloc_get_name(py_sd)); + TALLOC_FREE(frame); return NULL; } req = cli_set_security_descriptor_send( - NULL, self->ev, self->cli, fnum, sinfo, sd); + frame, self->ev, self->cli, fnum, sinfo, sd); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } @@ -2740,23 +2931,27 @@ static PyObject *py_smb_set_sd(struct py_cli_state *self, PyObject *args) TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } static PyObject *py_smb_smb1_posix( struct py_cli_state *self, PyObject *Py_UNUSED(ignored)) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; struct tevent_req *req = NULL; uint16_t major, minor; uint32_t caplow, caphigh; PyObject *result = NULL; - req = cli_unix_extensions_version_send(NULL, self->ev, self->cli); + req = cli_unix_extensions_version_send(frame, self->ev, self->cli); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_unix_extensions_version_recv( @@ -2764,18 +2959,21 @@ static PyObject *py_smb_smb1_posix( TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } req = cli_set_unix_extensions_capabilities_send( - NULL, self->ev, self->cli, major, minor, caplow, caphigh); + frame, self->ev, self->cli, major, minor, caplow, caphigh); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_set_unix_extensions_capabilities_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } @@ -2785,12 +2983,14 @@ static PyObject *py_smb_smb1_posix( (unsigned)major, (unsigned)caplow, (unsigned)caphigh); + TALLOC_FREE(frame); return result; } static PyObject *py_smb_smb1_readlink( struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; const char *filename = NULL; struct tevent_req *req = NULL; @@ -2798,74 +2998,87 @@ static PyObject *py_smb_smb1_readlink( PyObject *result = NULL; if (!PyArg_ParseTuple(args, "s:smb1_readlink", &filename)) { + TALLOC_FREE(frame); return NULL; } - req = cli_posix_readlink_send(NULL, self->ev, self->cli, filename); + req = cli_posix_readlink_send(frame, self->ev, self->cli, filename); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } - status = cli_posix_readlink_recv(req, NULL, &target); + status = cli_posix_readlink_recv(req, frame, &target); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } result = PyBytes_FromString(target); - TALLOC_FREE(target); + TALLOC_FREE(frame); return result; } static PyObject *py_smb_smb1_symlink( struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; const char *target = NULL, *newname = NULL; struct tevent_req *req = NULL; if (!PyArg_ParseTuple(args, "ss:smb1_symlink", &target, &newname)) { + TALLOC_FREE(frame); return NULL; } req = cli_posix_symlink_send( - NULL, self->ev, self->cli, target, newname); + frame, self->ev, self->cli, target, newname); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_posix_symlink_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); Py_RETURN_NONE; } static PyObject *py_smb_smb1_stat( struct py_cli_state *self, PyObject *args) { + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; const char *fname = NULL; struct tevent_req *req = NULL; struct stat_ex sbuf = { .st_ex_nlink = 0, }; if (!PyArg_ParseTuple(args, "s:smb1_stat", &fname)) { + TALLOC_FREE(frame); return NULL; } - req = cli_posix_stat_send(NULL, self->ev, self->cli, fname); + req = cli_posix_stat_send(frame, self->ev, self->cli, fname); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_posix_stat_recv(req, &sbuf); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + TALLOC_FREE(frame); return Py_BuildValue( "{sLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsL}", "dev", @@ -2913,6 +3126,7 @@ static PyObject *py_smb_smb1_stat( static PyObject *py_cli_mknod( struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); char *fname = NULL; int mode = 0, major = 0, minor = 0, dev = 0; struct tevent_req *req = NULL; @@ -2932,6 +3146,7 @@ static PyObject *py_cli_mknod( &major, &minor); if (!ok) { + TALLOC_FREE(frame); return NULL; } @@ -2940,22 +3155,27 @@ static PyObject *py_cli_mknod( #endif req = cli_mknod_send( - NULL, self->ev, self->cli, fname, mode, dev); + frame, self->ev, self->cli, fname, mode, dev); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } status = cli_mknod_recv(req); TALLOC_FREE(req); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } + + TALLOC_FREE(frame); Py_RETURN_NONE; } static PyObject *py_cli_fsctl( struct py_cli_state *self, PyObject *args, PyObject *kwds) { + TALLOC_CTX *frame = talloc_stackframe(); int fnum, ctl_code; int max_out = 0; char *buf = NULL; @@ -2981,26 +3201,29 @@ static PyObject *py_cli_fsctl( &buflen, &max_out); if (!ok) { + TALLOC_FREE(frame); return NULL; } in = (DATA_BLOB) { .data = (uint8_t *)buf, .length = buflen, }; req = cli_fsctl_send( - NULL, self->ev, self->cli, fnum, ctl_code, &in, max_out); + frame, self->ev, self->cli, fnum, ctl_code, &in, max_out); if (!py_tevent_req_wait_exc(self, req)) { + TALLOC_FREE(frame); return NULL; } - status = cli_fsctl_recv(req, NULL, &out); + status = cli_fsctl_recv(req, frame, &out); if (!NT_STATUS_IS_OK(status)) { PyErr_SetNTSTATUS(status); + TALLOC_FREE(frame); return NULL; } result = PyBytes_FromStringAndSize((char *)out.data, out.length); - data_blob_free(&out); + TALLOC_FREE(frame); return result; } -- 2.47.3