Update to version 4.21.1

- resolves: rhbz#2318518
This commit is contained in:
Pavel Filipenský 2024-10-14 14:29:04 +02:00
parent 92d190c9b6
commit 2535a64d34
6 changed files with 517 additions and 480 deletions

View File

@ -1,286 +0,0 @@
From e2d3bf09d6d75c7dc009aff36119e51ea59371fc Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 25 Sep 2024 09:19:17 +0200
Subject: [PATCH 1/4] lib:ldb: Remove trailing spaces from ldb_modules.c
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15643
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit 8d6b5183770895fef002b6cce84902d1874fa502)
---
lib/ldb/common/ldb_modules.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/lib/ldb/common/ldb_modules.c b/lib/ldb/common/ldb_modules.c
index b5627b0d04f..5c970626206 100644
--- a/lib/ldb/common/ldb_modules.c
+++ b/lib/ldb/common/ldb_modules.c
@@ -631,9 +631,9 @@ int ldb_next_start_trans(struct ldb_module *module)
/* Set a default error string, to place the blame somewhere */
ldb_asprintf_errstring(module->ldb, "start_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
}
- if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
- ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_start_trans error: %s",
- ldb_errstring(module->ldb));
+ if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_start_trans error: %s",
+ ldb_errstring(module->ldb));
}
return ret;
}
@@ -650,9 +650,9 @@ int ldb_next_end_trans(struct ldb_module *module)
/* Set a default error string, to place the blame somewhere */
ldb_asprintf_errstring(module->ldb, "end_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
}
- if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
- ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_end_trans error: %s",
- ldb_errstring(module->ldb));
+ if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_end_trans error: %s",
+ ldb_errstring(module->ldb));
}
return ret;
}
@@ -720,9 +720,9 @@ int ldb_next_prepare_commit(struct ldb_module *module)
/* Set a default error string, to place the blame somewhere */
ldb_asprintf_errstring(module->ldb, "prepare_commit error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
}
- if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
- ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_prepare_commit error: %s",
- ldb_errstring(module->ldb));
+ if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_prepare_commit error: %s",
+ ldb_errstring(module->ldb));
}
return ret;
}
@@ -739,9 +739,9 @@ int ldb_next_del_trans(struct ldb_module *module)
/* Set a default error string, to place the blame somewhere */
ldb_asprintf_errstring(module->ldb, "del_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
}
- if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
- ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_del_trans error: %s",
- ldb_errstring(module->ldb));
+ if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_del_trans error: %s",
+ ldb_errstring(module->ldb));
}
return ret;
}
@@ -777,17 +777,17 @@ int ldb_module_send_entry(struct ldb_request *req,
req->handle->nesting == 0) {
char *s;
struct ldb_ldif ldif;
-
+
ldif.changetype = LDB_CHANGETYPE_NONE;
ldif.msg = discard_const_p(struct ldb_message, msg);
ldb_debug_add(req->handle->ldb, "ldb_trace_response: ENTRY\n");
- /*
+ /*
* The choice to call
* ldb_ldif_write_redacted_trace_string() is CRITICAL
* for security. It ensures that we do not output
- * passwords into debug logs
+ * passwords into debug logs
*/
s = ldb_ldif_write_redacted_trace_string(req->handle->ldb, msg, &ldif);
@@ -1104,8 +1104,8 @@ static int ldb_modules_load_dir(const char *modules_dir, const char *version)
return LDB_SUCCESS;
}
-/*
- load any additional modules from the given directory
+/*
+ load any additional modules from the given directory
*/
void ldb_set_modules_dir(struct ldb_context *ldb, const char *path)
{
--
2.46.1
From d0ec464cfced2654d74672846d83c19f69af622b Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 25 Sep 2024 09:19:44 +0200
Subject: [PATCH 2/4] lib:ldb: Don't use RTLD_DEEPBIND by default
It should be off by default, as this is not needed by default. It
crashes named on startup, if bind is built with jemalloc support.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15643
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit dc6927fdca2ad77dbcf212ef4d3ba0d118ec7bdf)
---
lib/ldb/common/ldb_modules.c | 21 ++++++---------------
selftest/selftest.pl | 6 ------
selftest/wscript | 5 ++---
3 files changed, 8 insertions(+), 24 deletions(-)
diff --git a/lib/ldb/common/ldb_modules.c b/lib/ldb/common/ldb_modules.c
index 5c970626206..08d251f9bdd 100644
--- a/lib/ldb/common/ldb_modules.c
+++ b/lib/ldb/common/ldb_modules.c
@@ -945,7 +945,7 @@ static int ldb_modules_load_path(const char *path, const char *version)
int dlopen_flags;
#ifdef RTLD_DEEPBIND
- bool deepbind_enabled = (getenv("LDB_MODULES_DISABLE_DEEPBIND") == NULL);
+ bool deepbind_enabled = (getenv("LDB_MODULES_ENABLE_DEEPBIND") != NULL);
#endif
ret = stat(path, &st);
@@ -981,21 +981,12 @@ static int ldb_modules_load_path(const char *path, const char *version)
dlopen_flags = RTLD_NOW;
#ifdef RTLD_DEEPBIND
/*
- * use deepbind if possible, to avoid issues with different
- * system library variants, for example ldb modules may be linked
- * against Heimdal while the application may use MIT kerberos.
+ * On systems where e.g. different kerberos libraries are used, like a
+ * mix of Heimdal and MIT Kerberos, LDB_MODULES_ENABLE_DEEPBIND should
+ * be set to avoid issues.
*
- * See the dlopen manpage for details.
- *
- * One typical user is the bind_dlz module of Samba,
- * but symbol versioning might be enough...
- *
- * We need a way to disable this in order to allow the
- * ldb_*ldap modules to work with a preloaded socket wrapper.
- *
- * So in future we may remove this completely
- * or at least invert the default behavior.
- */
+ * By default Linux distributions only have one Kerberos library.
+ */
if (deepbind_enabled) {
dlopen_flags |= RTLD_DEEPBIND;
}
diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index 26b1663b5b6..a0c4ec80f59 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -433,12 +433,6 @@ $ENV{UID_WRAPPER} = 1;
# We are already hitting the limit, so double it.
$ENV{NSS_WRAPPER_MAX_HOSTENTS} = 200;
-# Disable RTLD_DEEPBIND hack for Samba bind dlz module
-#
-# This is needed in order to allow the ldb_*ldap module
-# to work with a preloaded socket wrapper.
-$ENV{LDB_MODULES_DISABLE_DEEPBIND} = 1;
-
my $socket_wrapper_dir;
if ($opt_socket_wrapper) {
$socket_wrapper_dir = SocketWrapper::setup_dir("$prefix_abs/w", $opt_socket_wrapper_pcap);
diff --git a/selftest/wscript b/selftest/wscript
index 52c34dcb88d..95e70706e63 100644
--- a/selftest/wscript
+++ b/selftest/wscript
@@ -333,9 +333,8 @@ def cmd_testonly(opt):
asan_options += ":suppressions=${srcdir}/selftest/sanitizer/asan.supp"
asan_options += " "
- # And we need to disable RTLD_DEEPBIND in ldb and socket wrapper
- no_leak_check = "LDB_MODULES_DISABLE_DEEPBIND=1 "
- no_leak_check += "SOCKET_WRAPPER_DISABLE_DEEP_BIND=1"
+ # We need to disable RTLD_DEEPBIND in socket wrapper
+ no_leak_check = "SOCKET_WRAPPER_DISABLE_DEEP_BIND=1"
no_leak_check += " "
env.CORE_COMMAND = asan_options + no_leak_check + env.CORE_COMMAND
--
2.46.1
From e6745b1444b28904258710dff1dddd18a8b9f662 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 25 Sep 2024 09:40:23 +0200
Subject: [PATCH 3/4] lib:ldb: Remove trailing spaces from ldb.3.xml
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15643
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit d6ff05cb5708fb6746176821bee5f713195efa54)
---
lib/ldb/man/ldb.3.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/ldb/man/ldb.3.xml b/lib/ldb/man/ldb.3.xml
index 1c0a2ece552..1dd8b2462d4 100644
--- a/lib/ldb/man/ldb.3.xml
+++ b/lib/ldb/man/ldb.3.xml
@@ -247,7 +247,7 @@ ldb_search(3) manual pages.
<title>Author</title>
<para>
- ldb was written by
+ ldb was written by
<ulink url="https://www.samba.org/~tridge/">Andrew Tridgell</ulink>.
</para>
--
2.46.1
From ba9918d45820fbdb864b5a1e058136eeb0cf1ce7 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 25 Sep 2024 09:22:08 +0200
Subject: [PATCH 4/4] lib:ldb: Document environment variables in ldb manpage
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15643
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Fri Sep 27 09:06:43 UTC 2024 on atb-devel-224
(cherry picked from commit 20a3a94e06a2294206ec233ccc7f873d6ef2aca0)
---
lib/ldb/man/ldb.3.xml | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/lib/ldb/man/ldb.3.xml b/lib/ldb/man/ldb.3.xml
index 1dd8b2462d4..f8d3cb50446 100644
--- a/lib/ldb/man/ldb.3.xml
+++ b/lib/ldb/man/ldb.3.xml
@@ -243,6 +243,27 @@ ldb_search(3) manual pages.
</itemizedlist>
</refsect1>
+<refsect1>
+ <title>ENVIRONMENT VARIABLES</title>
+
+ <itemizedlist>
+ <listitem><para>
+ <envar>LDB_URL</envar>
+ - connect to the provided URL (cmdline tools only)
+ </para></listitem>
+
+ <listitem><para>
+ <envar>LDB_MODULES_PATH</envar>
+ - path where to load ldb modules from
+ </para></listitem>
+
+ <listitem><para>
+ <envar>LDB_MODULES_ENABLE_DEEPBIND</envar>
+ - enable RTLD_DEEPBIND when loading ldb modules
+ </para></listitem>
+ </itemizedlist>
+</refsect1>
+
<refsect1>
<title>Author</title>
--
2.46.1

