Proper size checking for link ADR commands

In a specific branch path 'adr_settings' in link_adr_request() API, the
structure adr_settings of type link_adr_params_t will be rendered
uninitialized. To prevent this we initialize the construct as zero.
In addition to that, to handle the case properly we should check for the
command identifier and the command payload length anticipating contiguous
blocks of adr commands. If we find a discrepency in size, we should
abort.
pull/9601/head
Hasnain Virk 2019-02-04 15:01:35 +02:00
parent d257d7287f
commit 726eff9305
6 changed files with 61 additions and 15 deletions

View File

@ -149,7 +149,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui
int8_t link_adr_dr = DR_0;
int8_t link_adr_txpower = TX_POWER_0;
uint8_t link_adr_nbtrans = 0;
uint8_t link_adr_nb_bytes_pasred = 0;
uint8_t link_adr_nb_bytes_parsed = 0;
// Fill parameter structure
link_adr_req.payload = &payload[mac_index - 1];
@ -165,7 +165,14 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui
&link_adr_dr,
&link_adr_txpower,
&link_adr_nbtrans,
&link_adr_nb_bytes_pasred);
&link_adr_nb_bytes_parsed);
// If nothing was consumed, we have a malformed packet at our hand
// we bin everything and return. link_adr_nb_bytes_parsed being 0 is
// a magic identifier letting us know that there are payload inconsistencies
if (link_adr_nb_bytes_parsed == 0) {
return LORAWAN_STATUS_UNSUPPORTED;
}
if ((status & 0x07) == 0x07) {
mac_sys_params.channel_data_rate = link_adr_dr;
@ -174,11 +181,11 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui
}
// Add the answers to the buffer
for (uint8_t i = 0; i < (link_adr_nb_bytes_pasred / 5); i++) {
for (uint8_t i = 0; i < (link_adr_nb_bytes_parsed / 5); i++) {
ret_value = add_link_adr_ans(status);
}
// Update MAC index
mac_index += link_adr_nb_bytes_pasred - 1;
mac_index += link_adr_nb_bytes_parsed - 1;
}
break;
case SRV_MAC_DUTY_CYCLE_REQ:

View File

@ -309,11 +309,12 @@ lorawan_time_t LoRaPHY::update_band_timeoff(bool joined, bool duty_cycle,
}
uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t *payload,
uint8_t payload_size,
link_adr_params_t *params)
{
uint8_t ret_index = 0;
if (payload[0] == SRV_MAC_LINK_ADR_REQ) {
if (payload_size >= 5) {
// Parse datarate and tx power
params->datarate = payload[1];
@ -973,13 +974,17 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t *link_adr_req,
verify_adr_params_t verify_params;
while (bytes_processed < link_adr_req->payload_size) {
while (bytes_processed < link_adr_req->payload_size &&
link_adr_req->payload[bytes_processed] == SRV_MAC_LINK_ADR_REQ) {
// Get ADR request parameters
next_index = parse_link_ADR_req(&(link_adr_req->payload[bytes_processed]),
link_adr_req->payload_size - bytes_processed,
&adr_settings);
if (next_index == 0) {
break; // break loop, since no more request has been found
bytes_processed = 0;
// break loop, malformed packet
break;
}
// Update bytes processed
@ -1024,6 +1029,11 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t *link_adr_req,
}
}
if (bytes_processed == 0) {
*nb_bytes_processed = 0;
return status;
}
if (is_datarate_supported(adr_settings.datarate)) {
verify_params.status = status;

View File

@ -608,7 +608,8 @@ protected:
/**
* Parses the parameter of an LinkAdrRequest.
*/
uint8_t parse_link_ADR_req(const uint8_t *payload, link_adr_params_t *adr_params);
uint8_t parse_link_ADR_req(const uint8_t *payload, uint8_t payload_size,
link_adr_params_t *adr_params);
/**
* Verifies and updates the datarate, the TX power and the number of repetitions

View File

@ -435,12 +435,16 @@ uint8_t LoRaPHYAU915::link_ADR_request(adr_req_params_t *params,
// Initialize local copy of channels mask
copy_channel_mask(temp_channel_masks, channel_mask, AU915_CHANNEL_MASK_SIZE);
while (bytes_processed < params->payload_size) {
while (bytes_processed < params->payload_size &&
params->payload[bytes_processed] == SRV_MAC_LINK_ADR_REQ) {
next_index = parse_link_ADR_req(&(params->payload[bytes_processed]),
params->payload_size,
&adr_settings);
if (next_index == 0) {
break; // break loop, since no more request has been found
bytes_processed = 0;
// break loop, malformed packet
break;
}
// Update bytes processed
@ -471,6 +475,11 @@ uint8_t LoRaPHYAU915::link_ADR_request(adr_req_params_t *params,
}
}
if (bytes_processed == 0) {
*nb_bytes_parsed = 0;
return status;
}
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
if ((adr_settings.datarate < DR_6)
&& (num_active_channels(temp_channel_masks, 0, 4) < 2)) {

View File

@ -460,13 +460,18 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t *params,
// Initialize local copy of channels mask
copy_channel_mask(temp_channel_masks, channel_mask, CN470_CHANNEL_MASK_SIZE);
while (bytes_processed < params->payload_size) {
while (bytes_processed < params->payload_size &&
params->payload[bytes_processed] == SRV_MAC_LINK_ADR_REQ) {
// Get ADR request parameters
next_index = parse_link_ADR_req(&(params->payload[bytes_processed]), &adr_settings);
next_index = parse_link_ADR_req(&(params->payload[bytes_processed]),
params->payload_size,
&adr_settings);
if (next_index == 0) {
break; // break loop, since no more request has been found
bytes_processed = 0;
// break loop, malformed packet
break;
}
// Update bytes processed
@ -501,6 +506,11 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t *params,
}
}
if (bytes_processed == 0) {
*nb_bytes_parsed = 0;
return status;
}
verify_params.status = status;
verify_params.adr_enabled = params->adr_enabled;
verify_params.datarate = adr_settings.datarate;

View File

@ -460,12 +460,16 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t *params,
// Initialize local copy of channels mask
copy_channel_mask(temp_channel_masks, channel_mask, US915_CHANNEL_MASK_SIZE);
while (bytes_processed < params->payload_size) {
while (bytes_processed < params->payload_size &&
params->payload[bytes_processed] == SRV_MAC_LINK_ADR_REQ) {
next_idx = parse_link_ADR_req(&(params->payload[bytes_processed]),
params->payload_size - bytes_processed,
&adr_settings);
if (next_idx == 0) {
break; // break loop, since no more request has been found
bytes_processed = 0;
// break loop, malformed packet
break;
}
// Update bytes processed
@ -501,6 +505,11 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t *params,
}
}
if (bytes_processed == 0) {
*nb_bytes_parsed = 0;
return status;
}
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
if ((adr_settings.datarate < DR_4) &&
(num_active_channels(temp_channel_masks, 0, 4) < 2)) {