fix(mavlink): only handle log requests addressed to this vehicle (#28585)

LOG_REQUEST_LIST, LOG_REQUEST_DATA, LOG_REQUEST_END and LOG_ERASE all carry
target_system and target_component, and MavlinkLogHandler ignored both. The
message is not even decoded in handle_log_erase(): every LOG_ERASE seen on the
link deletes this vehicle's logs, whoever it was addressed to.

On a link shared with more than one vehicle, which is the normal case for a
ground station managing several or for a swarm, erasing one vehicle's logs
erases them everywhere, and a listing or download request for one vehicle is
answered by all of them, corrupting the transfers.

Check the target in each handler, next to the decode it already performs. Only
handle_log_request_end() and handle_log_erase() gain a decode, because they had
none.

Reported by @20210607 and @Nathaniel-hl.

Assisted-by: Claude:claude-opus-5[1m]

Signed-off-by: Julian Oes <julian@oes.ch>
This commit is contained in:
Julian Oes
2026-09-16 11:01:40 +12:00
committed by GitHub
parent dd3273ac3b
commit ae63ebc726

View File

@@ -44,6 +44,19 @@ static const char *kLogListFilePath = PX4_STORAGEDIR "/logdata.txt";
static const char *kLogListFilePathTemp = PX4_STORAGEDIR "/$log$.txt";
static const char *kLogDir = PX4_STORAGEDIR "/log";
/**
* The log messages all carry target ids. On a link shared with other vehicles an unfiltered
* LOG_ERASE deletes this vehicle's logs too, and a listing request for one vehicle is
* answered by all of them. Zero is the broadcast value for both fields.
*/
static bool targeted_at_us(uint8_t target_system, uint8_t target_component)
{
return (target_system == 0 || target_system == mavlink_system.sysid)
&& (target_component == 0
|| target_component == mavlink_system.compid
|| target_component == MAV_COMP_ID_ALL);
}
MavlinkLogHandler::MavlinkLogHandler(Mavlink &mavlink)
: _mavlink(mavlink)
{}
@@ -248,6 +261,10 @@ void MavlinkLogHandler::handle_log_request_list(const mavlink_message_t *msg)
mavlink_log_request_list_t request;
mavlink_msg_log_request_list_decode(msg, &request);
if (!targeted_at_us(request.target_system, request.target_component)) {
return;
}
if (!create_log_list_file()) {
return;
}
@@ -271,6 +288,10 @@ void MavlinkLogHandler::handle_log_request_data(const mavlink_message_t *msg)
mavlink_log_request_data_t request;
mavlink_msg_log_request_data_decode(msg, &request);
if (!targeted_at_us(request.target_system, request.target_component)) {
return;
}
if (request.id >= _num_logs) {
PX4_DEBUG("Requested log %" PRIu16 " but we only have %u", request.id, _num_logs);
_state = LogHandlerState::Idle;
@@ -323,11 +344,25 @@ void MavlinkLogHandler::handle_log_request_data(const mavlink_message_t *msg)
void MavlinkLogHandler::handle_log_request_end(const mavlink_message_t *msg)
{
mavlink_log_request_end_t request;
mavlink_msg_log_request_end_decode(msg, &request);
if (!targeted_at_us(request.target_system, request.target_component)) {
return;
}
_state = LogHandlerState::Idle;
}
void MavlinkLogHandler::handle_log_erase(const mavlink_message_t *msg)
{
mavlink_log_erase_t request;
mavlink_msg_log_erase_decode(msg, &request);
if (!targeted_at_us(request.target_system, request.target_component)) {
return;
}
if (_current_entry.fp) {
fclose(_current_entry.fp);
_current_entry.fp = nullptr;