obgm / libcoap

A CoAP (RFC 7252) implementation in C
Other
790 stars 422 forks source link

SEGV in coap_handle_request_put_block function at src/coap_block.c #1509

Closed Terminator111 closed 2 weeks ago

Terminator111 commented 2 weeks ago

Environment

libcoap Configuration Summary

libcoap package version : "4.3.5rc3" libcoap package source : "v4.3.5-rc3-8-gc2b34daa" libcoap API version : "3" libcoap ABI version : "3.1.2" libcoap libtool SO version : "4.2.1" libcoap DTLS lib extn : "-gnutls" host system : "x86_64-pc-linux-gnu" build with server support : "yes" build with client support : "yes" build with proxy support : "yes" build with IPv4 support : "yes" build with IPv6 support : "yes" build with Unix socket support : "yes" build with TCP support : "yes" build DTLS support : "yes" --> GnuTLS around : "yes" (found GnuTLS 3.6.13) GnuTLS_CFLAGS : "-I/usr/include/p11-kit-1" GnuTLS_LIBS : "-lgnutls" add default names : "yes" build Observe Persist : "yes" build using epoll : "yes" enable small stack size : "no" enable separate responses : "yes" enable OSCORE support : "yes" enable Q-Block support : "yes" enable max logging level : "none" enable thread safe code : "yes" enable recursive lock check : "yes" build doxygen pages : "no" build man pages : "no" build unit test binary : "no" build examples : "yes" install examples source : "yes" build with gcov support : "no" build shared library : "yes" build static library : "yes"

Problem Description

I triggered a SEGV bug reported by AddressSanitizer when fuzzing libcoap for more than 13 hours. The bug occurs due to a segmentation fault when the function coap_handle_request_put_block in coap_block.c attempts to access a memory address that is close to null, indicating a likely null pointer dereference or an attempt to read memory from an uninitialized or invalid pointer during the handling of a PUT request with block-wise transfer.

Expected Behavior

The expected behavior is that the coap_handle_request_put_block function should correctly handle the PUT request with block-wise transfer in the CoAP protocol without attempting to access invalid memory. The function should ensure that all pointers are properly initialized and valid before dereferencing them, allowing the request to be processed without causing a segmentation fault, leading to stable and correct execution of the CoAP server.

Actual Behavior

The actual behavior is that the coap_handle_request_put_block function in the CoAP server attempts to access an invalid memory address near the null pointer, leading to a segmentation fault. This results in the program crashing during the handling of a PUT request with block-wise transfer, instead of processing the request as expected. The AddressSanitizer tool detects this memory access violation and terminates the program, highlighting a wrong memory handling within the function.

Steps to reproduce

I'm sorry that I can't guarantee the success of the reproduction, because I used tools to fuzz for more than 13 hours before triggering this bug. I have tried to send packets manually, but it turned out that a single round or several rounds of sending packets could not trigger this problem. I have conducted multiple experiments, and it took an average of 9 hours of continuous fuzzing to trigger this bug. Therefore, I apologize that I can only provide the compilation process and startup parameters without hexstreams here.

  1. Prepare the build environment and compile the libcoap project.
    • Set the environment variables for the compiler and linker:
      export CC=afl-clang-fast CXX=afl-clang-fast++
      export CFLAGS="-g -fsanitize=address,undefined -fno-omit-frame-pointer"
      export CXXFLAGS="-g -fsanitize=address,undefined -fno-omit-frame-pointer"
      export LDFLAGS="-fsanitize=address,undefined"
      export AFL_USE_ASAN=1
    • Navigate to the libcoap directory and clear any previous configurations:
      cd libcoap
      bash ./autogen.sh --clear
    • Generate the new configuration scripts and run the configure script with the desired options:
      bash ./autogen.sh
      bash ./configure --disable-doxygen --disable-manpages --disable-dtls
    • Compile the project:
      make -j
  2. Run the server:
    cd examples
    ./coap-server -A 127.0.0.1 -p 6999 -e -d 100 -v 9 -P coap://127.0.0.1:5999,proxy1 -L 3 -N -g 224.0.1.187 -X 64
  3. fuzz...

Debug Logs

Here is the complete logs of server (too large): https://drive.google.com/file/d/1zPV8oewSj2FWAW905sbT-SJKj3NFJxEy/view?usp=sharing

