The branch, master has been updated via 00316255984 dsdb: Make a shallow copy of ldb_parse_tree in operational module via 3b51091c20a dsdb: Replace talloc_steal() with a shallow copy and reference in dsdb_paged_results via 1b68bd977af paged_results: add no memory checks in paged_search() via c67534fe3ff selftest: Add test for combination of anr and paged_results via 8f4c1c67b4f vfs_aio_pthread: fix segfault if samba-tool ntacl get from d23dd3e26c5 dsdb: Add tracing to dsdb_search_dn() similar to gendb_search_v()
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 003162559848ce45d4f5bd3fb66642960538120f Author: Andrew Bartlett <abart...@samba.org> Date: Wed Aug 2 14:13:00 2023 +1200 dsdb: Make a shallow copy of ldb_parse_tree in operational module We should not be making modifications to caller memory. In particular, this causes problems for logging of requests if the original request becomes modified. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15442 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Wed Aug 2 12:10:20 UTC 2023 on atb-devel-224 commit 3b51091c20a3c807932bcc986ebb8a676e0ffe6a Author: Andrew Bartlett <abart...@samba.org> Date: Wed Aug 2 14:12:07 2023 +1200 dsdb: Replace talloc_steal() with a shallow copy and reference in dsdb_paged_results We should not be stealing caller memory like this, and while a talloc_reference() is not much better, this combined with a shallow copy should be a little better in terms of polite memory management. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15442 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 1b68bd977af39263a71af2c6a314c5ccb29e348c Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 8 00:41:54 2022 +0100 paged_results: add no memory checks in paged_search() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15442 Signed-off-by: Arvid Requate <requ...@univention.de> Signed-off-by: Stefan Metzmacher <me...@samba.org> Signed-off-by: Andrew Bartlett <abart...@samba.org> [abart...@samba.org combination of two patches by the above authors] commit c67534fe3ff1652dcf95eac2030778b066cdf7a4 Author: Andrew Bartlett <abart...@samba.org> Date: Wed Aug 2 13:40:03 2023 +1200 selftest: Add test for combination of anr and paged_results This combination was known to cause a segfault in Samba 4.13, fixed by 5f0590362c5c0c5ee20503a67467f9be2d50e73b in later versions. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14970 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 8f4c1c67b4f118a9a47b09ac7908cd3d969b19c2 Author: Jones Syue <joness...@qnap.com> Date: Wed Aug 2 09:48:40 2023 +0800 vfs_aio_pthread: fix segfault if samba-tool ntacl get If configured as AD DC and aio_pthread appended into 'vfs objects'[1], run these commands would get segfault: 1. sudo samba-tool ntacl get . 2. sudo net vfs getntacl sysvol . gdb said it goes through aio_pthread_openat_fn() @ vfs_aio_pthread.c[2], and the fsp->conn->sconn->client is null (0x0). 'sconn->client' memory is allocated when a new connection is accpeted: smbd_accept_connection > smbd_process > smbXsrv_client_create While running local commands looks like it would not go through smbXsrv_client_create so the 'client' is null, segfault might happen. We should not dereference 'client->server_multi_channel_enabled', if 'client' is null. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15441 [1] smb.conf example, samba-4.18.5, ubuntu 22.04.2 [global] dns forwarder = 127.0.0.53 netbios name = U22-JONES-88X1 realm = U22-JONES-88X1.X88X1.JONES server role = active directory domain controller workgroup = X88X1 idmap_ldb:use rfc2307 = yes vfs objects = dfs_samba4 acl_xattr aio_pthread [sysvol] path = /var/lib/samba/sysvol read only = No [netlogon] path = /var/lib/samba/sysvol/u22-jones-88x1.x88x1.jones/scripts read only = No [2] gdb (gdb) run /usr/local/samba/bin/samba-tool ntacl get . Starting program: /usr/local/Python3/bin/python3 /usr/local/samba/bin/samba-tool ntacl get . [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Program received signal SIGSEGV, Segmentation fault. 0x00007fffd0eb809e in aio_pthread_openat_fn (handle=0x8d5cc0, dirfsp=0x8c3070, smb_fname=0x18ab4f0, fsp=0x1af3550, flags=196608, mode=0) at ../../source3/modules/vfs_aio_pthread.c:467 warning: Source file is more recent than executable. 467 if (fsp->conn->sconn->client->server_multi_channel_enabled) { (gdb) bt at ../../source3/modules/vfs_aio_pthread.c:467 at ../../source3/smbd/pysmbd.c:320 ---Type <return> to continue, or q <return> to quit--- (gdb) f at ../../source3/modules/vfs_aio_pthread.c:467 467 if (fsp->conn->sconn->client->server_multi_channel_enabled) { (gdb) p fsp->conn->sconn->client $1 = (struct smbXsrv_client *) 0x0 (gdb) Signed-off-by: Jones Syue <joness...@qnap.com> Reviewed-by: Ralph Boehme <s...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/modules/vfs_aio_pthread.c | 3 +- source4/dsdb/samdb/ldb_modules/operational.c | 93 +++++++++++++++++++++++--- source4/dsdb/samdb/ldb_modules/paged_results.c | 39 ++++++++++- source4/dsdb/tests/python/vlv.py | 21 ++++++ 4 files changed, 143 insertions(+), 13 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c index 428ae5f2a4c..0303ff04bc9 100644 --- a/source3/modules/vfs_aio_pthread.c +++ b/source3/modules/vfs_aio_pthread.c @@ -475,7 +475,8 @@ static int aio_pthread_openat_fn(vfs_handle_struct *handle, aio_allow_open = false; } - if (fsp->conn->sconn->client->server_multi_channel_enabled) { + if (fsp->conn->sconn->client != NULL && + fsp->conn->sconn->client->server_multi_channel_enabled) { /* * This module is not compatible with multi channel yet. */ diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c index 8821765a703..5d87a16564f 100644 --- a/source4/dsdb/samdb/ldb_modules/operational.c +++ b/source4/dsdb/samdb/ldb_modules/operational.c @@ -1556,6 +1556,7 @@ struct operational_context { struct ldb_request *req; enum ldb_scope scope; const char * const *attrs; + struct ldb_parse_tree *tree; struct op_controls_flags* controls_flags; struct op_attributes_operations *list_operations; unsigned int list_operations_size; @@ -1681,12 +1682,57 @@ static struct op_attributes_operations* operation_get_op_list(TALLOC_CTX *ctx, return list; } +struct operational_present_ctx { + const char *attr; + bool found_operational; +}; + +/* + callback to determine if an operational attribute (needing + replacement) is in use at all + */ +static int operational_present(struct ldb_parse_tree *tree, void *private_context) +{ + struct operational_present_ctx *ctx = private_context; + switch (tree->operation) { + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + if (ldb_attr_cmp(tree->u.equality.attr, ctx->attr) == 0) { + ctx->found_operational = true; + } + break; + case LDB_OP_SUBSTRING: + if (ldb_attr_cmp(tree->u.substring.attr, ctx->attr) == 0) { + ctx->found_operational = true; + } + break; + case LDB_OP_PRESENT: + if (ldb_attr_cmp(tree->u.present.attr, ctx->attr) == 0) { + ctx->found_operational = true; + } + break; + case LDB_OP_EXTENDED: + if (tree->u.extended.attr && + ldb_attr_cmp(tree->u.extended.attr, ctx->attr) == 0) { + ctx->found_operational = true; + } + break; + default: + break; + } + return LDB_SUCCESS; +} + + static int operational_search(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb; struct operational_context *ac; struct ldb_request *down_req; const char **search_attrs = NULL; + struct operational_present_ctx ctx; unsigned int i, a; int ret; @@ -1707,15 +1753,44 @@ static int operational_search(struct ldb_module *module, struct ldb_request *req ac->scope = req->op.search.scope; ac->attrs = req->op.search.attrs; - /* FIXME: We must copy the tree and keep the original - * unmodified. SSS */ - /* replace any attributes in the parse tree that are - searchable, but are stored using a different name in the - backend */ + ctx.found_operational = false; + + /* + * find any attributes in the parse tree that are searchable, + * but are stored using a different name in the backend, so we + * only duplicate the memory when needed + */ for (i=0;i<ARRAY_SIZE(parse_tree_sub);i++) { - ldb_parse_tree_attr_replace(req->op.search.tree, - parse_tree_sub[i].attr, - parse_tree_sub[i].replace); + ctx.attr = parse_tree_sub[i].attr; + + ldb_parse_tree_walk(req->op.search.tree, + operational_present, + &ctx); + if (ctx.found_operational) { + break; + } + } + + if (ctx.found_operational) { + + ac->tree = ldb_parse_tree_copy_shallow(ac, + req->op.search.tree); + + if (ac->tree == NULL) { + return ldb_operr(ldb); + } + + /* replace any attributes in the parse tree that are + searchable, but are stored using a different name in the + backend */ + for (i=0;i<ARRAY_SIZE(parse_tree_sub);i++) { + ldb_parse_tree_attr_replace(ac->tree, + parse_tree_sub[i].attr, + parse_tree_sub[i].replace); + } + } else { + /* Avoid allocating a copy if we do not need to */ + ac->tree = req->op.search.tree; } ac->controls_flags = talloc(ac, struct op_controls_flags); @@ -1795,7 +1870,7 @@ static int operational_search(struct ldb_module *module, struct ldb_request *req ret = ldb_build_search_req_ex(&down_req, ldb, ac, req->op.search.base, req->op.search.scope, - req->op.search.tree, + ac->tree, /* use new set of attrs if any */ search_attrs == NULL?req->op.search.attrs:search_attrs, req->controls, diff --git a/source4/dsdb/samdb/ldb_modules/paged_results.c b/source4/dsdb/samdb/ldb_modules/paged_results.c index 2063e84e157..83729b02c0b 100644 --- a/source4/dsdb/samdb/ldb_modules/paged_results.c +++ b/source4/dsdb/samdb/ldb_modules/paged_results.c @@ -681,6 +681,7 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req) struct ldb_control *ext_ctrl; struct ldb_control **controls; static const char * const attrs[1] = { NULL }; + void *ref = NULL; if (paged_ctrl->size == 0) { return LDB_ERR_OPERATIONS_ERROR; @@ -705,9 +706,15 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req) struct ldb_request *req_extended_dn; struct ldb_extended_dn_control *ext_ctrl_data; req_extended_dn = talloc_zero(req, struct ldb_request); + if (req_extended_dn == NULL) { + return ldb_module_oom(module); + } req_extended_dn->controls = req->controls; ext_ctrl_data = talloc_zero(req, struct ldb_extended_dn_control); + if (ext_ctrl_data == NULL) { + return ldb_module_oom(module); + } ext_ctrl_data->type = 1; ret = ldb_request_add_control(req_extended_dn, @@ -733,11 +740,37 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req) return ret; } - ac->store->expr = talloc_steal(ac->store, req->op.search.tree); + /* + * LDB does not have a function to take a full copy of + * this, but at least take a shallow copy + */ + ac->store->expr = ldb_parse_tree_copy_shallow(ac->store, + req->op.search.tree); + + if (ac->store->expr == NULL) { + return ldb_operr(ldb); + } + + /* + * As the above is only a shallow copy, take a + * reference to ensure the values are kept around + */ + ref = talloc_reference(ac->store, req->op.search.tree); + if (ref == NULL) { + return ldb_module_oom(module); + } ac->store->expr_str = ldb_filter_from_tree(ac->store, req->op.search.tree); - ac->store->attrs = paged_copy_attrs(ac->store, - req->op.search.attrs); + if (ac->store->expr_str == NULL) { + return ldb_module_oom(module); + } + if (req->op.search.attrs != NULL) { + ac->store->attrs = paged_copy_attrs(ac->store, + req->op.search.attrs); + if (ac->store->attrs == NULL) { + return ldb_module_oom(module); + } + } /* save it locally and remove it from the list */ /* we do not need to replace them later as we diff --git a/source4/dsdb/tests/python/vlv.py b/source4/dsdb/tests/python/vlv.py index 33b51557ed3..13fccba75c9 100644 --- a/source4/dsdb/tests/python/vlv.py +++ b/source4/dsdb/tests/python/vlv.py @@ -1754,6 +1754,27 @@ class PagedResultsTestsRW(PagedResultsTests): (enum, estr) = e.args self.assertEqual(enum, ldb.ERR_UNSUPPORTED_CRITICAL_EXTENSION) + def test_anr_paged(self): + """Testing behaviour with anr= searches and paged_results set. + + A problematic combination, as anr involves filter rewriting + + """ + prefix = "anr" + num_users = 5 + users = [self.create_user(i, num_users, prefix=prefix) + for i in range(num_users)] + expr = f"(|(anr={prefix})(&(objectClass=user)(facsimileTelephoneNumber={prefix}*)))" + + results, cookie = self.paged_search(expr, page_size=1) + self.assertEqual(len(results), 1) + + results, cookie = self.paged_search(expr, page_size=2, cookie=cookie) + self.assertEqual(len(results), 2) + + results, cookie = self.paged_search(expr, page_size=2, cookie=cookie) + self.assertEqual(len(results), 2) + if "://" not in host: if os.path.isfile(host): -- Samba Shared Repository