summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2017-12-13 16:12:09 +1100
committerMartin Schwenke <martins@samba.org>2017-12-13 08:48:18 +0100
commitde3f0d889b3667eb165ab1004fdfff3a05046110 (patch)
tree40013b8b34e74db3d10c74730186b83a3b20909a /ctdb
parentcb5e6e8c798b19610dfaa505fdfc5b2cab3fa19b (diff)
downloadsamba-de3f0d889b3667eb165ab1004fdfff3a05046110.tar.gz
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@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/server/ctdb_recovery_helper.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/ctdb/server/ctdb_recovery_helper.c b/ctdb/server/ctdb_recovery_helper.c
index ab9ab4152b0..2a10b07b508 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);
}