Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[gdb] Fix heap-buffer-overflow in child_path
When compiling gdb with '-lasan -fsanitizer=address' and running tests with: - export ASAN_OPTIONS="detect_leaks=0:alloc_dealloc_mismatch=0", and - a target board using local-board.exp, which sets sysroot to "" we run into a heap-buffer-overflow in child_path for f.i. gdb.arch/amd64-byte: ... ==3997==ERROR: AddressSanitizer: heap-buffer-overflow on address \ 0x60200002abcf at pc 0x5602acdf6872 bp 0x7ffe5237a090 sp 0x7ffe5237a080 READ of size 1 at 0x60200002abcf thread T0 #0 0x5602acdf6871 in child_path(char const*, char const*) \ gdb/common/pathstuff.c:161 riscvarchive#1 0x5602adb06587 in find_separate_debug_file gdb/symfile.c:1483 riscvarchive#2 0x5602adb06f2f in find_separate_debug_file_by_debuglink[abi:cxx11](...) \ gdb/symfile.c:1563 riscvarchive#3 0x5602ad13b743 in elf_symfile_read gdb/elfread.c:1293 riscvarchive#4 0x5602adb01cfa in read_symbols gdb/symfile.c:798 riscvarchive#5 0x5602adb03769 in syms_from_objfile_1 gdb/symfile.c:1000 riscvarchive#6 0x5602adb039d0 in syms_from_objfile gdb/symfile.c:1017 riscvarchive#7 0x5602adb04551 in symbol_file_add_with_addrs gdb/symfile.c:1124 riscvarchive#8 0x5602adb04ebf in symbol_file_add_from_bfd(...) gdb/symfile.c:1204 riscvarchive#9 0x5602ada5a78d in solib_read_symbols(...) gdb/solib.c:695 riscvarchive#10 0x5602ada5bdae in solib_add(char const*, int, int) gdb/solib.c:1004 riscvarchive#11 0x5602ada49bcd in enable_break gdb/solib-svr4.c:2394 riscvarchive#12 0x5602ada4dae9 in svr4_solib_create_inferior_hook gdb/solib-svr4.c:3028 riscvarchive#13 0x5602ada5d4f1 in solib_create_inferior_hook(int) gdb/solib.c:1215 riscvarchive#14 0x5602ad347f66 in post_create_inferior(target_ops*, int) \ gdb/infcmd.c:467 riscvarchive#15 0x5602ad348b3c in run_command_1 gdb/infcmd.c:663 riscvarchive#16 0x5602ad348e55 in run_command gdb/infcmd.c:686 riscvarchive#17 0x5602acd7d32b in do_const_cfunc gdb/cli/cli-decode.c:106 riscvarchive#18 0x5602acd84bfe in cmd_func(cmd_list_element*, char const*, int) \ gdb/cli/cli-decode.c:1892 riscvarchive#19 0x5602adc62a90 in execute_command(char const*, int) gdb/top.c:630 riscvarchive#20 0x5602ad5053e6 in catch_command_errors gdb/main.c:372 riscvarchive#21 0x5602ad507eb1 in captured_main_1 gdb/main.c:1138 riscvarchive#22 0x5602ad5081ec in captured_main gdb/main.c:1163 riscvarchive#23 0x5602ad508281 in gdb_main(captured_main_args*) gdb/main.c:1188 riscvarchive#24 0x5602ac9ddc3a in main gdb/gdb.c:32 riscvarchive#25 0x7f582b56eb96 in __libc_start_main \ (/lib/x86_64-linux-gnu/libc.so.6+0x21b96) riscvarchive#26 0x5602ac9dda09 in _start \ (/home/smarchi/build/binutils-gdb/gdb/gdb+0x19a2a09) 0x60200002abcf is located 1 bytes to the left of 1-byte region \ [0x60200002abd0,0x60200002abd1) allocated by thread T0 here: #0 0x7f582e0e4b50 in __interceptor_malloc \ (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50) riscvarchive#1 0x5602acdd3656 in xmalloc gdb/common/common-utils.c:44 riscvarchive#2 0x5602aefe17d1 in xstrdup libiberty/xstrdup.c:34 riscvarchive#3 0x5602acdf61f6 in gdb_realpath(char const*) gdb/common/pathstuff.c:80 riscvarchive#4 0x5602adb06278 in find_separate_debug_file gdb/symfile.c:1444 riscvarchive#5 0x5602adb06f2f in find_separate_debug_file_by_debuglink[abi:cxx11](...) \ gdb/symfile.c:1563 riscvarchive#6 0x5602ad13b743 in elf_symfile_read gdb/elfread.c:1293 riscvarchive#7 0x5602adb01cfa in read_symbols gdb/symfile.c:798 riscvarchive#8 0x5602adb03769 in syms_from_objfile_1 gdb/symfile.c:1000 riscvarchive#9 0x5602adb039d0 in syms_from_objfile gdb/symfile.c:1017 riscvarchive#10 0x5602adb04551 in symbol_file_add_with_addrs gdb/symfile.c:1124 riscvarchive#11 0x5602adb04ebf in symbol_file_add_from_bfd(...) gdb/solib.c:695 riscvarchive#13 0x5602ada5bdae in solib_add(char const*, int, int) gdb/solib.c:1004 riscvarchive#14 0x5602ada49bcd in enable_break gdb/solib-svr4.c:2394 riscvarchive#15 0x5602ada4dae9 in svr4_solib_create_inferior_hook gdb/solib-svr4.c:3028 riscvarchive#16 0x5602ada5d4f1 in solib_create_inferior_hook(int) gdb/solib.c:1215 riscvarchive#17 0x5602ad347f66 in post_create_inferior(target_ops*, int) \ gdb/infcmd.c:467 riscvarchive#18 0x5602ad348b3c in run_command_1 gdb/infcmd.c:663 riscvarchive#19 0x5602ad348e55 in run_command gdb/infcmd.c:686 riscvarchive#20 0x5602acd7d32b in do_const_cfunc gdb/cli/cli-decode.c:106 riscvarchive#21 0x5602acd84bfe in cmd_func(cmd_list_element*, char const*, int) \ gdb/cli/cli-decode.c:1892 riscvarchive#22 0x5602adc62a90 in execute_command(char const*, int) gdb/top.c:630 riscvarchive#23 0x5602ad5053e6 in catch_command_errors gdb/main.c:372 riscvarchive#24 0x5602ad507eb1 in captured_main_1 gdb/main.c:1138 riscvarchive#25 0x5602ad5081ec in captured_main gdb/main.c:1163 riscvarchive#26 0x5602ad508281 in gdb_main(captured_main_args*) gdb/main.c:1188 riscvarchive#27 0x5602ac9ddc3a in main gdb/gdb.c:32 riscvarchive#28 0x7f582b56eb96 in __libc_start_main \ (/lib/x86_64-linux-gnu/libc.so.6+0x21b96) SUMMARY: AddressSanitizer: heap-buffer-overflow gdb/common/pathstuff.c:161 \ in child_path(char const*, char const*) Shadow bytes around the buggy address: 0x0c047fffd520: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fa 0x0c047fffd530: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c047fffd540: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c047fffd550: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa 0x0c047fffd560: fa fa fd fa fa fa fd fa fa fa fd fa fa fa 00 00 =>0x0c047fffd570: fa fa 07 fa fa fa 00 fa fa[fa]01 fa fa fa fa fa 0x0c047fffd580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffd590: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffd5a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffd5b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffd5c0: 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 ==3997==ABORTING ... The direct cause is that child_path gets called with parent == "", so this test: ... if (IS_DIR_SEPARATOR (parent[parent_len - 1])) ... accesses parent[-1]. [ There is an open discussion (1) about whether an empty sysroot should indeed be represented internally as "". But this patch focuses on fixing the heap-buffer-overflow without any redesign. ] Fix this by guarding the test with 'parent_len > 0'. Note that the fix makes child_path behave the same for: - parent == "/" && child == "/foo" (returns "foo") - parent == "" and child == "/foo" (returns "foo"). Build and reg-tested on x86_64-linux. (1) https://sourceware.org/ml/gdb-patches/2019-05/msg00193.html gdb/ChangeLog: 2019-06-17 Tom de Vries <[email protected]> PR gdb/24617 * common/pathstuff.c (child_path): Make sure parent_len > 0 before accessing parent[parent_len - 1].
- Loading branch information