310b344 [gdb] Fix heap-buffer-overflow in child_path

Authored and Committed by Tom de Vries 4 years ago
    [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
        #1 0x5602adb06587 in find_separate_debug_file gdb/symfile.c:1483
        #2 0x5602adb06f2f in find_separate_debug_file_by_debuglink[abi:cxx11](...) \
                          gdb/symfile.c:1563
        #3 0x5602ad13b743 in elf_symfile_read gdb/elfread.c:1293
        #4 0x5602adb01cfa in read_symbols gdb/symfile.c:798
        #5 0x5602adb03769 in syms_from_objfile_1 gdb/symfile.c:1000
        #6 0x5602adb039d0 in syms_from_objfile gdb/symfile.c:1017
        #7 0x5602adb04551 in symbol_file_add_with_addrs gdb/symfile.c:1124
        #8 0x5602adb04ebf in symbol_file_add_from_bfd(...) gdb/symfile.c:1204
        #9 0x5602ada5a78d in solib_read_symbols(...) gdb/solib.c:695
        #10 0x5602ada5bdae in solib_add(char const*, int, int) gdb/solib.c:1004
        #11 0x5602ada49bcd in enable_break gdb/solib-svr4.c:2394
        #12 0x5602ada4dae9 in svr4_solib_create_inferior_hook gdb/solib-svr4.c:3028
        #13 0x5602ada5d4f1 in solib_create_inferior_hook(int) gdb/solib.c:1215
        #14 0x5602ad347f66 in post_create_inferior(target_ops*, int) \
                              gdb/infcmd.c:467
        #15 0x5602ad348b3c in run_command_1 gdb/infcmd.c:663
        #16 0x5602ad348e55 in run_command gdb/infcmd.c:686
        #17 0x5602acd7d32b in do_const_cfunc gdb/cli/cli-decode.c:106
        #18 0x5602acd84bfe in cmd_func(cmd_list_element*, char const*, int) \
                              gdb/cli/cli-decode.c:1892
        #19 0x5602adc62a90 in execute_command(char const*, int) gdb/top.c:630
        #20 0x5602ad5053e6 in catch_command_errors gdb/main.c:372
        #21 0x5602ad507eb1 in captured_main_1 gdb/main.c:1138
        #22 0x5602ad5081ec in captured_main gdb/main.c:1163
        #23 0x5602ad508281 in gdb_main(captured_main_args*) gdb/main.c:1188
        #24 0x5602ac9ddc3a in main gdb/gdb.c:32
        #25 0x7f582b56eb96 in __libc_start_main \
                           (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
        #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)
        #1 0x5602acdd3656 in xmalloc gdb/common/common-utils.c:44
        #2 0x5602aefe17d1 in xstrdup libiberty/xstrdup.c:34
        #3 0x5602acdf61f6 in gdb_realpath(char const*) gdb/common/pathstuff.c:80
        #4 0x5602adb06278 in find_separate_debug_file gdb/symfile.c:1444
        #5 0x5602adb06f2f in find_separate_debug_file_by_debuglink[abi:cxx11](...) \
                          gdb/symfile.c:1563
        #6 0x5602ad13b743 in elf_symfile_read gdb/elfread.c:1293
        #7 0x5602adb01cfa in read_symbols gdb/symfile.c:798
        #8 0x5602adb03769 in syms_from_objfile_1 gdb/symfile.c:1000
        #9 0x5602adb039d0 in syms_from_objfile gdb/symfile.c:1017
        #10 0x5602adb04551 in symbol_file_add_with_addrs gdb/symfile.c:1124
        #11 0x5602adb04ebf in symbol_file_add_from_bfd(...) gdb/solib.c:695
        #13 0x5602ada5bdae in solib_add(char const*, int, int) gdb/solib.c:1004
        #14 0x5602ada49bcd in enable_break gdb/solib-svr4.c:2394
        #15 0x5602ada4dae9 in svr4_solib_create_inferior_hook gdb/solib-svr4.c:3028
        #16 0x5602ada5d4f1 in solib_create_inferior_hook(int) gdb/solib.c:1215
        #17 0x5602ad347f66 in post_create_inferior(target_ops*, int) \
                           gdb/infcmd.c:467
        #18 0x5602ad348b3c in run_command_1 gdb/infcmd.c:663
        #19 0x5602ad348e55 in run_command gdb/infcmd.c:686
        #20 0x5602acd7d32b in do_const_cfunc gdb/cli/cli-decode.c:106
        #21 0x5602acd84bfe in cmd_func(cmd_list_element*, char const*, int) \
                           gdb/cli/cli-decode.c:1892
        #22 0x5602adc62a90 in execute_command(char const*, int) gdb/top.c:630
        #23 0x5602ad5053e6 in catch_command_errors gdb/main.c:372
        #24 0x5602ad507eb1 in captured_main_1 gdb/main.c:1138
        #25 0x5602ad5081ec in captured_main gdb/main.c:1163
        #26 0x5602ad508281 in gdb_main(captured_main_args*) gdb/main.c:1188
        #27 0x5602ac9ddc3a in main gdb/gdb.c:32
        #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  <tdevries@suse.de>
    
    	PR gdb/24617
    	* common/pathstuff.c (child_path): Make sure parent_len > 0 before
    	accessing parent[parent_len - 1].
    
        
file modified
+6 -0
file modified
+1 -1