URL: https://github.com/SSSD/sssd/pull/5299
Author: pbrezina
 Title: #5299: dp: fix potential race condition in provider's sbus server
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5299/head:pr5299
git checkout pr5299
From 8d460852c3e19790d6b75c2983868c842ec2d186 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Wed, 26 Aug 2020 12:51:49 +0200
Subject: [PATCH] dp: fix potential race condition in provider's sbus server

We can hit a segfault if provider start is somehow delayed.

- dp_init_send
  - sbus_server_create_and_connect_send
    - sbus_server_create (*)
- dp_init_done (callback for sbus_server_create_and_connect_send)
  - sbus_server_create_and_connect_recv
  - sbus_server_set_on_connection (sets clients data and creates dp_cli)

At (*) sbus server is already created and accepts new connections once
we get into tevent loop. So it is possible that the client connects to
server before sbus_server_set_on_connection is called and thus the client
is not properly initialized. However it should not happen in normal start
because providers are started before responders and it can happen only if
data provider startup is somehow delay.

You can use this diff to reproduce the crash:
```diff
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -702,6 +702,8 @@ int main(int argc, const char *argv[])
     uid_t uid;
     gid_t gid;

+    sleep(5);
+
     struct poptOption long_options[] = {
         POPT_AUTOHELP
         SSSD_MAIN_OPTS
```

Resolves:
https://github.com/SSSD/sssd/issues/5298
---
 src/monitor/monitor.c                         |  3 ++-
 src/providers/data_provider/dp.c              |  9 +++------
 src/sbus/connection/sbus_connection_connect.c |  7 +++++--
 src/sbus/sbus.h                               | 12 ++++++++++--
 src/sbus/server/sbus_server.c                 |  9 ++++++++-
 5 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 1e94a8f36e..d9da05a511 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -2008,7 +2008,8 @@ static int monitor_process_init(struct mt_ctx *ctx,
 
     req = sbus_server_create_and_connect_send(ctx, ctx->ev, SSS_BUS_MONITOR,
                                               NULL, SSS_MONITOR_ADDRESS,
-                                              false, 100, ctx->uid, ctx->gid);
+                                              false, 100, ctx->uid, ctx->gid,
+                                              NULL, NULL);
     if (req == NULL) {
         ret = ENOMEM;
         goto done;
diff --git a/src/providers/data_provider/dp.c b/src/providers/data_provider/dp.c
index ba1cfec8a8..0858c43d2a 100644
--- a/src/providers/data_provider/dp.c
+++ b/src/providers/data_provider/dp.c
@@ -192,9 +192,9 @@ dp_init_send(TALLOC_CTX *mem_ctx,
     talloc_set_destructor(state->provider, dp_destructor);
 
     subreq = sbus_server_create_and_connect_send(state->provider, ev,
-                                                 state->sbus_name,
-                                                 NULL, sbus_address, true, 1000,
-                                                 uid, gid);
+        state->sbus_name, NULL, sbus_address, true, 1000, uid, gid,
+        (sbus_server_on_connection_cb)dp_client_init,
+        (sbus_server_on_connection_data)state->provider);
     if (subreq == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
         ret = ENOMEM;
@@ -235,9 +235,6 @@ static void dp_init_done(struct tevent_req *subreq)
         return;
     }
 
-    sbus_server_set_on_connection(state->provider->sbus_server,
-                                  dp_client_init, state->provider);
-
     /* be_ctx->provider must be accessible from modules and targets */
     state->be_ctx->provider = talloc_steal(state->be_ctx, state->provider);
 
diff --git a/src/sbus/connection/sbus_connection_connect.c b/src/sbus/connection/sbus_connection_connect.c
index 3f8702f0b7..9cfe86206b 100644
--- a/src/sbus/connection/sbus_connection_connect.c
+++ b/src/sbus/connection/sbus_connection_connect.c
@@ -344,7 +344,9 @@ sbus_server_create_and_connect_send(TALLOC_CTX *mem_ctx,
                                     bool use_symlink,
                                     uint32_t max_connections,
                                     uid_t uid,
-                                    gid_t gid)
+                                    gid_t gid,
+                                    sbus_server_on_connection_cb on_conn_cb,
+                                    sbus_server_on_connection_data on_conn_data)
 {
     struct sbus_server_create_and_connect_state *state;
     struct tevent_req *subreq;
@@ -358,7 +360,8 @@ sbus_server_create_and_connect_send(TALLOC_CTX *mem_ctx,
     }
 
     state->server = sbus_server_create(state, ev, address, use_symlink,
-                                       max_connections, uid, gid);
+                                       max_connections, uid, gid,
+                                       on_conn_cb, on_conn_data);
     if (state->server == NULL) {
         ret = ENOMEM;
         goto done;
diff --git a/src/sbus/sbus.h b/src/sbus/sbus.h
index 9136c4e4ad..bfa7ecd579 100644
--- a/src/sbus/sbus.h
+++ b/src/sbus/sbus.h
@@ -138,6 +138,8 @@ errno_t sbus_connect_private_recv(TALLOC_CTX *mem_ctx,
  * @param use_symlink            If a symlink to @address should be created.
  * @param uid                    Socket owner uid.
  * @param gid                    Socket owner gid.
+ * @param on_conn_cb             On new connection callback function.
+ * @param on_conn_data           Private data passed to the callback.
  *
  * @return New sbus server or NULL on error.
  */
@@ -148,7 +150,9 @@ sbus_server_create(TALLOC_CTX *mem_ctx,
                    bool use_symlink,
                    uint32_t max_connections,
                    uid_t uid,
-                   gid_t gid);
+                   gid_t gid,
+                   sbus_server_on_connection_cb on_conn_cb,
+                   sbus_server_on_connection_data on_conn_data);
 
 /**
  * Create a new sbus server at socket address @address and connect to it.
@@ -162,6 +166,8 @@ sbus_server_create(TALLOC_CTX *mem_ctx,
  * @param use_symlink            If a symlink to @address should be created.
  * @param uid                    Socket owner uid.
  * @param gid                    Socket owner gid.
+ * @param on_conn_cb             On new connection callback function.
+ * @param on_conn_data           Private data passed to the callback.
  *
  * @return Tevent request or NULL on error.
  */
@@ -174,7 +180,9 @@ sbus_server_create_and_connect_send(TALLOC_CTX *mem_ctx,
                                     bool use_symlink,
                                     uint32_t max_connections,
                                     uid_t uid,
-                                    gid_t gid);
+                                    gid_t gid,
+                                    sbus_server_on_connection_cb on_conn_cb,
+                                    sbus_server_on_connection_data on_conn_data);
 
 /**
  * Receive reply from @sbus_server_create_and_connect_send.
diff --git a/src/sbus/server/sbus_server.c b/src/sbus/server/sbus_server.c
index 2b93270516..69efd739b4 100644
--- a/src/sbus/server/sbus_server.c
+++ b/src/sbus/server/sbus_server.c
@@ -635,7 +635,9 @@ sbus_server_create(TALLOC_CTX *mem_ctx,
                    bool use_symlink,
                    uint32_t max_connections,
                    uid_t uid,
-                   gid_t gid)
+                   gid_t gid,
+                   sbus_server_on_connection_cb on_conn_cb,
+                   sbus_server_on_connection_data on_conn_data)
 {
     DBusServer *dbus_server;
     struct sbus_server *sbus_server;
@@ -675,6 +677,11 @@ sbus_server_create(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
+    if (on_conn_cb != NULL) {
+        _sbus_server_set_on_connection(sbus_server, "on-connection", on_conn_cb,
+                                       on_conn_data);
+    }
+
     sbus_server->names = sss_ptr_hash_create(sbus_server,
                              sbus_server_name_remove_from_table_cb, sbus_server);
     if (sbus_server->names == NULL) {
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org

Reply via email to