From 33f10d06baf44e31d558bc5bd926c886915322cc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Feb 2014 15:36:27 +0100 Subject: [PATCH] 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 Reviewed-by: Volker Lendecke Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Fri Feb 21 14:51:51 CET 2014 on sn-devel-104 --- source3/smbd/process.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file 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; }