lexborisov/myhtml

AddressSanitizer: NPE read in multithreading mode

hongxuchen opened this issue · 6 comments

When fuzzing the AddressSanitizer hardened callback_tree_node_high_level, we found several vulnerabilities/crashes due to multithreading.
A sample proof-of-crash (poc) file (zipped) is:

NPE_r__mchar_async.c:656_1.html.zip

with the error message like:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==12692==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000504b39 bp 0xcdce30adcdcf51b8 sp 0x7ffff30fdb20 T2)
==12692==The signal is caused by a READ memory access.
==12692==Hint: address points to the zero page.
    #0 0x504b38 in mchar_async_cache_delete /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/mycore/utils/mchar_async.c:656:44
    #1 0x506694 in mchar_async_malloc /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/mycore/utils/mchar_async.c:414:24
    #2 0x500cdb in mycore_string_init /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/mycore/./mystring.c:30:21
    #3 0x4cc912 in myhtml_parser_worker /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/myhtml/./parser.c:232:9
    #4 0x4fcf88 in mythread_function_queue_batch /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/mycore/./thread_queue.c:549:17
    #5 0x7ffff781f6da in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76da)
    #6 0x7ffff6f2488e in clone /build/glibc-OTsEL5/glibc-2.27/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/mycore/utils/mchar_async.c:656:44 in mchar_async_cache_delete
Thread T2 created by T0 here:
    #0 0x47da3a in pthread_create (/home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/bin/myhtml/callback_tree_node_high_level+0x47da3a)
    #1 0x4f997c in mythread_thread_create /home/hongxu/fuzzing/Targets/myhtml/myhtml-asan/source/myport/posix/mycore/./thread.c:39:8

==12692==ABORTING

In case it is not easily reproducible, we use the following command:

for i in `seq 1 1000`; do ./callback_tree_node_high_level $FILE &>/tmp/error_msg; grep AddressSanitizer /tmp/error_msg >/dev/null; if [[ $? -eq 0 ]];  then cat /tmp/error_msg; echo "\n$i: 
 $f"; break; fi; done

We will provide other pocs later.

FYI, we collected several other pocs with different crashing backtraces here.

@hongxuchen
I will definitely take a look and figure it out.

Thank you for the report!

@lexborisov my pleasure!

Hi @lexborisov , I had a quick review of the source code, it seems to relevant with the data race on queue->nodes_uses, which subsequently affects the memory (re)allocation operations and the wait/sleep flows. I'd suggest applying some basic locks for this data to avoid security and logic issues. Modest seems also affected.

@hongxuchen

Thanks for the work you've done!
I plan to rewrite the part of the code responsible for threads.

P.S.: There are no such problems in the lexbor project: the speed is the same, there are no threads, it consumes less resources, selectors will appear soon.

@lexborisov Great! Will try lexbor 👌