Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop in MbedOS CoAP library parser #12929

Closed
mjurczak opened this issue May 5, 2020 · 4 comments
Closed

Infinite loop in MbedOS CoAP library parser #12929

mjurczak opened this issue May 5, 2020 · 4 comments

Comments

@mjurczak
Copy link

mjurczak commented May 5, 2020

Description of defect

References:

https://github.com/ARMmbed/mbed-os/tree/mbed-os-5.15.3/features/frameworks/mbed-coap

https://github.com/ARMmbed/mbed-coap/tree/v5.1.5

File:

sn_coap_parser.c

Example Trace:
    #*  sn_coap_parser_options_parse_multiple_options()
        sn_coap_parser.c:657
    #*  sn_coap_parser_options_parse()
        sn_coap_parser.c:498
    #n  sn_coap_parser()
        sn_coap_parser.c:161

Analysis:

If a packet with an option processed by parse_multiple_options() function and declared zero option length is encountered, the parser enters an infinite loop.

Example entry point with zero-length option_len:

ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
&dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len,
COAP_OPTION_LOCATION_QUERY, option_len);
if (ret_status >= 0) {

Together with message_left equal to 1 this results in zero-length needed heap calculation result:

int16_t uri_query_needed_heap = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len);

With zero length heap allocation the function exits early without entering the main processing loop:

*dst_len_ptr = uri_query_needed_heap;
temp_parsed_uri_query_ptr = *dst_pptr;
/* Loop all Uri-Query options */
while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap) {

Which leaves (*packet_data_pptr) unmodified, pointing at the same option which leads to sn_coap_parser_options_parse() looping over the same option in an infinite loop.

Type:

  • Remote Denial Of Service
  • Excessive resources usage (CPU time)
  • System overload

Result:

  • The procedure loops infinitely

Target(s) affected by this defect ?

  • MbedOS mbed-coap library 5.1.5
  • MbedOS 5.15.3

Toolchain(s) (name and version) displaying this defect ?

N/A

What version of Mbed-os are you using (tag or sha) ?

MbedOS 5.15.3

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

N/A

How is this defect reproduced ?

Parsing the provided input example input with sn_coap_parser() function.

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "sn_coap_protocol.h"
#include "sn_coap_header.h"

struct coap_s* coapHandle;
coap_version_e coapVersion = COAP_VERSION_1;

void* coap_malloc(uint16_t size){
    return malloc(size);
}

void coap_free(void* addr){
    free(addr);
}

uint8_t coap_tx_cb(uint8_t *arg_a, uint16_t arg_b, sn_nsdl_addr_s *arg_c, void *arg_d){
    return 0;
}

int8_t coap_rx_cb(sn_coap_hdr_s *arg_a, sn_nsdl_addr_s *arg_b, void *arg_c){
    return 0;
}

int main(int argc, const char* argv[])
{
    FILE *fp;
    size_t read_bytes;
    size_t input_size;
    uint8_t *message_buffer;
    if (argc != 2)
    {
       return 1;
    }
    
    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
      return 2;
    }
     
    fseek (fp , 0 , SEEK_END);
    input_size = ftell(fp);
    rewind (fp);
     
    if (input_size > 65527)
    {
      return 3;
    }
     
    message_buffer = malloc(input_size);
    read_bytes = fread(message_buffer, 1, input_size, fp);
    fclose(fp);
    coapHandle = sn_coap_protocol_init(&coap_malloc, &coap_free, &coap_tx_cb, &coap_rx_cb);
    sn_coap_hdr_s* parsed = sn_coap_parser(coapHandle, read_bytes, message_buffer, &coapVersion);
    sn_coap_parser_release_allocated_coap_msg_mem(coapHandle, parsed);
    free(message_buffer);
    
    return 0;
}

hang1.log
hang_minimal.log

@ciarmcom
Copy link
Member

ciarmcom commented May 6, 2020

Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers.
Internal Jira reference: https://jira.arm.com/browse/MBOTRIAGE-2660

@0xc0170
Copy link
Contributor

0xc0170 commented May 6, 2020

cc @teetak01

@mjurczak
Copy link
Author

Patch proposal:
mjurczak/mbed-coap#2

@0xc0170
Copy link
Contributor

0xc0170 commented May 28, 2020

Thanks for the fix. As it was accepted, will close this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants