diff options
author | Stefan Metzmacher <metze@samba.org> | 2014-02-13 15:36:27 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2014-02-21 14:51:51 +0100 |
commit | 33f10d06baf44e31d558bc5bd926c886915322cc (patch) | |
tree | 6d5faff9c46f88d7999174a543603eba8003c1e3 /source3 | |
parent | 9677fae6aab26d2bf0884dc31516d2dcd8840c03 (diff) | |
download | samba-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.c | 41 |
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; } |