fix: UAF in _on_member_sync_done (channel_cache freed by refresh)
cs_flush_sync passed &cs->channels[i] as member_sync cb_arg, but the 30s cs_refresh_channels frees/reallocs cs->channels[], leaving the arg dangling when _session_done later fires the callback. Re-find the channel by the (stable) ns id instead of trusting arg.
This commit is contained in:
1 parent
9ee61dce6c
commit
a01a4ddba4
1 file changed
+7
-4
@@ -357,7 +357,7 @@ static void cs_flush_sync(struct chat_sync* cs) {
|
||||
if (pid == myid || !cs_is_peer_online(cs->inst, pid)) continue;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC, "%s: flush_sync start for peer=%016llx ch=%s",
|
||||
CS_ID, (unsigned long long)pid, ch->channel_id);
|
||||
member_sync_start(cs->inst, pid, ch->channel_id, _on_member_sync_done, ch);
|
||||
member_sync_start(cs->inst, pid, ch->channel_id, _on_member_sync_done, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,9 +416,12 @@ static void cs_resume_db_sync(const char* ch_id) {
|
||||
}
|
||||
|
||||
static void _on_member_sync_done(uint64_t peer, const char* ns, int result, void* arg) {
|
||||
struct channel_cache* ch = (struct channel_cache*)arg;
|
||||
if (result == MT_OK && ch) ch->synced = CS_SYNC_DONE;
|
||||
if (result == MT_OK) cs_resume_db_sync(ns);
|
||||
(void)arg;
|
||||
if (result == MT_OK) {
|
||||
struct channel_cache* ch = g_cs ? cs_find(g_cs, ns) : NULL;
|
||||
if (ch) ch->synced = CS_SYNC_DONE;
|
||||
cs_resume_db_sync(ns);
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: member_sync %s ns=%s peer=%016llx",
|
||||
CS_ID, result == MT_OK ? "OK" : "FAIL", ns, (unsigned long long)peer);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user