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

PDU use after free when sending an OSCORE message with OSCORE disabled at build time #1414

Closed
fun-works opened this issue May 21, 2024 · 5 comments

Comments

@fun-works
Copy link

fun-works commented May 21, 2024

Environment

  • Build System: CMake
  • Operating System: Linux
  • Operating System Version: [ ]
  • Hosted Environment: None

libcoap Configuration Summary

I am using 4.3.4

If using a non-standard TLS library build, please also provide the ./configure
options or equivalent to aid troubleshooting.

Problem Description

I have disabled OSCORE at build time as we already have implemented OSCORE on top of libcoap(with some manual access to PDU with libcoap 4.3.0).
But with version 4.3.4, we are trying to remove the manual PDU update and still want to use our OSCORE with libcoap.

As I am running my application and sending an OSCORE message from client, I am getting PDU use after free error as below:
==31544==ERROR: AddressSanitizer: heap-use-after-free on address 0x612000011d42 at pc 0x7ffff7625310 bp 0x7ffff3afd6b0 sp 0x7ffff3afce60
READ of size 34 at 0x612000011d42 thread T1
#0 0x7ffff762530f in read_iovec ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:992
#1 0x7ffff76607ae in read_msghdr ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:3043
#2 0x7ffff7661f13 in __interceptor_sendmsg ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:3060
#3 0x555555aea84d in coap_socket_send /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_io.c:959
#4 0x555555af4dbf in coap_netif_dgrm_write /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_netif.c:136
#5 0x555555aed1bd in coap_session_send_pdu /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:789
#6 0x555555aed317 in coap_send_pdu /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:827
#7 0x555555aef394 in coap_send_internal /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:1562
#8 0x555555af2868 in handle_request /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:3248
#9 0x555555af39fd in coap_dispatch /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:3801
#10 0x555555af047c in coap_handle_dgram /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:2222
#11 0x555555aef9c7 in coap_handle_dgram_for_proto /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:1725
#12 0x555555aeff5b in coap_read_endpoint /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:2007
#13 0x555555af00c1 in coap_io_do_epoll /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:2118
#14 0x555555aebaad in coap_io_process_with_fds /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_io.c:1675
#15 0x555555aeb976 in coap_io_process /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_io.c:1525
#16 0x555555a8ee77 in myproj::stack::iot::transport::coap::Transport::Process() /home/projects/stack-main/src/transport/libcoap/stack_coap_transport.cpp:597
#17 0x55555596d29a in myproj::stack::iot::ServerCoreTask(stackAppCtxType*) /home/projects/stack-main/src/server/core/stack_server_core.cpp:795
#18 0x7ffff72a5ea6 in start_thread nptl/pthread_create.c:477
#19 0x7ffff71d5dee in __clone (/lib/x86_64-linux-gnu/libc.so.6+0xfddee)

