Gcoap_dtls client and server crashes when (metadata length+payload length) > 91 bytes

Hi…I am working on an application built from the gcoap_dtls example and I am working on the 2022.01 version of RIOT OS.

  1. Suppose I want to get some data from Server using COAP GET.On the server side,inside the resourse handler function,we need to return the sumof metadata length and payload length. for eg.
static ssize_t _riot_board_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx)
{
    
    (void)ctx;
    gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
    coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
    size_t resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
    /* write the data  in the response buffer */
    if (pdu->payload_len >= strlen(temp_buf)) {
        printf("pdu->payload_len:%d\n",pdu->payload_len);
        memcpy(pdu->payload, temp_buf, strlen(temp_buf));
        return resp_len + strlen(temp_buf);
    }
    else {
        puts("gcoap_cli: msg buffer too small");
        return gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR);
    }
}

when resp_len + strlen(temp_buf) is greater than 91 bytes ,server crashes with *** stack smashing detected ***: terminated

  1. Similary on on the client side,when using COAP PUT method to a resource in server.

bytes_sent = gcoap_req_send(buf, len, remote, _resp_handler, NULL); len is the sum of payload and metadata length.

when len is greater than 91 bytes,client also crashes with *** stack smashing detected ***: terminated.

  1. another interesting point is,even though the server and client crashes when the length is greater than 91 bytes, both send the payload to the other side.So payload is sent to the client in COAP GET method from server and client can also send payload to a resource in server using COAP PUT method. After the payload is send,the system crashes.

Could anyone help me to resolve this issue ?

Try increasing your thread stack size - this was an issue even with the example.

I have increased the stack size by adding

CFLAGS += -DTHREAD_STACKSIZE_MAIN=(2*THREAD_STACKSIZE_LARGE)

still it crashes.Is there anything else to add in the Makefile ?

Are you using the main thread for the CoAP functionality? Otherwise you can specify the thread stack size when calling thread_create()

@benpicco I am using the main thread for CoAP. Th error can be easly reproduced by modifying the example. . For eg.Changing the riot_board_handler function like this.Even after increasing the main thread stacksize,system crashes.I am tesing on native and communicating between two native instances via tap interface.

char temp_buf[85];
static ssize_t _riot_board_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx)
{
    (void)ctx;
    gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
    coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
    size_t resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);

    memset(temp_buf, 'd',84);
    *(temp_buf + 85) = '\0';

    /* write the RIOT board name in the response buffer */
    if (pdu->payload_len >= strlen(temp_buf)) {
        printf("pdu->payload_len:%d\n",pdu->payload_len);
        memcpy(pdu->payload, temp_buf, strlen(temp_buf));
        printf("total len(%d+%d):%d\n",resp_len,strlen(temp_buf),(resp_len + strlen(temp_buf)));
        return resp_len + strlen(temp_buf);
    }
    else {
        puts("gcoap_cli: msg buffer too small");
        return gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR);
    }
}
1 Like

Thank you! Beware that with *(temp_buf + 85) = '\0'; you are corrupting memory yourself, but this can still be reproduced with

    static char temp_buf[86];
    memset(temp_buf, 'd', sizeof(temp_buf));
    temp_buf[sizeof(temp_buf) - 1] = '\0';

coap get fe80::7837:fcff:fe7d:1aaf 5684 /riot/board

*** stack smashing detected ***: terminated

Program received signal SIGABRT, Aborted.
0xf7fc7549 in __kernel_vsyscall ()
(gdb) bt
#0  0xf7fc7549 in __kernel_vsyscall ()
#1  0xf7df1b26 in ?? () from /lib/i386-linux-gnu/libc.so.6
#2  0xf7da0aa5 in raise () from /lib/i386-linux-gnu/libc.so.6
#3  0xf7d8936c in abort () from /lib/i386-linux-gnu/libc.so.6
#4  0xf7de431c in ?? () from /lib/i386-linux-gnu/libc.so.6
#5  0xf7e9a93c in __fortify_fail () from /lib/i386-linux-gnu/libc.so.6
#6  0xf7e9a90f in __stack_chk_fail () from /lib/i386-linux-gnu/libc.so.6
#7  0x08071b38 in __stack_chk_fail_local ()
#8  0x0806a458 in dtls_send_multi (ctx=0x80a8064 <dtlscontext_storage_data+36>, 
    peer=0x80a8280 <peer_storage_data>, security=0x80a7de0 <security_storage_data>, 
    session=0x80a8284 <peer_storage_data+4>, type=23 '\027', buf_array=0x809f4bc <_msg_stack+15324>, 
    buf_len_array=0x809f4b8 <_msg_stack+15320>, buf_array_len=1)
    at /home/benpicco/dev/RIOT/build/pkg/tinydtls/dtls.c:1735
