Project: libdwarf-code (davea42/libdwarf-code), language: c++
Vulnerability instance: libdwarf.cve-2022-39170
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/davea42/libdwarf-code/issues/132
## Description:
Issue: davea42/libdwarf-code#132
Title: [BUG] double free in _dwarf_exec_frame_instr
State: closed
Created by: kdsjZh
Created at: 2022-08-27 08:23:55+00:00

Issue Body:
Hello, I was testing my fuzzer and found a double free in dwarfdump, _dwarf_exec_frame_instr bug. A double free will be triggered when parsing a crafted file, when running ./dwarfdump -vv -a $POC, as shown in the attachment

## Environment
Ubuntu 22.04
gcc 11.2.0
libdwarf latest commit 271cc04a1bdd1f47d641ab9219fb138aa02839ff

## step to reproduce
```
export CC="gcc -fsanitize=address -g"
./autogen.sh && ./configure --disable-shared && make -j8
./src/bin/dwarfdump/dwarfdump -vv -a $POC
```

## ASan Output
```
=================================================================
==4097834==ERROR: AddressSanitizer: attempting double-free on 0x60c000000a00 in thread T0:
    #0 0x7fe56d032517 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x55c03cd25761 in _dwarf_exec_frame_instr /validate/libdwarf-code/src/lib/libdwarf/dwarf_frame.c:1501
    #2 0x55c03cd2c801 in dwarf_expand_frame_instructions /validate/libdwarf-code/src/lib/libdwarf/dwarf_frame.c:2547
    #3 0x55c03ccd8db4 in print_one_fde /validate/libdwarf-code/src/bin/dwarfdump/print_frames.c:1356
    #4 0x55c03ccd8db4 in print_all_fdes /validate/libdwarf-code/src/bin/dwarfdump/print_frames.c:2147
    #5 0x55c03ccd8db4 in print_frames /validate/libdwarf-code/src/bin/dwarfdump/print_frames.c:2367
    #6 0x55c03cc8db9a in process_one_file /validate/libdwarf-code/src/bin/dwarfdump/dwarfdump.c:1176
    #7 0x55c03cc782a4 in main /validate/libdwarf-code/src/bin/dwarfdump/dwarfdump.c:503
    #8 0x7fe56cd63d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #9 0x7fe56cd63e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #10 0x55c03cc798c4 in _start (/validate/libdwarf-code/src/bin/dwarfdump/dwarfdump+0x618c4)

0x60c000000a00 is located 0 bytes inside of 128-byte region [0x60c000000a00,0x60c000000a80)
freed by thread T0 here:
    #0 0x7fe56d032517 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x55c03cd257b3 in _dwarf_free_dfi_list /validate/libdwarf-code/src/lib/libdwarf/dwarf_frame.c:225
    #2 0x55c03cd257b3 in _dwarf_exec_frame_instr /validate/libdwarf-code/src/lib/libdwarf/dwarf_frame.c:1501

previously allocated by thread T0 here:
    #0 0x7fe56d032a37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x55c03cd21dc2 in _dwarf_exec_frame_instr /validate/libdwarf-code/src/lib/libdwarf/dwarf_frame.c:447

SUMMARY: AddressSanitizer: double-free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127 in __interceptor_free
==4097834==ABORTING
```

## POC

[poc.zip](https://github.com/davea42/libdwarf-code/files/9437551/poc.zip)


## Credit
Han Zheng ([NCNIPC of China](http://www.nipc.org.cn), [Hexhive](http://hexhive.epfl.ch))




Comments:
Comment by davea42 on 2022-08-29 22:20:39+00:00:
Yes, you are corrrect.
Thanks for the report and the fuzzed object file inside poc.zip.
I assigned this libdwarf vulnerability DW202208-001 and have
pushed the one-line (important) fix to github.
Closing this because it is fixed.
Thanks again for the report.

Attachments:
https://github.com/davea42/libdwarf-code/files/9437551/poc.zip

Commit References:
271cc04a1bdd1f47d641ab9219fb138aa02839ff

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
export CFLAGS="${CFLAGS} -g -Werror"
export CXXFLAGS="${CXXFLAGS} -g -Werror"
mkdir -p build
cd build
cmake ../
make -j$(nproc)
mkdir -p $SRC/corp

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/davea42/libdwarf-code libdwarf-code
RUN git -C libdwarf-code checkout 271cc04a1bdd1f47d641ab9219fb138aa02839ff
WORKDIR $SRC/libdwarf-code
COPY build.sh $SRC/

Additional files:
filename: fuzz_init_binary.c
content: /* Copyright 2021 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*
 * Libdwarf library callers can only use these headers.
 */
#include "dwarf.h"
#include "libdwarf.h"

/*
 * A fuzzer that simulates a small part of the simplereader.c example.
 * This fuzzer targets dwarf_init_b.
 */
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  char filename[256];
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());

  FILE *fp = fopen(filename, "wb");
  if (!fp) {
    return 0;
  }
  fwrite(data, size, 1, fp);
  fclose(fp);

  int my_init_fd = 0;
  Dwarf_Ptr errarg = 0;
  Dwarf_Handler errhand = 0;
  Dwarf_Error *errp = NULL;
  Dwarf_Debug dbg = 0;

  my_init_fd = open(filename, O_RDONLY);
  if (my_init_fd != -1) {
    dwarf_init_b(my_init_fd,DW_GROUPNUMBER_ANY,errhand,errarg,&dbg,errp);
    dwarf_finish(dbg);
    close(my_init_fd);
  }

  unlink(filename);
  return 0;
}

filename: fuzz_init_path.c
content: /* Copyright 2021 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

/*
 * Libdwarf library callers can only use these headers.
 */
#include "dwarf.h"
#include "libdwarf.h"

/*
 * A fuzzer that simulates a small part of the simplereader.c example.
 */
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  char filename[256];
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());

  FILE *fp = fopen(filename, "wb");
  if (!fp) {
    return 0;
  }
  fwrite(data, size, 1, fp);
  fclose(fp);
  Dwarf_Ptr errarg = 0;
  Dwarf_Handler errhand = 0;
  Dwarf_Debug dbg = 0;
  Dwarf_Error *errp = NULL;
#define MACHO_PATH_LEN 2000
  char macho_real_path[2000];
  dwarf_init_path(filename, macho_real_path, MACHO_PATH_LEN,
                  DW_GROUPNUMBER_ANY, errhand, errarg, &dbg, errp);

  dwarf_finish(dbg);

  unlink(filename);
  return 0;
}