]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:loadparm: add lp_register_snum_in_use_fn() callback registration
authorJeremy Allison <jallison@ciq.com>
Fri, 10 Apr 2026 21:15:48 +0000 (14:15 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 14 Apr 2026 23:04:37 +0000 (23:04 +0000)
Add a mechanism for smbd to register a callback that checks whether
a service number is currently in use by any active connection.

This will be used by subsequent commits to guard free_service_byindex()
calls in lp_servicenumber() and other sites that currently destroy
services without checking if they are in use, which can leave active
connections holding stale service numbers that lead to NULL pointer
dereferences.

The callback is registered by smbd during smbd_process() startup via
connections_snum_used. Non-smbd programs (testparm, net, etc.) leave the
callback as NULL, meaning no connections exist and it is always safe
to free services.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14978

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: David Mulder <dmulder@samba.org>
source3/param/loadparm.c
source3/param/loadparm.h
source3/smbd/smb2_process.c

index b081b917a8247a34dbb7490392128b7391dd62c2..02ad996c2653577ee8885a04fa17915f49d66ad2 100644 (file)
@@ -119,6 +119,21 @@ static bool defaults_saved = false;
 
 static struct loadparm_global Globals;
 
+/*
+ * Callback to check if a service number is currently in use
+ * by any active connection. Registered by smbd at startup.
+ * When NULL (non-smbd programs), no connections exist so
+ * it is always safe to free services.
+ */
+static bool (*snum_in_use)(struct smbd_server_connection *unused,
+                          int snum) = NULL;
+
+void lp_register_snum_in_use_fn(bool (*fn)(struct smbd_server_connection *,
+                                          int))
+{
+       snum_in_use = fn;
+}
+
 /* This is a default service used to prime a services structure */
 static const struct loadparm_service _sDefault =
 {
index 72773a8b2ece91d0edad3d40098f1f54e70390b5..43f6c61804deb144132979395600c52bea99cb25 100644 (file)
@@ -144,6 +144,8 @@ void lp_killunused(struct smbd_server_connection *sconn,
                   bool (*snumused) (struct smbd_server_connection *, int));
 void lp_kill_all_services(void);
 void lp_killservice(int iServiceIn);
+void lp_register_snum_in_use_fn(bool (*fn)(struct smbd_server_connection *,
+                                          int));
 const char* server_role_str(uint32_t role);
 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
                        SMB_STRUCT_STAT *psbuf,
index 9290714e8ae5e028d54e12a253e588fe0f329009..f16a14964386e0e2f84360baf3be20a16183baa3 100644 (file)
@@ -2031,6 +2031,7 @@ void smbd_process(struct tevent_context *ev_ctx,
        /* this is needed so that we get decent entries
           in smbstatus for port 445 connects */
        set_remote_machine_name(remaddr, false);
+       lp_register_snum_in_use_fn(connections_snum_used);
        reload_services(sconn, conn_snum_used, true);
        sub_set_socket_ids(remaddr,
                           sconn->remote_hostname,