0x612000011d42 is located 2 bytes inside of 262-byte region [0x612000011d40,0x612000011e46)
freed by thread T1 here:
==31544==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h:141 "((id & (((u32)-1) >> kReservedBits))) == ((id))" (0x1780011, 0x81780011)
#0 0x7ffff769c657 in AsanCheckFailed ../../../../src/libsanitizer/asan/asan_rtl.cpp:73
#1 0x7ffff76b9d4a in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_termination.cpp:78
#2 0x7ffff76b1bbd in __sanitizer::StackDepotBase<__sanitizer::StackDepotNode, 1, 20>::Get(unsigned int) ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h:141
#3 0x7ffff7616fec in GetStackTraceFromId ../../../../src/libsanitizer/asan/asan_descriptions.cpp:176
#4 0x7ffff7618c3b in __asan::HeapAddressDescription::Print() const ../../../../src/libsanitizer/asan/asan_descriptions.cpp:425
#5 0x7ffff761bf4b in __asan::AddressDescription::Print(char const*) const ../../../../src/libsanitizer/asan/asan_descriptions.h:234
#6 0x7ffff761bf4b in __asan::ErrorGeneric::Print() ../../../../src/libsanitizer/asan/asan_errors.cpp:591
#7 0x7ffff769c45b in __asan::ScopedInErrorReport::~ScopedInErrorReport() ../../../../src/libsanitizer/asan/asan_report.cpp:141
#8 0x7ffff769bd46 in __asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) ../../../../src/libsanitizer/asan/asan_report.cpp:470
#9 0x7ffff7625335 in read_iovec ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:992
#10 0x7ffff76607ae in read_msghdr ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:3043
#11 0x7ffff7661f13 in __interceptor_sendmsg ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:3060
#12 0x555555aea84d in coap_socket_send /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_io.c:959
#13 0x555555af4dbf in coap_netif_dgrm_write /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_netif.c:136
#14 0x555555aed1bd in coap_session_send_pdu /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:789
#15 0x555555aed317 in coap_send_pdu /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:827
#16 0x555555aef394 in coap_send_internal /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:1562
#17 0x555555af2868 in handle_request /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:3248
#18 0x555555af39fd in coap_dispatch /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:3801
#19 0x555555af047c in coap_handle_dgram /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:2222
#20 0x555555aef9c7 in coap_handle_dgram_for_proto /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:1725
#21 0x555555aeff5b in coap_read_endpoint /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:2007
#22 0x555555af00c1 in coap_io_do_epoll /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_net.c:2118
#23 0x555555aebaad in coap_io_process_with_fds /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_io.c:1675
#24 0x555555aeb976 in coap_io_process /home/projects/stack-main/_build/_deps/libcoap-src/src/coap_io.c:1525
#25 0x555555a8ee77 in myproj::stack::iot::transport::coap::Transport::Process() /home/projects/stack-main/src/transport/libcoap/stack_coap_transport.cpp:597
#26 0x55555596d29a in myproj::stack::iot::ServerCoreTask(stackAppCtxType*) /home/projects/stack-main/src/server/core/stack_server_core.cpp:795
#27 0x7ffff72a5ea6 in start_thread nptl/pthread_create.c:477
#28 0x7ffff71d5dee in __clone (/lib/x86_64-linux-gnu/libc.so.6+0xfddee)

Any idea if I am missing anything.
For your information, now even I have removed any response formation in our application to get it not crashed, but still I see this issue.

@mrdeep1
Copy link
Collaborator

mrdeep1 commented May 21, 2024

It looks like in the request handler doing your specific OSCORE stuff called from handle_request() for the resource defined in the CoAP PDU is releasing the response PDU's data as pointed to by response->token - response->hdr_size, but the response PDU object is still there.

This is where things start to fail

ssize_t
coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu) {
  ssize_t bytes_written = -1;
  assert(pdu->hdr_size > 0);

  /* Caller handles partial writes */
  bytes_written = session->sock.lfunc[COAP_LAYER_SESSION].l_write(session,
                  pdu->token - pdu->hdr_size,
                  pdu->used_size + pdu->hdr_size);
  coap_show_pdu(COAP_LOG_DEBUG, pdu);
  return bytes_written;
}

where l.write is coap_netif_dgrm_write() in your case.

What does your OSCORE implementation provide that libcoap's version does not?

@rpati12
Copy link

rpati12 commented May 21, 2024

What does your OSCORE implementation provide that libcoap's version does not?
==> We support both libcoap and openthread. We have a common oscore implementation which works on top of both these coap APIs. And this was already an old implementation we did as there was no support of OSCORE in libcoap or was in WIP.

Regarding freeing the response PDU, it looks unusual as we have not freed it explicitly. I had called it once but now I am trying after removing the delete-pdu() call. I will re-look into it and get back.

Thanks for your prompt response as always.

@mrdeep1
Copy link
Collaborator

mrdeep1 commented May 21, 2024

As a FYI, the libcoap code picks up the OSCORE option on an inbound packet and says it is invalid in the function coap_option_check_critical() if libcoap is not running OSCORE before the PDU gets passed up to the application. However, calling coap_register_option(context, COAP_OPTION_OSCORE) allows this to be overridden.

@fun-works
Copy link
Author

Yes, we have registered oscore option 9 to receive the oscore packets. Thanks for the information.

@fun-works
Copy link
Author

We can close this issue as it was an issue in my code. Thanks for your support.

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

No branches or pull requests

3 participants