#9  0x0806a49b in dtls_send (ctx=ctx@entry=0x80a8064 <dtlscontext_storage_data+36>, 
    peer=<optimized out>, type=type@entry=23 '\027', buf=<optimized out>, buflen=<optimized out>)
    at /home/benpicco/dev/RIOT/build/pkg/tinydtls/peer.h:73
#10 0x0806e2e4 in dtls_write (ctx=0x80a8064 <dtlscontext_storage_data+36>, 
    dst=0x809f6e4 <_msg_stack+15876>, 
    buf=0x809b6c0 <_listen_buf> "REҩ\023\313\300\377", 'd' <repeats 85 times>, len=93)
    at /home/benpicco/dev/RIOT/build/pkg/tinydtls/dtls.c:310
#11 0x0806fbef in sock_dtls_send_aux (sock=0x809b420 <_sock_dtls>, 
    remote=0x809f6e4 <_msg_stack+15876>, data=0x809b6c0 <_listen_buf>, len=93, 
    timeout=<optimized out>, aux=0x0) at /home/benpicco/dev/RIOT/pkg/tinydtls/contrib/sock_dtls.c:647
#12 0x08050770 in sock_dtls_send (timeout=4294967295, len=93, data=0x809b6c0 <_listen_buf>, 
    remote=0x809f6e4 <_msg_stack+15876>, sock=<optimized out>)
    at /home/benpicco/dev/RIOT/sys/include/net/sock/dtls.h:984
#13 _tl_send (sock=sock@entry=0x809f6dc <_msg_stack+15868>, data=data@entry=0x809b6c0 <_listen_buf>, 
    len=93, remote=0x809f6c4 <_msg_stack+15844>)
    at /home/benpicco/dev/RIOT/sys/net/application_layer/gcoap/gcoap.c:989
#14 0x08051a22 in _process_coap_pdu (sock=sock@entry=0x809f6dc <_msg_stack+15868>, 
    remote=remote@entry=0x809f6c4 <_msg_stack+15844>, 
    buf=buf@entry=0x809b6c0 <_listen_buf> "REҩ\023\313\300\377", 'd' <repeats 85 times>, len=17, 
    truncated=false) at /home/benpicco/dev/RIOT/sys/net/application_layer/gcoap/gcoap.c:394
#15 0x08051cf6 in _on_sock_dtls_evt (sock=0x809b420 <_sock_dtls>, type=SOCK_ASYNC_MSG_RECV, arg=0x0)
    at /home/benpicco/dev/RIOT/sys/net/application_layer/gcoap/gcoap.c:265
#16 0x08066fcc in _event_handler (ev=0x809b44c <_sock_dtls+44>)
    at /home/benpicco/dev/RIOT/sys/net/sock/async/event/sock_async_event.c:33
#17 0x080508f6 in event_loop_multi (n_queues=1, queues=0x809b8c0 <_queue>)
    at /home/benpicco/dev/RIOT/sys/include/event.h:409
#18 event_loop (queue=0x809b8c0 <_queue>) at /home/benpicco/dev/RIOT/sys/include/event.h:431
#19 _event_loop (arg=0x0) at /home/benpicco/dev/RIOT/sys/net/application_layer/gcoap/gcoap.c:181
#20 0xf7db3b39 in makecontext () from /lib/i386-linux-gnu/libc.so.6
#21 0x00000000 in ?? ()

@benpicco thanks for checking the error :slight_smile: . Still I got the same error,even after increasing the main thread stack size.What could be the solution ?

This looks more like a bug in Gcoap, might even allow for remote code execution if it allows manipulating the stack. Unfortunately I don’t have much time currently to look into that.