[SCM] Samba Shared Repository - branch master updated

Martin Schwenke martins at samba.org
Wed Dec 13 12:04:02 UTC 2017


The branch, master has been updated
       via  9f4eda9 selftest: Fix copyright header on samba.dsdb_lock
       via  de3f0d8 ctdb-recovery-helper: Deregister message handler in error paths
       via  cb5e6e8 ctdb-client: Add async version for ctdb_client_init()
       via  43145c8 ctdb-common: Avoid using void ** argument
       via  495cc4e ctdb-build: Apply dependency to correct subsystem
      from  2a8b507 selftest: Add cleanup of ForeignSecurityPrincipal in samba.dsdb test

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 9f4eda9c24ff4c051002080e862757b69c09b175
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Dec 6 14:31:54 2017 +1300

    selftest: Fix copyright header on samba.dsdb_lock
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13178
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    
    Autobuild-User(master): Martin Schwenke <martins at samba.org>
    Autobuild-Date(master): Wed Dec 13 13:03:16 CET 2017 on sn-devel-144

commit de3f0d889b3667eb165ab1004fdfff3a05046110
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Wed Dec 13 16:12:09 2017 +1100

    ctdb-recovery-helper: Deregister message handler in error paths
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13188
    
    If PULL_DB control times out but the remote node is still sending the
    data, then the tevent_req for pull_database_send will be freed without
    removing the message handler.  So when the data is received, srvid
    handler will be called and it will try to access tevent_req which will
    result in use-after-free and abort.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit cb5e6e8c798b19610dfaa505fdfc5b2cab3fa19b
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Nov 28 21:17:37 2017 +1100

    ctdb-client: Add async version for ctdb_client_init()
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 43145c88fe75d57ff66ea95d9db0ce503a2e8c03
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Nov 9 16:37:15 2017 +1100

    ctdb-common: Avoid using void ** argument
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 495cc4ed2255b334fa6fa75424add7c43575ab74
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Nov 2 17:33:19 2017 +1100

    ctdb-build: Apply dependency to correct subsystem
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

-----------------------------------------------------------------------

Summary of changes:
 ctdb/client/client.h               |  27 ++++-
 ctdb/client/client_connect.c       | 205 +++++++++++++++++++++++++------------
 ctdb/common/sock_client.c          |   4 +-
 ctdb/common/sock_client.h          |   2 +-
 ctdb/server/ctdb_recovery_helper.c |  16 ++-
 ctdb/wscript                       |   4 +-
 python/samba/tests/dsdb_lock.py    |   4 +-
 7 files changed, 185 insertions(+), 77 deletions(-)


Changeset truncated at 500 lines:

diff --git a/ctdb/client/client.h b/ctdb/client/client.h
index 5be54b2..e792047 100644
--- a/ctdb/client/client.h
+++ b/ctdb/client/client.h
@@ -83,7 +83,7 @@ typedef void (*ctdb_tunnel_callback_func_t)(struct ctdb_tunnel_context *tctx,
 					    void *private_data);
 
 /**
- * @brief Initialize and connect to ctdb daemon
+ * @brief Async computation start to initialize a connection to ctdb daemon
  *
  * This returns a ctdb client context.  Freeing this context will free the
  * connection to ctdb daemon and any memory associated with it.
@@ -102,6 +102,31 @@ typedef void (*ctdb_tunnel_callback_func_t)(struct ctdb_tunnel_context *tctx,
  * @param[in] mem_ctx Talloc memory context
  * @param[in] ev Tevent context
  * @param[in] sockpath Path to ctdb daemon unix domain socket
+ * @return new tevent request, NULL on failure
+ */
+struct tevent_req *ctdb_client_init_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 const char *sockpath);
+
+/**
+ * @brief Async computation end to initialize a connection to ctdb daemon
+ *
+ * @param[in] req Tevent request
+ * @param[out] perr errno in case of failure
+ * @param[in] mem_ctx Talloc memory context
+ * @param[out] result The new ctdb client context
+ * @return true on success, false on failure
+ */
+bool ctdb_client_init_recv(struct tevent_req *req, int *perr,
+			   TALLOC_CTX *mem_ctx,
+			   struct ctdb_client_context **result);
+
+/**
+ * @brief Sync wrapper to initialize ctdb connection
+ *
+ * @param[in] mem_ctx Talloc memory context
+ * @param[in] ev Tevent context
+ * @param[in] sockpath Path to ctdb daemon unix domain socket
  * @param[out] result The new ctdb client context
  * @return 0 on succcess, errno on failure
  */
