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

heap-use-after-free in fy-walk.c #120

Open
gabe-sherman opened this issue Aug 9, 2024 · 1 comment
Open

heap-use-after-free in fy-walk.c #120

gabe-sherman opened this issue Aug 9, 2024 · 1 comment

Comments

@gabe-sherman
Copy link

A heap-use-after-free error occurs at line 3147 in fy-walk.c when the below code is provided a malformed input. This occurs when fy_path_expr_free(exprl) is invoked, which leads to a heap-use-after free error a couple function calls later.

#include <stdarg.h>
#include <libfyaml.h>

int main(int argc, char *argv[])
{
	size_t emit_size = 256;
	char *emit = malloc(emit_size);

	struct fy_path_parse_cfg cfg;

	struct fy_document* doc = fy_document_build_from_file(NULL, argv[1]);

	fy_emit_document_to_buffer(doc, FYECF_MODE_MANUAL, emit, emit_size);

	fy_path_expr_build_from_string(NULL, emit, emit_size);
}

Test Environment

Ubuntu 22.04, 64bit

How to trigger

./filename poc

Version

Latest: 592ccc1

POC File

https://github.com/gabe-sherman/bug-pocs/blob/main/fyaml/c3

Address Sanitizer Output

==2360387==ERROR: AddressSanitizer: heap-use-after-free on address 0x507000000208 at pc 0x5555558e6b3c bp 0x7fffffffd840 sp 0x7fffffffd838
READ of size 8 at 0x507000000208 thread T0
    #0 0x5555558e6b3b in list_empty /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/util/fy-list.h:198:15
    #1 0x5555558e6b3b in fy_path_expr_list_empty /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.h:283:1
    #2 0x5555558e6b3b in fy_path_expr_list_head /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.h:283:1
    #3 0x5555558c477c in fy_path_expr_list_pop /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.h:283:1
    #4 0x5555558c4627 in fy_path_expr_free /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:548:18
    #5 0x5555558eb973 in evaluate_new /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3147:2
    #6 0x5555558ed91a in fy_path_parse_expression /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3432:11
    #7 0x5555558f050a in fy_path_parse_expr_from_string /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3726:9
    #8 0x5555558f0ae2 in fy_path_expr_build_from_string /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3757:9
    #9 0x555555744249 in main /home/gabriel/fuzzing-trials/fyaml/crashes/c3/rep.c:15:2
    #10 0x7ffff765ed8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #11 0x7ffff765ee3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #12 0x55555566b3a4 in _start (/home/gabriel/fuzzing-trials/fyaml/crashes/c3/r.out+0x1173a4) (BuildId: efcb4cdcb5d135d4aa79010b4168f2cbe2c4797c)

0x507000000208 is located 40 bytes inside of 72-byte region [0x5070000001e0,0x507000000228)
freed by thread T0 here:
    #0 0x5555557074a6 in free (/home/gabriel/fuzzing-trials/fyaml/crashes/c3/r.out+0x1b34a6) (BuildId: efcb4cdcb5d135d4aa79010b4168f2cbe2c4797c)
    #1 0x5555558eb96b in evaluate_new /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3146:2
    #2 0x5555558ea999 in evaluate_new /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:2974:10
    #3 0x5555558ed91a in fy_path_parse_expression /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3432:11
    #4 0x5555558f050a in fy_path_parse_expr_from_string /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3726:9
    #5 0x5555558f0ae2 in fy_path_expr_build_from_string /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:3757:9
    #6 0x555555744249 in main /home/gabriel/fuzzing-trials/fyaml/crashes/c3/rep.c:15:2
    #7 0x7ffff765ed8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

previously allocated by thread T0 here:
    #0 0x55555570774e in malloc (/home/gabriel/fuzzing-trials/fyaml/crashes/c3/r.out+0x1b374e) (BuildId: efcb4cdcb5d135d4aa79010b4168f2cbe2c4797c)
    #1 0x5555558c440e in fy_path_expr_alloc /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/lib/fy-walk.c:532:9

SUMMARY: AddressSanitizer: heap-use-after-free /home/gabriel/fuzzing-trials/fyaml/lib_asan/src/util/fy-list.h:198:15 in list_empty
Shadow bytes around the buggy address:
  0x506fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x507000000000: fa fa fa fa 00 00 00 00 00 00 00 00 00 fa fa fa
  0x507000000080: fa fa fd fd fd fd fd fd fd fd fd fd fa fa fa fa
  0x507000000100: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fd fd
  0x507000000180: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
=>0x507000000200: fd[fd]fd fd fd fa fa fa fa fa 00 00 00 00 00 00
  0x507000000280: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x507000000300: 00 fa fa fa fa fa 00 00 00 00 00 00 00 00 00 fa
  0x507000000380: fa fa fa fa 00 00 00 00 00 00 00 00 00 fa fa fa
  0x507000000400: fa fa 00 00 00 00 00 00 00 00 00 fa fa fa fa fa
  0x507000000480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==2360387==ABORTING
@gabe-sherman
Copy link
Author

To follow up, this heap-use-after free occurs for this reason: At this point in the process, the exprl variable is set to the value of the result of fy_expr_stack_peek called at line 2971. When evaluate_new is called again at line 2974, the value of the expr variable is set to the result of fy_expr_stack_pop called at line 2778. At this point, both exprl and expr point to the same location. The error handling routine is invoked in the internal function call, which returns -1, and expr is freed. However when the check to ret is done at line 2975, the error handling routine is entered again. The call to fy_path_expr_free(exprl) fails since that address was already freed in the previous function call. This all occurs in evaluate_new in fy-walk.c.

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

1 participant