Hi, busybox developers, We found a use-after-free vulnerability in awk applet of busybox v1.36.1. The affected component is awk.c:1064 in copyvar function. Following is the reproduction process, and we put the poc file in the attachment. [1.] Environment Ubuntu 18.04, 64 bit BusyBox 1.36.1 Clang 6.0.0 [2.] Compilation 2.1 Modify the Makefile: HOSTCC=clang -fsanitize=address HOSTCXX=clang++ -fsanitize=address CC=clang CFLAGS=-fsanitize=address CPPFLAGS=-fsanitize=address LDFLAGS="-Wl,--allow-multiple-definition" 2.2 Modify the Config.in file, switch the following configs to y: DEBUG: y DEBUG_PESSIMIZE: y FEATURE_CLEAN_UP: y DEBUG_SANITIZE: y 2.3 Commands for compilation: export ASAN_OPTIONS=detect_leaks=0 make defconfig make install [3.] Reproduction export ASAN_OPTIONS="abort_on_error=1 symbolize=0" ./busybox_unstripped awk -f $poc ./awk_t1_input [ASAN report]: ==32093==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000003080 at pc 0x000000e7dfe2 bp 0x7fff6ee9b930 sp 0x7fff6ee9b928 READ of size 4 at 0x606000003080 thread T0 #0 0xe7dfe1 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe7dfe1) #1 0xe4bbdf (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4bbdf) #2 0xe4eb16 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4eb16) #3 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #4 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #5 0xe4062d (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4062d) #6 0x50ac81 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x50ac81) #7 0x50dbaf (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x50dbaf) #8 0x51036d (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x51036d) #9 0x50db58 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x50db58) #10 0x50c3fd (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x50c3fd) #11 0x7f8358526c86 (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) #12 0x41e459 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x41e459) 0x606000003080 is located 0 bytes inside of 64-byte region [0x606000003080,0x6060000030c0) freed by thread T0 here: #0 0x4dc500 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x4dc500) #1 0xe7f4ca (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe7f4ca) #2 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #3 0xe4eb16 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4eb16) #4 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #5 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #6 0xe4062d (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4062d) #7 0x50ac81 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x50ac81) previously allocated by thread T0 here: #0 0x4dc6d0 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x4dc6d0) #1 0x519df2 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x519df2) #2 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #3 0xe4eb16 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4eb16) #4 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #5 0xe4886f (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4886f) #6 0xe4062d (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe4062d) #7 0x50ac81 (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0x50ac81) SUMMARY: AddressSanitizer: heap-use-after-free (/home/zclin/afl-vul-score/llvm_mode/research/path-collect-all-new-0524/path-collect-all-new/busybox/reproduce/busybox-1_36_1/fuzz_check/awk/busybox_unstripped+0xe7dfe1) [line number]: addr2line -e ./busybox_unstripped 0xe7dfe1 .../busybox-1_36_1/editors/awk.c:1064 Best wishes, Zclin
Created attachment 9673 [details] POC file
Created attachment 9676 [details] awk_t1_input file
The result of OC_REPLACE may be a TEMPVAR0 via L.v res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, ...);
This appears to be fixed in git master. valgrind with the attached POC does not show anything. But I am not sure which commit fixes it?
A git bisect with the POC shows that it was fixed with commit 0256e00a9d077588bd3a39f5a1ef7e2eaa2911e4 (HEAD) Author: Denys Vlasenko <vda.linux@googlemail.com> Date: Tue May 30 16:42:18 2023 +0200 awk: fix precedence of = relative to == https://git.busybox.net/busybox/commit/editors/awk.c?id=0256e00a9d077588bd3a39f5a1ef7e2eaa2911e4
(In reply to Natanael Copa from comment #5) The commit that "fixes" it also introduces a regression. awk 'BEGIN { a = 0 ? \"yes\": \"no\"; print a }' Prints '0' instead of 'no'. But that is a different issue. I have a smaller reproducer for the use-after-free: ``` function f1(v) { return v } function f2(a) { return f1(a) -= 0 } function f3(a) { return missingfunc(a) } BEGIN { f2() || f3() } ``` Or: awk 'function f1(v) { return v } function f2(a) { return f1(a) -= 0 } function f3(a) { return missingfunc(a) } BEGIN { f2() || f3() }'