summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-02-13 15:36:27 +0100
committerStefan Metzmacher <metze@samba.org>2014-02-21 14:51:51 +0100
commit33f10d06baf44e31d558bc5bd926c886915322cc (patch)
tree6d5faff9c46f88d7999174a543603eba8003c1e3 /source3
parent9677fae6aab26d2bf0884dc31516d2dcd8840c03 (diff)
downloadsamba-33f10d06baf44e31d558bc5bd926c886915322cc.tar.gz
samba-33f10d06baf44e31d558bc5bd926c886915322cc.tar.xz
samba-33f10d06baf44e31d558bc5bd926c886915322cc.zip
s3:smbd: avoid invalid lock_order panic triggered by "CTDB_SRVID_RELEASE_IP"
If smbd_server_connection_terminate("CTDB_SRVID_RELEASE_IP") is triggered from within ctdbd_migrate(), we got a smb_panic complaining about invalid lock_order, as ctdbd_migrate is called from dbwrap_fetch_locked(). Bug: https://bugzilla.samba.org/show_bug.cgi?id=10444 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Volker Lendecke <vl@samba.org> Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Fri Feb 21 14:51:51 CET 2014 on sn-devel-104
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/process.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 3dcc5d4e271..41b3611f306 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -2503,9 +2503,28 @@ static void smbd_server_echo_handler(struct tevent_context *ev,
struct smbd_release_ip_state {
struct smbd_server_connection *sconn;
+ struct tevent_immediate *im;
char addr[INET6_ADDRSTRLEN];
};
+static void smbd_release_ip_immediate(struct tevent_context *ctx,
+ struct tevent_immediate *im,
+ void *private_data)
+{
+ struct smbd_release_ip_state *state =
+ talloc_get_type_abort(private_data,
+ struct smbd_release_ip_state);
+
+ if (!NT_STATUS_EQUAL(state->sconn->status, NT_STATUS_ADDRESS_CLOSED)) {
+ /*
+ * smbd_server_connection_terminate() already triggered ?
+ */
+ return;
+ }
+
+ smbd_server_connection_terminate(state->sconn, "CTDB_SRVID_RELEASE_IP");
+}
+
/****************************************************************************
received when we should release a specific IP
****************************************************************************/
@@ -2517,6 +2536,11 @@ static bool release_ip(const char *ip, void *priv)
const char *addr = state->addr;
const char *p = addr;
+ if (!NT_STATUS_IS_OK(state->sconn->status)) {
+ /* avoid recursion */
+ return false;
+ }
+
if (strncmp("::ffff:", addr, 7) == 0) {
p = addr + 7;
}
@@ -2543,9 +2567,18 @@ static bool release_ip(const char *ip, void *priv)
* triggered and has implication on our process model,
* we can just use smbd_server_connection_terminate()
* (also for SMB1).
+ *
+ * We don't call smbd_server_connection_terminate() directly
+ * as we might be called from within ctdbd_migrate(),
+ * we need to defer our action to the next event loop
*/
- smbd_server_connection_terminate(state->sconn,
- "CTDB_SRVID_RELEASE_IP");
+ tevent_schedule_immediate(state->im, state->sconn->ev_ctx,
+ smbd_release_ip_immediate, state);
+
+ /*
+ * Make sure we don't get any io on the connection.
+ */
+ state->sconn->status = NT_STATUS_ADDRESS_CLOSED;
return true;
}
@@ -2569,6 +2602,10 @@ static NTSTATUS smbd_register_ips(struct smbd_server_connection *sconn,
return NT_STATUS_NO_MEMORY;
}
state->sconn = sconn;
+ state->im = tevent_create_immediate(state);
+ if (state->im == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (print_sockaddr(state->addr, sizeof(state->addr), srv) == NULL) {
return NT_STATUS_NO_MEMORY;
}