]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:pylibsmb: add explicit talloc_stackframes to most functions
authorStefan Metzmacher <metze@samba.org>
Tue, 13 May 2025 14:58:14 +0000 (16:58 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Mon, 19 May 2025 09:11:29 +0000 (09:11 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/libsmb/pylibsmb.c

index 19107f9d7fdab19a075cf0f5a97a920df4096c00..d88b0e12c9e093e2de26080a38c3a1dfff7719dc 100644 (file)
@@ -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;
 }