diff --git a/ctdb/client/client_connect.c b/ctdb/client/client_connect.c
index ed4371f..89a602d 100644
--- a/ctdb/client/client_connect.c
+++ b/ctdb/client/client_connect.c
@@ -40,58 +40,127 @@
 #include "client/client.h"
 #include "client/client_sync.h"
 
-static int ctdb_client_connect(struct ctdb_client_context *client,
-			       struct tevent_context *ev,
-			       const char *sockpath);
+static void client_read_handler(uint8_t *buf, size_t buflen,
+				void *private_data);
+static void client_dead_handler(void *private_data);
+
+struct ctdb_client_init_state {
+	struct ctdb_client_context *client;
+};
 
 static int ctdb_client_context_destructor(struct ctdb_client_context *client);
+static void ctdb_client_init_done(struct tevent_req *subreq);
 
-int ctdb_client_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-		     const char *sockpath, struct ctdb_client_context **out)
+struct tevent_req *ctdb_client_init_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 const char *sockpath)
 {
+	struct tevent_req *req, *subreq;
+	struct ctdb_client_init_state *state;
 	struct ctdb_client_context *client;
+	struct ctdb_req_control request;
+	struct sockaddr_un addr;
+	size_t len;
 	int ret;
 
-	client = talloc_zero(mem_ctx, struct ctdb_client_context);
-	if (client == NULL) {
-		DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n"));
-		return ENOMEM;
+	req = tevent_req_create(mem_ctx, &state,
+				struct ctdb_client_init_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	if (sockpath == NULL) {
+		D_ERR("socket path cannot be NULL\n");
+		tevent_req_error(req, EINVAL);
+		return tevent_req_post(req, ev);
+	}
+
+	client = talloc_zero(state, struct ctdb_client_context);
+	if (tevent_req_nomem(client, req)) {
+		return tevent_req_post(req, ev);
 	}
 
 	ret = reqid_init(client, INT_MAX-200, &client->idr);
 	if (ret != 0) {
-		DEBUG(DEBUG_ERR, ("reqid_init() failed, ret=%d\n", ret));
+		D_ERR("reqid_init() failed, ret=%d\n", ret);
 		talloc_free(client);
-		return ret;
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
 	}
 
 	ret = srvid_init(client, &client->srv);
 	if (ret != 0) {
 		DEBUG(DEBUG_ERR, ("srvid_init() failed, ret=%d\n", ret));
 		talloc_free(client);
-		return ret;
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
 	}
 
 	ret = srvid_init(client, &client->tunnels);
 	if (ret != 0) {
 		DEBUG(DEBUG_ERR, ("srvid_init() failed, ret=%d\n", ret));
 		talloc_free(client);
-		return ret;
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
 	}
 
-	client->fd = -1;
-	client->pnn = CTDB_UNKNOWN_PNN;
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
+	if (len != strlen(sockpath)) {
+		D_ERR("socket path too long, len=%zu\n", strlen(sockpath));
+		talloc_free(client);
+		tevent_req_error(req, ENAMETOOLONG);
+		return tevent_req_post(req, ev);
+	}
 
-	ret = ctdb_client_connect(client, ev, sockpath);
+	client->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (client->fd == -1) {
+		ret = errno;
+		D_ERR("socket() failed, errno=%d\n", ret);
+		talloc_free(client);
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
+	}
+
+	ret = connect(client->fd, (struct sockaddr *)&addr, sizeof(addr));
+	if (ret == -1) {
+		ret = errno;
+		DEBUG(DEBUG_ERR, ("connect() failed, errno=%d\n", ret));
+		close(client->fd);
+		talloc_free(client);
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
+	}
+
+	ret = comm_setup(client, ev, client->fd, client_read_handler, client,
+			 client_dead_handler, client, &client->comm);
 	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("comm_setup() failed, ret=%d\n", ret));
+		close(client->fd);
 		talloc_free(client);
-		return ret;
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
 	}
 
+	client->pnn = CTDB_UNKNOWN_PNN;
+
 	talloc_set_destructor(client, ctdb_client_context_destructor);
 
-	*out = client;
-	return 0;
+	state->client = client;
+
+	ctdb_req_control_get_pnn(&request);
+	subreq = ctdb_client_control_send(state, ev, client,
+					  CTDB_CURRENT_NODE,
+					  tevent_timeval_zero(),
+					  &request);
+	if (tevent_req_nomem(subreq, req)) {
+		TALLOC_FREE(state->client);
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, ctdb_client_init_done, req);
+
+	return req;
 }
 
 static int ctdb_client_context_destructor(struct ctdb_client_context *client)