Asan Report:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==2636018==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x7f1a4f220a66 bp 0x7ffc86d69a70 sp 0x7ffc86d697a0 T0)
==2636018==The signal is caused by a READ memory access.
==2636018==Hint: address points to the zero page.
    #0 0x7f1a4f220a66 in coap_handle_request_put_block /root/protocolFuzz/coap/libcoap/src/coap_block.c
    #1 0x7f1a4f25dc67 in handle_request /root/protocolFuzz/coap/libcoap/src/coap_net.c:3346:9
    #2 0x7f1a4f251677 in coap_dispatch /root/protocolFuzz/coap/libcoap/src/coap_net.c:4189:7
    #3 0x7f1a4f258d7d in coap_handle_dgram /root/protocolFuzz/coap/libcoap/src/coap_net.c:2475:3
    #4 0x7f1a4f258215 in coap_handle_dgram_for_proto /root/protocolFuzz/coap/libcoap/src/coap_net.c:1953:14
    #5 0x7f1a4f258215 in coap_read_endpoint /root/protocolFuzz/coap/libcoap/src/coap_net.c:2236:16
    #6 0x7f1a4f258215 in coap_io_do_epoll_lkd /root/protocolFuzz/coap/libcoap/src/coap_net.c:2363:11
    #7 0x7f1a4f240848 in coap_io_process_with_fds_lkd /root/protocolFuzz/coap/libcoap/src/coap_io.c:1747:5
    #8 0x7f1a4f2404b2 in coap_io_process_lkd /root/protocolFuzz/coap/libcoap/src/coap_io.c:1543:10
    #9 0x7f1a4f2404b2 in coap_io_process /root/protocolFuzz/coap/libcoap/src/coap_io.c:1536:9
    #10 0x4ca32e in main /root/protocolFuzz/coap/libcoap/examples/coap-server.c:3132:20
    #11 0x7f1a4ee87082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16
    #12 0x41ebad in _start (/root/protocolFuzz/coap/libcoap/examples/.libs/coap-server+0x41ebad)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /root/protocolFuzz/coap/libcoap/src/coap_block.c in coap_handle_request_put_block
==2636018==ABORTING
mrdeep1 commented 2 weeks ago

Thanks for your work in checking this out.

It appears that the version of code you are using for doing the fuzzing is commit aac5de9e55a7afda8227dec0b43cc741b00d9d9f, not commit c2b34daa9b494cac5429a28c8b960708bcfe0c7a as indicated by the libcoap configuration summary. There are the following updates after the version you are using

1c97907f coap_net.h: add ifdef WITH_LWIP around lwip functions
a705e04c man: fix typo in logging documentation
c2b34daa mcast_loop: Drop mcast packet that server sent on different socket
e220c371 coap.h: Remove need for different coap.h files for different OS
8899063a coap_ws: accept longer header lines and specific header sent by firefox browser
3d790a59 reverse-proxy: Provide dedicated reverse-proxy handler setup function
626d4632 multicast: Document coap_mcast_set_hops()
79e6fcdb examples: Do CI pre-commit checks on man page examples
7dab8f6f Contiki-NG: Fix coap_resolve_address_info
76502319 coap_proxy.c: Fix error "'.*' expects argument of type 'int'"
540fede1 release 4.3.5rc3: Release candidate 3 for 4.3.5
82b721d7 coap-server.c: Replace SERVER_CAN_PROXY with COAP_PROXY_SUPPORT
92198b00 Supported: Break out run-time checks and libcoap build #defines
5f3d7eb2 reverse-proxy: Add in reverse proxy support to coap-server
af024f91 Connection-ID: Only change source port when CID has been negotiated
83718a6d Cleanup building header files for different OS
9656876b configure.ac: Not all pkg-config support PKG_CHECK_MODULES_STATIC
4851806c scan-build: CI Fail if scan-build warnings
8b2fb390 Connection-ID: Support changing client IP addresses
b75c784a Constrained Stack: No need for individual locks
48b56aa8 coap_prng: Provide global_lock protection
bbefdfc5 src/coap_mbedtls.c: Support EC-JPAKE with Client Only builds
bd328237 client-coap.c: Fix client spin loop for NO_SYS == 0
f4094636 Locking: Remove locking initialization from coap_new_context()
d87af119 coap_openssl.c: Fix libcoap shutdown restart issues
62686555 Locking: Unlock global_lock after coap_free_context() call
f9c7223e Locking: Use single global lock instead of context lock
af7da459 TLS: EC-JPAKE support (RFC8236)
7551d2e1 block handling: Update lg_crcv->last_used when sending Block1
bfdbdc3e coap_block.c: Replace usage of p with lg_xmit, lg_srcv, lg_crcv
d84d8639 LwIP: Update to STABLE 2.2.0

1483 (4851806c scan-build: CI Fail if scan-build warnings) has a fix to coap_handle_request_put_block()which may be the issue you are running to. Unfortunately AddressSanitizer does not give the faulting line at issue.

It may be that you need to run the server application using gdbto catch the line giving the issue.

Terminator111 commented 2 weeks ago

Thanks for the fix, I fuzzed the latest version for 20h and this bug no longer exists.

mrdeep1 commented 2 weeks ago

That is great - thanks for the feedback and doing the testing. I will close this off now.