Avoid returning uninitialized packet_id on ACLK publish failure - #22504
Conversation
aclk_send_bin_message_subtopic_pid returned an uninitialized packet_id when mqtt_wss_publish5 failed. aclk_graceful_disconnect stores that value in mqtt_shutdown_msg_id and the PUBACK handler matches incoming packet_ids against it, so a garbage match could falsely declare the shutdown ack'd and trigger an early graceful exit. Initialize packet_id to 0 (the existing "no message" sentinel matching mqtt_shutdown_msg_id's -1 init and >0 check) and force it back to 0 on any non-OK return from mqtt_wss_publish5. Defensive init also added to aclk_send_message_with_bin_payload for the same pattern.
There was a problem hiding this comment.
Pull request overview
This PR fixes an ACLK/MQTT shutdown edge case where a failed publish could return an uninitialized packet_id, which could then be mistakenly treated as an expected PUBACK id and cause premature agent shutdown.
Changes:
- Initialize
packet_idto0inaclk_send_bin_message_subtopic_pid()and force it back to0whenmqtt_wss_publish5()returns a non-OK status. - Defensively initialize
packet_idto0inaclk_send_message_with_bin_payload().
Comments suppressed due to low confidence (1)
src/aclk/aclk_tx_msgs.c:43
mqtt_wss_publish5()may freemsgimmediately on publish failure (e.g., not connected/disconnecting or message too big) via themsg_freecallback, but the code still callsprotomsg_to_json(msg, ...)for conversation logging afterwards. This can dereference freed memory whenaclklog_enabledis on. To avoid a UAF, generate the JSON/log payload before callingmqtt_wss_publish5(), or only log whenrc == MQTT_WSS_OK(and ensure the log path never touchesmsgafter ownership has been handed off).
int rc = mqtt_wss_publish5(client, (char *)topic, NULL, msg, &freez_aclk_publish5a, msg_len, MQTT_WSS_PUB_QOS1, &packet_id);
if (rc != MQTT_WSS_OK)
packet_id = 0;
if (aclklog_enabled) {
char *json = protomsg_to_json(msg, msg_len, msgname);
log_aclk_message_bin(json, strlen(json), 1, topic, msgname);
freez(json);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…rom mqtt_ng_generate_publish
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
thiagoftsm
left a comment
There was a problem hiding this comment.
No issues were identified on cloud when running this PR. LGTM!
…ata#22504) * aclk: return packet_id=0 on publish failure aclk_send_bin_message_subtopic_pid returned an uninitialized packet_id when mqtt_wss_publish5 failed. aclk_graceful_disconnect stores that value in mqtt_shutdown_msg_id and the PUBACK handler matches incoming packet_ids against it, so a garbage match could falsely declare the shutdown ack'd and trigger an early graceful exit. Initialize packet_id to 0 (the existing "no message" sentinel matching mqtt_shutdown_msg_id's -1 init and >0 check) and force it back to 0 on any non-OK return from mqtt_wss_publish5. Defensive init also added to aclk_send_message_with_bin_payload for the same pattern. * aclk: move mqtt_wss_publish5 call after logging to avoid use after free * aclk: ensure msg_free contract holds on non-OK return from message generator * aclk: clear packet_id and ensure msg_free contract on non-OK return from mqtt_ng_generate_publish * aclk: clarify msg_free logic to ensure publish-layer contract on non-OK returns * aclk: add null check for packet_id before assignment on failure rollback * aclk: reset packet_id to 0 on oversized message error path
* aclk: return packet_id=0 on publish failure aclk_send_bin_message_subtopic_pid returned an uninitialized packet_id when mqtt_wss_publish5 failed. aclk_graceful_disconnect stores that value in mqtt_shutdown_msg_id and the PUBACK handler matches incoming packet_ids against it, so a garbage match could falsely declare the shutdown ack'd and trigger an early graceful exit. Initialize packet_id to 0 (the existing "no message" sentinel matching mqtt_shutdown_msg_id's -1 init and >0 check) and force it back to 0 on any non-OK return from mqtt_wss_publish5. Defensive init also added to aclk_send_message_with_bin_payload for the same pattern. * aclk: move mqtt_wss_publish5 call after logging to avoid use after free * aclk: ensure msg_free contract holds on non-OK return from message generator * aclk: clear packet_id and ensure msg_free contract on non-OK return from mqtt_ng_generate_publish * aclk: clarify msg_free logic to ensure publish-layer contract on non-OK returns * aclk: add null check for packet_id before assignment on failure rollback * aclk: reset packet_id to 0 on oversized message error path



Summary
aclk_send_bin_message_subtopic_pidwas returning an uninitializedpacket_idwhenever the MQTT publish failed, sincemqtt_wss_publish5only writes the out-param on success.aclk_graceful_disconnect, and the PUBACK handler compares incoming ids against it — so a random match can falselydeclare the shutdown ack'd and exit the agent early.
packet_idto 0 (the existing "no message" sentinel) and force it back to 0 on any non-OK publish return; same defensive init applied toaclk_send_message_with_bin_payload.Summary by cubic
Fixes a bug where failed publishes could return an uninitialized or stale
packet_id, and hardens the publish path to prevent leaks and use-after-free.packet_idis now 0 on error (including oversize), logging happens before send, and messages are freed on generator failures.aclk_send_bin_message_subtopic_pid: initializepacket_id=0; reset to 0 whenmqtt_wss_publish5!=MQTT_WSS_OK.aclk_send_message_with_bin_payload: initializepacket_id=0; publish after logging to avoid use-after-free.mqtt_ng_publish: on oversized messages or non-OK frommqtt_ng_generate_publish, null-check and set*packet_id=0; callmsg_free(msg)on failure; only add to timeout list on success.Written for commit 33bdf6a. Summary will update on new commits. Review in cubic