@@ -103,63 +172,69 @@ static int ctdb_client_context_destructor(struct ctdb_client_context *client)
 	return 0;
 }
 
-static void client_read_handler(uint8_t *buf, size_t buflen,
-				void *private_data);
-static void client_dead_handler(void *private_data);
-
-static int ctdb_client_connect(struct ctdb_client_context *client,
-			       struct tevent_context *ev, const char *sockpath)
+static void ctdb_client_init_done(struct tevent_req *subreq)
 {
-	struct sockaddr_un addr;
-	size_t len;
-	int fd, ret;
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct ctdb_client_init_state *state = tevent_req_data(
+		req, struct ctdb_client_init_state);
+	struct ctdb_reply_control *reply;
+	int ret;
+	bool status;
 
-	if (sockpath == NULL) {
-		DEBUG(DEBUG_ERR, ("socket path cannot be NULL\n"));
-		return EINVAL;
+	status = ctdb_client_control_recv(subreq, &ret, state, &reply);
+	TALLOC_FREE(subreq);
+	if (! status) {
+		tevent_req_error(req, ret);
+		return;
 	}
 
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_UNIX;
-	len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
-	if (len != strlen(sockpath)) {
-		DEBUG(DEBUG_ERR, ("socket path too long, len=%zu\n",
-				  strlen(sockpath)));
-		return ENAMETOOLONG;
+	ret = ctdb_reply_control_get_pnn(reply, &state->client->pnn);
+	if (ret != 0) {
+		tevent_req_error(req, ret);
+		return;
 	}
 
-	fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (fd == -1) {
-		ret = errno;
-		DEBUG(DEBUG_ERR, ("socket() failed, errno=%d\n", ret));
-		return ret;
-	}
+	tevent_req_done(req);
+}
 
-	ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
-	if (ret == -1) {
-		ret = errno;
-		DEBUG(DEBUG_ERR, ("connect() failed, errno=%d\n", ret));
-		close(fd);
-		return ret;
+bool ctdb_client_init_recv(struct tevent_req *req, int *perr,
+			   TALLOC_CTX *mem_ctx,
+			   struct ctdb_client_context **result)
+{
+	struct ctdb_client_init_state *state = tevent_req_data(
+		req, struct ctdb_client_init_state);
+	int ret;
+
+	if (tevent_req_is_unix_error(req, &ret)) {
+		if (perr != NULL) {
+			*perr = ret;
+		}
+		return false;
 	}
-	client->fd = fd;
 
-	ret = comm_setup(client, ev, fd, client_read_handler, client,
-			 client_dead_handler, client, &client->comm);
-	if (ret != 0) {
-		DEBUG(DEBUG_ERR, ("comm_setup() failed, ret=%d\n", ret));
-		close(fd);
-		client->fd = -1;
-		return ret;
+	*result = talloc_steal(mem_ctx, state->client);
+	return true;
+}
+
+
+int ctdb_client_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+		     const char *sockpath, struct ctdb_client_context **out)
+{
+	struct tevent_req *req;
+	int ret;
+	bool status;
+
+	req = ctdb_client_init_send(mem_ctx, ev, sockpath);
+	if (req == NULL) {
+		return ENOMEM;
 	}
 
-	ret = ctdb_ctrl_get_pnn(client, ev, client, CTDB_CURRENT_NODE,
-				tevent_timeval_zero(), &client->pnn);
-	if (ret != 0) {
-		DEBUG(DEBUG_ERR, ("failed to get current node pnn\n"));
-		close(fd);
-		client->fd = -1;
-		TALLOC_FREE(client->comm);
+	tevent_req_poll(req, ev);
+
+	status = ctdb_client_init_recv(req, &ret, mem_ctx, out);
+	TALLOC_FREE(req);
+	if (! status) {
 		return ret;
 	}
 
diff --git a/ctdb/common/sock_client.c b/ctdb/common/sock_client.c
index e5f993e..ced7050 100644
--- a/ctdb/common/sock_client.c
+++ b/ctdb/common/sock_client.c
@@ -311,7 +311,7 @@ static void sock_client_msg_reply(struct sock_client_context *sockc,
 }
 
 bool sock_client_msg_recv(struct tevent_req *req, int *perr,
-			  TALLOC_CTX *mem_ctx, void **reply)
+			  TALLOC_CTX *mem_ctx, void *reply)
 {
 	struct sock_client_msg_state *state = tevent_req_data(
 		req, struct sock_client_msg_state);
@@ -325,7 +325,7 @@ bool sock_client_msg_recv(struct tevent_req *req, int *perr,
 	}
 
 	if (reply != NULL) {
-		*reply = talloc_steal(mem_ctx, state->reply);
+		*(void **)reply = talloc_steal(mem_ctx, state->reply);
 	}
 
 	return true;
diff --git a/ctdb/common/sock_client.h b/ctdb/common/sock_client.h
index c640767..c5822a0 100644
--- a/ctdb/common/sock_client.h
+++ b/ctdb/common/sock_client.h
@@ -124,6 +124,6 @@ struct tevent_req *sock_client_msg_send(TALLOC_CTX *mem_ctx,
  * @return true on success, false on failure
  */
 bool sock_client_msg_recv(struct tevent_req *req, int *perr,
-			  TALLOC_CTX *mem_ctx, void **reply);
+			  TALLOC_CTX *mem_ctx, void *reply);
 
 #endif /* __CTDB_SOCK_CLIENT_H__ */
diff --git a/ctdb/server/ctdb_recovery_helper.c b/ctdb/server/ctdb_recovery_helper.c
index ab9ab41..2a10b07 100644
--- a/ctdb/server/ctdb_recovery_helper.c
+++ b/ctdb/server/ctdb_recovery_helper.c
@@ -397,6 +397,7 @@ struct pull_database_state {
 	uint32_t pnn;
 	uint64_t srvid;
 	int num_records;
+	int result;
 };
 
 static void pull_database_handler(uint64_t srvid, TDB_DATA data,
@@ -595,8 +596,8 @@ static void pull_database_new_done(struct tevent_req *subreq)
 	if (! status) {
 		D_ERR("control DB_PULL failed for %s on node %u, ret=%d\n",
 		      recdb_name(state->recdb), state->pnn, ret);
-		tevent_req_error(req, ret);
-		return;
+		state->result = ret;
+		goto unregister;
 	}
 
 	ret = ctdb_reply_control_db_pull(reply, &num_records);
@@ -605,13 +606,15 @@ static void pull_database_new_done(struct tevent_req *subreq)
 		D_ERR("mismatch (%u != %u) in DB_PULL records for db %s\n",
 		      num_records, state->num_records,
 		      recdb_name(state->recdb));
-		tevent_req_error(req, EIO);
-		return;
+		state->result = EIO;
+		goto unregister;
 	}
 
 	D_INFO("Pulled %d records for db %s from node %d\n",
 	       state->num_records, recdb_name(state->recdb), state->pnn);
 
+unregister:
+
 	subreq = ctdb_client_remove_message_handler_send(
 					state, state->ev, state->client,
 					state->srvid, req);
@@ -639,6 +642,11 @@ static void pull_database_unregister_done(struct tevent_req *subreq)
 		return;
 	}
 
+	if (state->result != 0) {
+		tevent_req_error(req, state->result);
+		return;
+	}
+
 	tevent_req_done(req);
 }
 
diff --git a/ctdb/wscript b/ctdb/wscript
index f5a2481..8774b99 100644
--- a/ctdb/wscript
+++ b/ctdb/wscript
@@ -442,7 +442,7 @@ def build(bld):
                         source=bld.SUBDIR('common',
                                           '''sock_daemon.c'''),
                         deps='''samba-util ctdb-util tevent-util
-                                replace talloc tevent''')
+                                LIBASYNC_REQ replace talloc tevent''')
 
     bld.SAMBA_SUBSYSTEM('ctdb-ipalloc',
                         source=bld.SUBDIR('server',
@@ -511,7 +511,7 @@ def build(bld):
     bld.SAMBA_BINARY('ctdb_eventd',
                      source='server/ctdb_eventd.c',
                      deps='''ctdb-server-util ctdb-protocol ctdb-protocol-util
-                             ctdb-util samba-util LIBASYNC_REQ replace popt''',
+                             ctdb-util samba-util replace popt''',
                      install_path='${CTDB_HELPER_BINDIR}')
 
     bld.SAMBA_BINARY('ctdb_lock_helper',
diff --git a/python/samba/tests/dsdb_lock.py b/python/samba/tests/dsdb_lock.py
index 9cc93aa..cd3851e 100644
--- a/python/samba/tests/dsdb_lock.py
+++ b/python/samba/tests/dsdb_lock.py
@@ -1,5 +1,5 @@
-# Unix SMB/CIFS implementation. Tests for SamDB
-# Copyright (C) Jelmer Vernooij <jelmer at samba.org> 2008
+# Unix SMB/CIFS implementation. Tests for DSDB locking
+# Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by


-- 
Samba Shared Repository



More information about the samba-cvs mailing list