View File

@ -1,132 +0,0 @@
From 26797d7bd2662718b3eb795f1b8e6100d51e3ab7 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab@samba.org>
Date: Tue, 3 Sep 2024 08:48:24 +0300
Subject: [PATCH] sync machine password to keytab: handle FreeIPA use case
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
FreeIPA uses own procedure to retrieve keytabs and during the setup of
Samba on FreeIPA client the keytab is already present, only machine
account needs to be set in the secrets database.
'sync machine password to keytab' option handling broke this use case by
always attempting to contact a domain controller and failing to do so
(Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=2309199).
The original synchronizing machine account password to keytab feature
did not have a mechanism to disable its logic at all.
Signed-off-by: Alexander Bokovoy <ab@samba.org>
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
Autobuild-User(master): Alexander Bokovoy <ab@samba.org>
Autobuild-Date(master): Fri Sep 13 13:16:09 UTC 2024 on atb-devel-224
(cherry picked from commit 4f577c7b6894132be4842944f2f950b087312b16)
---
.../security/syncmachinepasswordtokeytab.xml | 29 +++++++++++++++++--
source3/libads/kerberos_keytab.c | 5 ++++
source3/utils/net.c | 8 +++++
source3/utils/testparm.c | 3 +-
4 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/docs-xml/smbdotconf/security/syncmachinepasswordtokeytab.xml b/docs-xml/smbdotconf/security/syncmachinepasswordtokeytab.xml
index 4cad9da73f2..f7dc30023d4 100644
--- a/docs-xml/smbdotconf/security/syncmachinepasswordtokeytab.xml
+++ b/docs-xml/smbdotconf/security/syncmachinepasswordtokeytab.xml
@@ -18,7 +18,11 @@ or by winbindd doing regular updates (see <smbconfoption name="machine password
</para>
<para>
-The option takes a list of keytab strings. Each string has this form:
+The option takes a list of keytab strings to describe how to synchronize
+content of those keytabs or a single 'disabled' value to disable the
+synchronization.
+
+Each string has this form:
<programlisting>
absolute_path_to_keytab:spn_spec[:sync_etypes][:sync_kvno][:netbios_aliases][:additional_dns_hostnames][:machine_password]
</programlisting>
@@ -70,8 +74,27 @@ If sync_etypes or sync_kvno or sync_spns is present then winbind connects to DC.
</para>
<para>
-If no value is present, winbind uses value <programlisting>/path/to/keytab:sync_spns:sync_kvno:machine_password</programlisting>
-where the path to the keytab is obtained either from the krb5 library or from <smbconfoption name="dedicated keytab file"/>
+If no value is present and <smbconfoption name="kerberos method"/> is different from
+'secrets only', the behavior differs between winbind and net utility:
+</para>
+<itemizedlist>
+ <listitem>
+ <para><userinput>winbind</userinput> uses value
+ <programlisting>/path/to/keytab:sync_spns:sync_kvno:machine_password</programlisting>
+ where the path to the keytab is obtained either from the krb5 library or from
+ <smbconfoption name="dedicated keytab file"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><userinput>net changesecretpw -f</userinput> command uses the default 'disabled' value.</para>
+ </listitem>
+ <listitem><para>No other <userinput>net</userinput> subcommands use the 'disabled' value.</para></listitem>
+</itemizedlist>
+
+<para>
+If a single value 'disabled' is present, the synchronization process is
+disabled. This is required for FreeIPA domain member setup where keytab
+synchronization uses a protocol not implemented by Samba.
</para>
<para>
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 6ede567b75f..dbf8af44c1f 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -904,6 +904,11 @@ NTSTATUS sync_pw2keytabs(void)
goto params_ready;
}
+ if ((*lp_ptr != NULL) && strequal_m(*lp_ptr, "disabled")) {
+ DBG_DEBUG("'sync machine password to keytab' is explicitly disabled.\n");
+ return NT_STATUS_OK;
+ }
+
line = lp_ptr;
while (*line) {
DBG_DEBUG("Scanning line: %s\n", *line);
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 7b40d2bee95..c432ebe991f 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -207,6 +207,14 @@ static int net_changesecretpw(struct net_context *c, int argc,
struct timeval tv = timeval_current();
NTTIME now = timeval_to_nttime(&tv);
+#ifdef HAVE_ADS
+ if (USE_KERBEROS_KEYTAB) {
+ if (lp_sync_machine_password_to_keytab() == NULL) {
+ lp_do_parameter(-1, "sync machine password to keytab", "disabled");
+ }
+ }
+#endif
+
if (c->opt_stdin) {
set_line_buffering(stdin);
set_line_buffering(stdout);
diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
index e3ed336a79a..a31a7a8a30a 100644
--- a/source3/utils/testparm.c
+++ b/source3/utils/testparm.c
@@ -803,7 +803,8 @@ static int do_global_checks(void)
"instead of 'kerberos method'.\n\n");
}
- if (lp_ptr != NULL) {
+ if (lp_ptr != NULL &&
+ ((*lp_ptr != NULL) && !strequal_m(*lp_ptr, "disabled"))) {
while (*lp_ptr) {
ret |= pw2kt_check_line(*lp_ptr++);
}
--
2.46.0

View File

@ -1,55 +0,0 @@
From 9f265d6f3b852a9eed9f19147585fe2801507f63 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Tue, 24 Sep 2024 15:48:23 +0200
Subject: [PATCH] ldb: Build lmdb backend also in non-AD case
We should build with lmdb support also if it is not in AD case. The lmdb
backend is also used e.g. by sssd.
If you don't want to build it, you can always specify --without-ldb-lmdb
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15721
Signed-off-by: Andreas Schneider <asn@samba.org>
---
lib/ldb/wscript | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index 87aa3bb6d77..f234fa79c10 100644
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -33,21 +33,17 @@ def configure(conf):
conf.CONFIG_GET('ENABLE_SELFTEST'):
Logs.warn("NOTE: Some AD DC parts of selftest will fail")
+ conf.env.REQUIRE_LMDB = False
+ elif Options.options.without_ldb_lmdb:
+ if not Options.options.without_ad_dc and \
+ conf.CONFIG_GET('ENABLE_SELFTEST'):
+ raise Errors.WafError('--without-ldb-lmdb conflicts '
+ 'with --enable-selftest while '
+ 'building the AD DC')
+
conf.env.REQUIRE_LMDB = False
else:
- if Options.options.without_ad_dc:
- conf.env.REQUIRE_LMDB = False
- else:
- if Options.options.without_ldb_lmdb:
- if not Options.options.without_ad_dc and \
- conf.CONFIG_GET('ENABLE_SELFTEST'):
- raise Errors.WafError('--without-ldb-lmdb conflicts '
- 'with --enable-selftest while '
- 'building the AD DC')
-
- conf.env.REQUIRE_LMDB = False
- else:
- conf.env.REQUIRE_LMDB = True
+ conf.env.REQUIRE_LMDB = True
# if lmdb support is enabled then we require lmdb
# is present, build the mdb back end and enable lmdb support in
--
GitLab

View File

@ -0,0 +1,513 @@
From c9a7bc3e8f36cb9d6746e23ea56f9c27b82dcf49 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Mon, 22 Jul 2024 12:26:55 +0200
Subject: [PATCH] s3:notifyd: Use a watcher per db record
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This fixes a O(n²) performance regression in notifyd. The problem was
that we had a watcher per notify instance. This changes the code to have
a watcher per notify db entry.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14430
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit af011b987a4ad0d3753d83cc0b8d97ad64ba874a)
---
source3/smbd/notifyd/notifyd.c | 214 ++++++++++++++++++-------
source3/smbd/notifyd/notifyd_db.c | 5 +-
source3/smbd/notifyd/notifyd_entry.c | 51 ++++--
source3/smbd/notifyd/notifyd_private.h | 46 ++++--
4 files changed, 228 insertions(+), 88 deletions(-)
diff --git a/source3/smbd/notifyd/notifyd.c b/source3/smbd/notifyd/notifyd.c
index 64dd26a7e11..0b07ab3e435 100644
--- a/source3/smbd/notifyd/notifyd.c
+++ b/source3/smbd/notifyd/notifyd.c
@@ -337,6 +337,7 @@ static bool notifyd_apply_rec_change(
struct messaging_context *msg_ctx)
{
struct db_record *rec = NULL;
+ struct notifyd_watcher watcher = {};
struct notifyd_instance *instances = NULL;
size_t num_instances;
size_t i;
@@ -344,6 +345,7 @@ static bool notifyd_apply_rec_change(
TDB_DATA value;
NTSTATUS status;
bool ok = false;
+ bool new_watcher = false;
if (pathlen == 0) {
DBG_WARNING("pathlen==0\n");
@@ -374,8 +376,12 @@ static bool notifyd_apply_rec_change(
value = dbwrap_record_get_value(rec);
if (value.dsize != 0) {
- if (!notifyd_parse_entry(value.dptr, value.dsize, NULL,
- &num_instances)) {
+ ok = notifyd_parse_entry(value.dptr,
+ value.dsize,
+ &watcher,
+ NULL,
+ &num_instances);
+ if (!ok) {
goto fail;
}
}
@@ -390,8 +396,22 @@ static bool notifyd_apply_rec_change(
goto fail;
}
- if (value.dsize != 0) {
- memcpy(instances, value.dptr, value.dsize);
+ if (num_instances > 0) {
+ struct notifyd_instance *tmp = NULL;
+ size_t num_tmp = 0;
+
+ ok = notifyd_parse_entry(value.dptr,
+ value.dsize,
+ NULL,
+ &tmp,
+ &num_tmp);
+ if (!ok) {
+ goto fail;
+ }
+
+ memcpy(instances,
+ tmp,
+ sizeof(struct notifyd_instance) * num_tmp);
}
for (i=0; i<num_instances; i++) {
@@ -414,41 +434,106 @@ static bool notifyd_apply_rec_change(
*instance = (struct notifyd_instance) {
.client = *client,
.instance = *chg,
- .internal_filter = chg->filter,
- .internal_subdir_filter = chg->subdir_filter
};
num_instances += 1;
}
- if ((instance->instance.filter != 0) ||
- (instance->instance.subdir_filter != 0)) {
- int ret;
+ /*
+ * Calculate an intersection of the instances filters for the watcher.
+ */
+ if (instance->instance.filter > 0) {
+ uint32_t filter = instance->instance.filter;
+
+ if ((watcher.filter & filter) != filter) {
+ watcher.filter |= filter;
+
+ new_watcher = true;
+ }
+ }
+
+ /*
+ * Calculate an intersection of the instances subdir_filters for the
+ * watcher.
+ */
+ if (instance->instance.subdir_filter > 0) {
+ uint32_t subdir_filter = instance->instance.subdir_filter;
- TALLOC_FREE(instance->sys_watch);
+ if ((watcher.subdir_filter & subdir_filter) != subdir_filter) {
+ watcher.subdir_filter |= subdir_filter;
- ret = sys_notify_watch(entries, sys_notify_ctx, path,
- &instance->internal_filter,
- &instance->internal_subdir_filter,
- notifyd_sys_callback, msg_ctx,
- &instance->sys_watch);
- if (ret != 0) {
- DBG_WARNING("sys_notify_watch for [%s] returned %s\n",
- path, strerror(errno));
+ new_watcher = true;
}
}
if ((instance->instance.filter == 0) &&
(instance->instance.subdir_filter == 0)) {
+ uint32_t tmp_filter = 0;
+ uint32_t tmp_subdir_filter = 0;
+
/* This is a delete request */
- TALLOC_FREE(instance->sys_watch);
*instance = instances[num_instances-1];
num_instances -= 1;
+
+ for (i = 0; i < num_instances; i++) {
+ struct notifyd_instance *tmp = &instances[i];
+
+ tmp_filter |= tmp->instance.filter;
+ tmp_subdir_filter |= tmp->instance.subdir_filter;
+ }
+
+ /*
+ * If the filter has changed, register a new watcher with the
+ * changed filter.
+ */
+ if (watcher.filter != tmp_filter ||
+ watcher.subdir_filter != tmp_subdir_filter)
+ {
+ watcher.filter = tmp_filter;
+ watcher.subdir_filter = tmp_subdir_filter;
+
+ new_watcher = true;
+ }
+ }
+
+ if (new_watcher) {
+ /*
+ * In case we removed all notify instances, we want to remove
+ * the watcher. We won't register a new one, if no filters are
+ * set anymore.
+ */
+
+ TALLOC_FREE(watcher.sys_watch);
+
+ watcher.sys_filter = watcher.filter;
+ watcher.sys_subdir_filter = watcher.subdir_filter;
+
+ /*
+ * Only register a watcher if we have filter.
+ */
+ if (watcher.filter != 0 || watcher.subdir_filter != 0) {
+ int ret = sys_notify_watch(entries,
+ sys_notify_ctx,
+ path,
+ &watcher.sys_filter,
+ &watcher.sys_subdir_filter,
+ notifyd_sys_callback,
+ msg_ctx,
+ &watcher.sys_watch);
+ if (ret != 0) {
+ DBG_WARNING("sys_notify_watch for [%s] "
+ "returned %s\n",
+ path,
+ strerror(errno));
+ }
+ }
}
DBG_DEBUG("%s has %zu instances\n", path, num_instances);
if (num_instances == 0) {
+ TALLOC_FREE(watcher.sys_watch);
+
status = dbwrap_record_delete(rec);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("dbwrap_record_delete returned %s\n",
@@ -456,13 +541,21 @@ static bool notifyd_apply_rec_change(
goto fail;
}
} else {
- value = make_tdb_data(
- (uint8_t *)instances,
- sizeof(struct notifyd_instance) * num_instances);
+ struct TDB_DATA iov[2] = {
+ {
+ .dptr = (uint8_t *)&watcher,
+ .dsize = sizeof(struct notifyd_watcher),
+ },
+ {
+ .dptr = (uint8_t *)instances,
+ .dsize = sizeof(struct notifyd_instance) *
+ num_instances,
+ },
+ };
- status = dbwrap_record_store(rec, value, 0);
+ status = dbwrap_record_storev(rec, iov, ARRAY_SIZE(iov), 0);
if (!NT_STATUS_IS_OK(status)) {
- DBG_WARNING("dbwrap_record_store returned %s\n",
+ DBG_WARNING("dbwrap_record_storev returned %s\n",
nt_errstr(status));
goto fail;
}
@@ -706,12 +799,18 @@ static void notifyd_trigger_parser(TDB_DATA key, TDB_DATA data,
.when = tstate->msg->when };
struct iovec iov[2];
size_t path_len = key.dsize;
+ struct notifyd_watcher watcher = {};
struct notifyd_instance *instances = NULL;
size_t num_instances = 0;
size_t i;
+ bool ok;
- if (!notifyd_parse_entry(data.dptr, data.dsize, &instances,
- &num_instances)) {
+ ok = notifyd_parse_entry(data.dptr,
+ data.dsize,
+ &watcher,
+ &instances,
+ &num_instances);
+ if (!ok) {
DBG_DEBUG("Could not parse notifyd_entry\n");
return;
}
@@ -734,9 +833,11 @@ static void notifyd_trigger_parser(TDB_DATA key, TDB_DATA data,
if (tstate->covered_by_sys_notify) {
if (tstate->recursive) {
- i_filter = instance->internal_subdir_filter;
+ i_filter = watcher.sys_subdir_filter &
+ instance->instance.subdir_filter;
} else {
- i_filter = instance->internal_filter;
+ i_filter = watcher.sys_filter &
+ instance->instance.filter;
}
} else {
if (tstate->recursive) {
@@ -1146,46 +1247,39 @@ static int notifyd_add_proxy_syswatches(struct db_record *rec,
struct db_context *db = dbwrap_record_get_db(rec);
TDB_DATA key = dbwrap_record_get_key(rec);
TDB_DATA value = dbwrap_record_get_value(rec);
- struct notifyd_instance *instances = NULL;
- size_t num_instances = 0;
- size_t i;
+ struct notifyd_watcher watcher = {};
char path[key.dsize+1];
bool ok;
+ int ret;
memcpy(path, key.dptr, key.dsize);
path[key.dsize] = '\0';
- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances,
- &num_instances);
+ /* This is a remote database, we just need the watcher. */
+ ok = notifyd_parse_entry(value.dptr, value.dsize, &watcher, NULL, NULL);
if (!ok) {
DBG_WARNING("Could not parse notifyd entry for %s\n", path);
return 0;
}
- for (i=0; i<num_instances; i++) {
- struct notifyd_instance *instance = &instances[i];
- uint32_t filter = instance->instance.filter;
- uint32_t subdir_filter = instance->instance.subdir_filter;
- int ret;
+ watcher.sys_watch = NULL;
+ watcher.sys_filter = watcher.filter;
+ watcher.sys_subdir_filter = watcher.subdir_filter;
- /*
- * This is a remote database. Pointers that we were
- * given don't make sense locally. Initialize to NULL
- * in case sys_notify_watch fails.
- */
- instances[i].sys_watch = NULL;
-
- ret = state->sys_notify_watch(
- db, state->sys_notify_ctx, path,
- &filter, &subdir_filter,
- notifyd_sys_callback, state->msg_ctx,
- &instance->sys_watch);
- if (ret != 0) {
- DBG_WARNING("inotify_watch returned %s\n",
- strerror(errno));
- }
+ ret = state->sys_notify_watch(db,
+ state->sys_notify_ctx,
+ path,
+ &watcher.filter,
+ &watcher.subdir_filter,
+ notifyd_sys_callback,
+ state->msg_ctx,
+ &watcher.sys_watch);
+ if (ret != 0) {
+ DBG_WARNING("inotify_watch returned %s\n", strerror(errno));
}
+ memcpy(value.dptr, &watcher, sizeof(struct notifyd_watcher));
+
return 0;
}
@@ -1193,21 +1287,17 @@ static int notifyd_db_del_syswatches(struct db_record *rec, void *private_data)
{
TDB_DATA key = dbwrap_record_get_key(rec);
TDB_DATA value = dbwrap_record_get_value(rec);
- struct notifyd_instance *instances = NULL;
- size_t num_instances = 0;
- size_t i;
+ struct notifyd_watcher watcher = {};
bool ok;
- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances,
- &num_instances);
+ ok = notifyd_parse_entry(value.dptr, value.dsize, &watcher, NULL, NULL);
if (!ok) {
DBG_WARNING("Could not parse notifyd entry for %.*s\n",
(int)key.dsize, (char *)key.dptr);
return 0;
}
- for (i=0; i<num_instances; i++) {
- TALLOC_FREE(instances[i].sys_watch);
- }
+ TALLOC_FREE(watcher.sys_watch);
+
return 0;
}
diff --git a/source3/smbd/notifyd/notifyd_db.c b/source3/smbd/notifyd/notifyd_db.c
index 18228619e9a..7dc3cd58081 100644
--- a/source3/smbd/notifyd/notifyd_db.c
+++ b/source3/smbd/notifyd/notifyd_db.c
@@ -40,7 +40,10 @@ static bool notifyd_parse_db_parser(TDB_DATA key, TDB_DATA value,
memcpy(path, key.dptr, key.dsize);
path[key.dsize] = 0;
- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances,
+ ok = notifyd_parse_entry(value.dptr,
+ value.dsize,
+ NULL,
+ &instances,
&num_instances);
if (!ok) {
DBG_DEBUG("Could not parse entry for path %s\n", path);
diff --git a/source3/smbd/notifyd/notifyd_entry.c b/source3/smbd/notifyd/notifyd_entry.c
index 539010de03a..f3b0e908136 100644
--- a/source3/smbd/notifyd/notifyd_entry.c
+++ b/source3/smbd/notifyd/notifyd_entry.c
@@ -21,22 +21,51 @@
* Parse an entry in the notifyd_context->entries database
*/
-bool notifyd_parse_entry(
- uint8_t *buf,
- size_t buflen,
- struct notifyd_instance **instances,
- size_t *num_instances)
+/**
+ * @brief Parse a notifyd database entry.
+ *
+ * The memory we pass down needs to be aligned. If it isn't aligned we can run
+ * into obscure errors as we just point into the data buffer.
+ *
+ * @param data The data to parse
+ * @param data_len The length of the data to parse
+ * @param watcher A pointer to store the watcher data or NULL.
+ * @param instances A pointer to store the array of notify instances or NULL.
+ * @param pnum_instances The number of elements in the array. If you just want
+ * the number of elements pass NULL for the watcher and instances pointers.
+ *
+ * @return true on success, false if an error occurred.
+ */
+bool notifyd_parse_entry(uint8_t *data,
+ size_t data_len,
+ struct notifyd_watcher *watcher,
+ struct notifyd_instance **instances,
+ size_t *pnum_instances)
{
- if ((buflen % sizeof(struct notifyd_instance)) != 0) {
- DBG_WARNING("invalid buffer size: %zu\n", buflen);
+ size_t ilen;
+
+ if (data_len < sizeof(struct notifyd_watcher)) {
return false;
}
- if (instances != NULL) {
- *instances = (struct notifyd_instance *)buf;
+ if (watcher != NULL) {
+ *watcher = *((struct notifyd_watcher *)(uintptr_t)data);
}
- if (num_instances != NULL) {
- *num_instances = buflen / sizeof(struct notifyd_instance);
+
+ ilen = data_len - sizeof(struct notifyd_watcher);
+ if ((ilen % sizeof(struct notifyd_instance)) != 0) {
+ return false;
+ }
+
+ if (pnum_instances != NULL) {
+ *pnum_instances = ilen / sizeof(struct notifyd_instance);
}
+ if (instances != NULL) {
+ /* The (uintptr_t) cast removes a warning from -Wcast-align. */
+ *instances =
+ (struct notifyd_instance *)(uintptr_t)
+ (data + sizeof(struct notifyd_watcher));
+ }
+
return true;
}
diff --git a/source3/smbd/notifyd/notifyd_private.h b/source3/smbd/notifyd/notifyd_private.h
index 36c08f47c54..db8e6e1c005 100644
--- a/source3/smbd/notifyd/notifyd_private.h
+++ b/source3/smbd/notifyd/notifyd_private.h
@@ -20,30 +20,48 @@
#include "lib/util/server_id.h"
#include "notifyd.h"
+
/*
- * notifyd's representation of a notify instance
+ * Representation of a watcher for a path
+ *
+ * This will be stored in the db.
*/
-struct notifyd_instance {
- struct server_id client;
- struct notify_instance instance;
-
- void *sys_watch; /* inotify/fam/etc handle */
+struct notifyd_watcher {
+ /*
+ * This is an intersections of the filter the watcher is listening for.
+ */
+ uint32_t filter;
+ uint32_t subdir_filter;
/*
- * Filters after sys_watch took responsibility of some bits
+ * Those are inout variables passed to the sys_watcher. The sys_watcher
+ * will remove the bits it can't handle.
*/
- uint32_t internal_filter;
- uint32_t internal_subdir_filter;
+ uint32_t sys_filter;
+ uint32_t sys_subdir_filter;
+
+ /* The handle for inotify/fam etc. */
+ void *sys_watch;
+};
+
+/*
+ * Representation of a notifyd instance
+ *
+ * This will be stored in the db.
+ */
+struct notifyd_instance {
+ struct server_id client;
+ struct notify_instance instance;
};
/*
* Parse an entry in the notifyd_context->entries database
*/
-bool notifyd_parse_entry(
- uint8_t *buf,
- size_t buflen,
- struct notifyd_instance **instances,
- size_t *num_instances);
+bool notifyd_parse_entry(uint8_t *data,
+ size_t data_len,
+ struct notifyd_watcher *watcher,
+ struct notifyd_instance **instances,
+ size_t *num_instances);
#endif
--
2.46.1

View File

@ -150,7 +150,7 @@
%define samba_requires_eq() %(LC_ALL="C" echo '%*' | xargs -r rpm -q --qf 'Requires: %%{name} = %%{epoch}:%%{version}\\n' | sed -e 's/ (none):/ /' -e 's/ 0:/ /' | grep -v "is not")
%global samba_version 4.21.0
%global samba_version 4.21.1
# The release field is extended:
# <pkgrel>[.<extraver>][.<snapinfo>]%%{?dist}[.<minorbump>]
@ -252,10 +252,7 @@ Source18: samba-winbind-systemd-sysusers.conf
Source201: README.downgrade
Source202: samba.abignore
Patch0: samba-4.21.0-backport-freeipa-support.patch
# https://gitlab.com/samba-team/samba/-/merge_requests/3807
Patch1: samba-4.21.0-ldb-lmdb.patch
Patch2: samba-4-21-fix-libldb-deepbind.patch
Patch0: samba-4.21.0-s3-notifyd.patch
Requires(pre): %{name}-common = %{samba_depver}
Requires: %{name}-common = %{samba_depver}

View File

@ -1,2 +1,2 @@
SHA512 (samba-4.21.0.tar.xz) = d05c823afc04669766130745c139e7d129eb9961525453d6da8b5ee6693d4c08192496d07e5c211e86d553956504fb9df16611cc9268111b71b95c7f2fa868a0
SHA512 (samba-4.21.0.tar.asc) = 7fffbd0b88b42dd7f340e4bcae17da4a68a0f8de86a1e71534a4a02a477a746e4cdb16df7c0da33aaf13278cefb452bd9b7c61ed029e248576f7158e8bec339e
SHA512 (samba-4.21.1.tar.xz) = 182759820708c9df26fbcb09e755e81236ecacf543f3e18a05dbd0ea551ab072d338fe239eb99ff506f158ec45e981a893ce46eacdde6e073ee85ceb43e2669a
SHA512 (samba-4.21.1.tar.asc) = 2c1e4b347044e15a852ced8bb412a3f372fd2c2b5e0001b1a773f7283f2d8fa62942143b46cbc3f16b18882255cf0aac4426002453971361b0002357657484f1