Skip to content

Commit 504bd54

Browse files
authored
Merge pull request #4717 from pks-t/pks/v0.27.3
Release v0.27.3
2 parents 8d36dc6 + 8fbd756 commit 504bd54

5 files changed

Lines changed: 77 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
v0.27.3
2+
-------
3+
4+
This is a security release fixing out-of-bounds reads when
5+
reading objects from a packfile. This corresponds to
6+
CVE-2018-10887 and CVE-2018-10888, which were both reported by
7+
Riccardo Schirone.
8+
9+
When packing objects into a single so-called packfile, objects
10+
may not get stored as complete copies but instead as deltas
11+
against another object "base". A specially crafted delta object
12+
could trigger an integer overflow and thus bypass our input
13+
validation, which may result in copying memory before or after
14+
the base object into the final deflated object. This may lead to
15+
objects containing copies of system memory being written into the
16+
object database. As the hash of those objects cannot be easily
17+
controlled by the attacker, it is unlikely that any of those
18+
objects will be valid and referenced by the commit graph.
19+
20+
Note that the error could also be triggered by the function
21+
`git_apply__patch`. But as this function is not in use outside of
22+
our test suite, it is not a possible attack vector.
23+
124
v0.27.2
225
---------
326

include/git2/version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
#ifndef INCLUDE_git_version_h__
88
#define INCLUDE_git_version_h__
99

10-
#define LIBGIT2_VERSION "0.27.2"
10+
#define LIBGIT2_VERSION "0.27.3"
1111
#define LIBGIT2_VER_MAJOR 0
1212
#define LIBGIT2_VER_MINOR 27
13-
#define LIBGIT2_VER_REVISION 2
13+
#define LIBGIT2_VER_REVISION 3
1414
#define LIBGIT2_VER_PATCH 0
1515

1616
#define LIBGIT2_SOVERSION 27

src/delta.c

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -539,10 +539,11 @@ int git_delta_apply(
539539
*out = NULL;
540540
*out_len = 0;
541541

542-
/* Check that the base size matches the data we were given;
543-
* if not we would underflow while accessing data from the
544-
* base object, resulting in data corruption or segfault.
545-
*/
542+
/*
543+
* Check that the base size matches the data we were given;
544+
* if not we would underflow while accessing data from the
545+
* base object, resulting in data corruption or segfault.
546+
*/
546547
if ((hdr_sz(&base_sz, &delta, delta_end) < 0) || (base_sz != base_len)) {
547548
giterr_set(GITERR_INVALID, "failed to apply delta: base size does not match given data");
548549
return -1;
@@ -564,42 +565,43 @@ int git_delta_apply(
564565
while (delta < delta_end) {
565566
unsigned char cmd = *delta++;
566567
if (cmd & 0x80) {
567-
/* cmd is a copy instruction; copy from the base.
568-
*/
569-
size_t off = 0, len = 0;
570-
571-
if (cmd & 0x01) off = *delta++;
572-
if (cmd & 0x02) off |= *delta++ << 8UL;
573-
if (cmd & 0x04) off |= *delta++ << 16UL;
574-
if (cmd & 0x08) off |= *delta++ << 24UL;
575-
576-
if (cmd & 0x10) len = *delta++;
577-
if (cmd & 0x20) len |= *delta++ << 8UL;
578-
if (cmd & 0x40) len |= *delta++ << 16UL;
579-
if (!len) len = 0x10000;
580-
581-
if (base_len < off + len || res_sz < len)
568+
/* cmd is a copy instruction; copy from the base. */
569+
size_t off = 0, len = 0, end;
570+
571+
#define ADD_DELTA(o, shift) { if (delta < delta_end) (o) |= ((unsigned) *delta++ << shift); else goto fail; }
572+
if (cmd & 0x01) ADD_DELTA(off, 0UL);
573+
if (cmd & 0x02) ADD_DELTA(off, 8UL);
574+
if (cmd & 0x04) ADD_DELTA(off, 16UL);
575+
if (cmd & 0x08) ADD_DELTA(off, 24UL);
576+
577+
if (cmd & 0x10) ADD_DELTA(len, 0UL);
578+
if (cmd & 0x20) ADD_DELTA(len, 8UL);
579+
if (cmd & 0x40) ADD_DELTA(len, 16UL);
580+
if (!len) len = 0x10000;
581+
#undef ADD_DELTA
582+
583+
if (GIT_ADD_SIZET_OVERFLOW(&end, off, len) ||
584+
base_len < end || res_sz < len)
582585
goto fail;
586+
583587
memcpy(res_dp, base + off, len);
584588
res_dp += len;
585589
res_sz -= len;
586590

587-
}
588-
else if (cmd) {
589-
/* cmd is a literal insert instruction; copy from
590-
* the delta stream itself.
591-
*/
591+
} else if (cmd) {
592+
/*
593+
* cmd is a literal insert instruction; copy from
594+
* the delta stream itself.
595+
*/
592596
if (delta_end - delta < cmd || res_sz < cmd)
593597
goto fail;
594598
memcpy(res_dp, delta, cmd);
595599
delta += cmd;
596600
res_dp += cmd;
597601
res_sz -= cmd;
598602

599-
}
600-
else {
601-
/* cmd == 0 is reserved for future encodings.
602-
*/
603+
} else {
604+
/* cmd == 0 is reserved for future encodings. */
603605
goto fail;
604606
}
605607
}

tests/delta/apply.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "clar_libgit2.h"
2+
3+
#include "delta.h"
4+
5+
void test_delta_apply__read_at_off(void)
6+
{
7+
unsigned char base[16] = { 0 }, delta[] = { 0x10, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00 };
8+
void *out;
9+
size_t outlen;
10+
11+
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
12+
}
13+
14+
void test_delta_apply__read_after_limit(void)
15+
{
16+
unsigned char base[16] = { 0 }, delta[] = { 0x10, 0x70, 0xff };
17+
void *out;
18+
size_t outlen;
19+
20+
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
21+
}

tests/diff/binary.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "git2/sys/diff.h"
44

55
#include "buffer.h"
6+
#include "delta.h"
67
#include "filebuf.h"
78
#include "repository.h"
89

0 commit comments

Comments
 (0)