Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / Git

Git Bisection Utility Wrapper Script for Memory Corruption Bugs

0.00/5 (No votes)
16 Jul 2020CPOL2 min read 3.6K   15  
A single-script git bisection utility wrapper for memory corruption bugs
Simple one-bash-script utility for git bisection. Receives suspected commit range, PoC input, and PoC command, produces the first bad commit (if it exists in the range).

Background

Git already has an embedded facility to trace back the root commit that introduced a given bug, namely git bisect, but its usage is seemingly not widespread. Why is it that? I suspect it's because git bisect still resorts to quite a lot of manual efforts, such as deciding whether a given commit is good (bug-free) or bad (bug-affected).

However, come to think of it, does every kind of bug actually need manual efforts to decide the presence of a certain bug? When we trace back the root commit of a certain bug, we simply investigate whether a given PoC input exhibits the same crash at the same program location. This procedure is quite mechanical, so it's not supposed to require human efforts.

On this account, I wrote a short bash script that automates the git bisect operation, given a suspected commit range and a PoC input/command. The script simply decides whether a certain commit is bug-affected by identifying the bug type and the crashing function in the ASAN report, spitting out the first bad commit hash as a result if it exists between the suspected commit range.

Requirements

  • ASAN-enabled compiler
  • (Obviously) git-managed project
  • Known bad/good commit hashes
  • PoC input
  • PoC command

Using the Code

  1. Place a BISECT file in the project directory, formatted as follows:
    XML
    <known_bad_commit> <known_good_commit> <poc_input_path> -- <poc_command>
    • <known_bad_commit>: Known bad commit hash (tag name applicable as tags/<name>)
    • <known_good_commit>: Known good commit hash
    • <poc_input_path>: Path to PoC input
    • <poc_command>: PoC command, with `@@` as a placeholder for the PoC input
  2. Place `bisector` in the project directory and execute it:
    $ ./bisector
  3. When finished, find the first bad commit in the FIRSTBAD file. See {good,bad}.bis for the ASAN dumps from the last good and first bad commit, respectively.

Example: CVE-2016-3658

  1. Prepare libtiff itself and the PoC input.
    $ git clone https://gitlab.com/libtiff/libtiff.git libtiff
    $ cd libtiff
    $ curl http://bugzilla.maptools.org/attachment.cgi?id=601 > POC

    The PoC input is provided by http://bugzilla.maptools.org/show_bug.cgi?id=2500.

  2. Place a BISECT file.
    d7db70c9 tags/Release-v4-0-0 POC -- ./tools/tiffset @@

    d7db70c9 is the last commit before 07/01/2015, and we expect CVE-2016-3658 has been created after 4.0.0.

  3. Place the bisector script and run it.
    $ ./bisector
    [*] Initializing...
     +  Commit range: 'd7db70c9'(bad) to 'f7b79dc7'(good)
     +  PoC input: POC
     +  PoC command: ./tools/tiffset @@
    [*] Generating most recent ASAN dump...
    [*] Testing commit 'd7db70c9'...
     +  Bug type: heap-buffer-overflow
     +  Crash function: TIFFWriteDirectoryTagSampleformatArray
    [*] Verifying good commit...
    [*] Testing commit 'f7b79dc7'... Good
    [*] Bisecting...
    [*] Testing commit 'd1be5cb7'... (234 remaining) Bad
    [*] Testing commit '871d1067'... (117 remaining) Bad
    [*] Testing commit '1358a916'... (58 remaining) Bad
    [*] Testing commit 'f502a159'... (29 remaining) Good
    [*] Testing commit '920688aa'... (15 remaining) Bad
    [*] Testing commit 'e54e9545'... (7 remaining) Good
    [*] Testing commit 'c0733844'... (4 remaining) Bad
    [*] Testing commit 'af47ad26'... (2 remaining) Good
    [*] Verifying...
    [*] Testing commit 'c0733844'... Bad
    [*] Testing commit 'af47ad26'... Good
     +  First bad commit: c0733844461ceb1b05f41968c1d962480f0db5f6 (see FIRSTBAD)
     +  {Last-good, First-bad} ASAN log: {good, bad}.bis
     +  All done!
  4. Check FIRSTBAD to see the first bad commit.
    c0733844461ceb1b05f41968c1d962480f0db5f6

Disclaimer

  • Currently supports configure only
  • Supported bug types include:
    • ASAN-detectable memory corruptions
    • Divide-by-zero (SIGFPE)
    • Null dereference (SIGSEGV)
    • Assertion failure
  • This script tests a bug by identifying the bug type and the crashing function in the ASAN dump; it does not recognize whether the bug manifests in another commit with a different bug type or at a different function.
  • Random contributions would be very much appreciated.

History

  • 16th July, 2020: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)