1. 05 Oct, 2018 3 commits
  2. 03 Oct, 2018 12 commits
    • smart_pkt: do not accept callers passing in no line length · 21a2318b
      Right now, we simply ignore the `linelen` parameter of
      `git_pkt_parse_line` in case the caller passed in zero. But in fact, we
      never want to assume anything about the provided buffer length and
      always want the caller to pass in the available number of bytes.
      And in fact, checking all the callers, one can see that the funciton is
      never being called in case where the buffer length is zero, and thus we
      are safe to remove this check.
      
      (cherry picked from commit 1bc5b05c)
      Patrick Steinhardt committed
    • smart_pkt: return parsed length via out-parameter · 5836d8b6
      The `parse_len` function currently directly returns the parsed length of
      a packet line or an error code in case there was an error. Instead,
      convert this to our usual style of using the return value as error code
      only and returning the actual value via an out-parameter. Thus, we can
      now convert the output parameter to an unsigned type, as the size of a
      packet cannot ever be negative.
      
      While at it, we also move the check whether the input buffer is long
      enough into `parse_len` itself. We don't really want to pass around
      potentially non-NUL-terminated buffers to functions without also passing
      along the length, as this is dangerous in the unlikely case where other
      callers for that function get added. Note that we need to make sure
      though to not mess with `GIT_EBUFS` error codes, as these indicate not
      an error to the caller but that he needs to fetch more data.
      
      (cherry picked from commit c05790a8)
      Patrick Steinhardt committed
    • smart_pkt: reorder and rename parameters of `git_pkt_parse_line` · 3bbda7d7
      The parameters of the `git_pkt_parse_line` function are quite confusing.
      First, there is no real indicator what the `out` parameter is actually
      all about, and it's not really clear what the `bufflen` parameter refers
      to. Reorder and rename the parameters to make this more obvious.
      
      (cherry picked from commit 0b3dfbf4)
      Patrick Steinhardt committed
    • smart_pkt: fix buffer overflow when parsing "unpack" packets · a8356af8
      When checking whether an "unpack" packet returned the "ok" status or
      not, we use a call to `git__prefixcmp`. In case where the passed line
      isn't properly NUL terminated, though, this may overrun the line buffer.
      Fix this by using `git__prefixncmp` instead.
      
      (cherry picked from commit 5fabaca8)
      Patrick Steinhardt committed
    • smart_pkt: fix "ng" parser accepting non-space character · 02e4b27f
      When parsing "ng" packets, we blindly assume that the character
      immediately following the "ng" prefix is a space and skip it. As the
      calling function doesn't make sure that this is the case, we can thus
      end up blindly accepting an invalid packet line.
      
      Fix the issue by using `git__prefixncmp`, checking whether the line
      starts with "ng ".
      
      (cherry picked from commit b5ba7af2)
      Patrick Steinhardt committed
    • smart_pkt: fix buffer overflow when parsing "ok" packets · 8cd0a897
      There are two different buffer overflows present when parsing "ok"
      packets. First, we never verify whether the line already ends after
      "ok", but directly go ahead and also try to skip the expected space
      after "ok". Second, we then go ahead and use `strchr` to scan for the
      terminating newline character. But in case where the line isn't
      terminated correctly, this can overflow the line buffer.
      
      Fix the issues by using `git__prefixncmp` to check for the "ok " prefix
      and only checking for a trailing '\n' instead of using `memchr`. This
      also fixes the issue of us always requiring a trailing '\n'.
      
      Reported by oss-fuzz, issue 9749:
      
      Crash Type: Heap-buffer-overflow READ {*}
      Crash Address: 0x6310000389c0
      Crash State:
        ok_pkt
        git_pkt_parse_line
        git_smart__store_refs
      
      Sanitizer: address (ASAN)
      (cherry picked from commit a9f1ca09)
      Patrick Steinhardt committed
    • smart_pkt: fix buffer overflow when parsing "ACK" packets · 82c3fc33
      We are being quite lenient when parsing "ACK" packets. First, we didn't
      correctly verify that we're not overrunning the provided buffer length,
      which we fix here by using `git__prefixncmp` instead of
      `git__prefixcmp`. Second, we do not verify that the actual contents make
      any sense at all, as we simply ignore errors when parsing the ACKs OID
      and any unknown status strings. This may result in a parsed packet
      structure with invalid contents, which is being silently passed to the
      caller. This is being fixed by performing proper input validation and
      checking of return codes.
      
      (cherry picked from commit bc349045)
      Patrick Steinhardt committed
    • smart_pkt: adjust style of "ref" packet parsing function · 3fd6ce0d
      While the function parsing ref packets doesn't have any immediately
      obvious buffer overflows, it's style is different to all the other
      parsing functions. Instead of checking buffer length while we go, it
      does a check up-front. This causes the code to seem a lot more magical
      than it really is due to some magic constants. Refactor the function to
      instead make use of the style of other packet parser and verify buffer
      lengths as we go.
      
      (cherry picked from commit 5edcf5d1)
      Patrick Steinhardt committed
    • smart_pkt: check whether error packets are prefixed with "ERR " · e14dab2f
      In the `git_pkt_parse_line` function, we determine what kind of packet
      a given packet line contains by simply checking for the prefix of that
      line. Except for "ERR" packets, we always only check for the immediate
      identifier without the trailing space (e.g. we check for an "ACK"
      prefix, not for "ACK "). But for "ERR" packets, we do in fact include
      the trailing space in our check. This is not really much of a problem at
      all, but it is inconsistent with all the other packet types and thus
      causes confusion when the `err_pkt` function just immediately skips the
      space without checking whether it overflows the line buffer.
      
      Adjust the check in `git_pkt_parse_line` to not include the trailing
      space and instead move it into `err_pkt` for consistency.
      
      (cherry picked from commit 786426ea)
      Patrick Steinhardt committed
    • smart_pkt: explicitly avoid integer overflows when parsing packets · cfb9802b
      When parsing data, progress or error packets, we need to copy the
      contents of the rest of the current packet line into the flex-array of
      the parsed packet. To keep track of this array's length, we then assign
      the remaining length of the packet line to the structure. We do have a
      mismatch of types here, as the structure's `len` field is a signed
      integer, while the length that we are assigning has type `size_t`.
      
      On nearly all platforms, this shouldn't pose any problems at all. The
      line length can at most be 16^4, as the line's length is being encoded
      by exactly four hex digits. But on a platforms with 16 bit integers,
      this assignment could cause an overflow. While such platforms will
      probably only exist in the embedded ecosystem, we still want to avoid
      this potential overflow. Thus, we now simply change the structure's
      `len` member to be of type `size_t` to avoid any integer promotion.
      
      (cherry picked from commit 40fd84cc)
      Patrick Steinhardt committed
    • smart_pkt: honor line length when determining packet type · a7e87dd5
      When we parse the packet type of an incoming packet line, we do not
      verify that we don't overflow the provided line buffer. Fix this by
      using `git__prefixncmp` instead and passing in `len`. As we have
      previously already verified that `len <= linelen`, we thus won't ever
      overflow the provided buffer length.
      
      (cherry picked from commit 4a5804c9)
      Patrick Steinhardt committed
    • tests: verify parsing logic for smart packets · 5d108c9a
      The commits following this commit are about to introduce quite a lot of
      refactoring and tightening of the smart packet parser. Unfortunately, we
      do not yet have any tests despite our online tests that verify that our
      parser does not regress upon changes. This is doubly unfortunate as our
      online tests aren't executed by default.
      
      Add new tests that exercise the smart parsing logic directly by
      executing `git_pkt_parse_line`.
      
      (cherry picked from commit 365d2720)
      Patrick Steinhardt committed
  3. 01 Oct, 2018 10 commits
  4. 06 Aug, 2018 5 commits
    • Merge pull request #4757 from pks-t/pks/v0.26.6 · e98d0a37
      Release v0.26.6
      Patrick Steinhardt committed
    • smart_pkt: fix potential OOB-read when processing ng packet · 50705a2a
      OSS-fuzz has reported a potential out-of-bounds read when processing a
      "ng" smart packet:
      
      ==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6310000249c0 at pc 0x000000493a92 bp 0x7ffddc882cd0 sp 0x7ffddc882480
      	READ of size 65529 at 0x6310000249c0 thread T0
      	SCARINESS: 26 (multi-byte-read-heap-buffer-overflow)
      	#0 0x493a91 in __interceptor_strchr.part.35 /src/llvm/projects/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc:673
      	#1 0x813960 in ng_pkt libgit2/src/transports/smart_pkt.c:320:14
      	#2 0x810f79 in git_pkt_parse_line libgit2/src/transports/smart_pkt.c:478:9
      	#3 0x82c3c9 in git_smart__store_refs libgit2/src/transports/smart_protocol.c:47:12
      	#4 0x6373a2 in git_smart__connect libgit2/src/transports/smart.c:251:15
      	#5 0x57688f in git_remote_connect libgit2/src/remote.c:708:15
      	#6 0x52e59b in LLVMFuzzerTestOneInput /src/download_refs_fuzzer.cc:145:9
      	#7 0x52ef3f in ExecuteFilesOnyByOne(int, char**) /src/libfuzzer/afl/afl_driver.cpp:301:5
      	#8 0x52f4ee in main /src/libfuzzer/afl/afl_driver.cpp:339:12
      	#9 0x7f6c910db82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/libc-start.c:291
      	#10 0x41d518 in _start
      
      When parsing an "ng" packet, we keep track of both the current position
      as well as the remaining length of the packet itself. But instead of
      taking care not to exceed the length, we pass the current pointer's
      position to `strchr`, which will search for a certain character until
      hitting NUL. It is thus possible to create a crafted packet which
      doesn't contain a NUL byte to trigger an out-of-bounds read.
      
      Fix the issue by instead using `memchr`, passing the remaining length as
      restriction. Furthermore, verify that we actually have enough bytes left
      to produce a match at all.
      
      OSS-Fuzz-Issue: 9406
      Patrick Steinhardt committed
    • travis: force usage of Xcode 8.3 image · 7e12ca68
      Travis has upgraded the default Xcode images from 8.3 to 9.4 on 31st
      July 2018, including an upgrade to macOS 10.13. Unfortunately, this
      breaks our CI builds on our maintenance branches. As we do not want to
      include mayor changes to fix the integration right now, we force use of
      the old Xcode 8.3 images.
      Patrick Steinhardt committed
  5. 09 Jul, 2018 1 commit
  6. 05 Jul, 2018 5 commits
    • delta: fix overflow when computing limit · 47ea1f58
      When checking whether a delta base offset and length fit into the base
      we have in memory already, we can trigger an overflow which breaks the
      check. This would subsequently result in us reading memory from out of
      bounds of the base.
      
      The issue is easily fixed by checking for overflow when adding `off` and
      `len`, thus guaranteeting that we are never indexing beyond `base_len`.
      This corresponds to the git patch 8960844a7 (check patch_delta bounds
      more carefully, 2006-04-07), which adds these overflow checks.
      
      Reported-by: Riccardo Schirone <rschiron@redhat.com>
      Patrick Steinhardt committed
    • delta: fix out-of-bounds read of delta · 25d4a8c9
      When computing the offset and length of the delta base, we repeatedly
      increment the `delta` pointer without checking whether we have advanced
      past its end already, which can thus result in an out-of-bounds read.
      Fix this by repeatedly checking whether we have reached the end. Add a
      test which would cause Valgrind to produce an error.
      
      Reported-by: Riccardo Schirone <rschiron@redhat.com>
      Test-provided-by: Riccardo Schirone <rschiron@redhat.com>
      Patrick Steinhardt committed
    • delta: fix sign-extension of big left-shift · 8ab4f363
      Our delta code was originally adapted from JGit, which itself adapted it
      from git itself. Due to this heritage, we inherited a bug from git.git
      in how we compute the delta offset, which was fixed upstream in
      48fb7deb5 (Fix big left-shifts of unsigned char, 2009-06-17). As
      explained by Linus:
      
          Shifting 'unsigned char' or 'unsigned short' left can result in sign
          extension errors, since the C integer promotion rules means that the
          unsigned char/short will get implicitly promoted to a signed 'int' due to
          the shift (or due to other operations).
      
          This normally doesn't matter, but if you shift things up sufficiently, it
          will now set the sign bit in 'int', and a subsequent cast to a bigger type
          (eg 'long' or 'unsigned long') will now sign-extend the value despite the
          original expression being unsigned.
      
          One example of this would be something like
      
                  unsigned long size;
                  unsigned char c;
      
                  size += c << 24;
      
          where despite all the variables being unsigned, 'c << 24' ends up being a
          signed entity, and will get sign-extended when then doing the addition in
          an 'unsigned long' type.
      
          Since git uses 'unsigned char' pointers extensively, we actually have this
          bug in a couple of places.
      
      In our delta code, we inherited such a bogus shift when computing the
      offset at which the delta base is to be found. Due to the sign extension
      we can end up with an offset where all the bits are set. This can allow
      an arbitrary memory read, as the addition in `base_len < off + len` can
      now overflow if `off` has all its bits set.
      
      Fix the issue by casting the result of `*delta++ << 24UL` to an unsigned
      integer again. Add a test with a crafted delta that would actually
      succeed with an out-of-bounds read in case where the cast wouldn't
      exist.
      
      Reported-by: Riccardo Schirone <rschiron@redhat.com>
      Test-provided-by: Riccardo Schirone <rschiron@redhat.com>
      Patrick Steinhardt committed
  7. 04 Jun, 2018 1 commit
  8. 01 Jun, 2018 3 commits