From a715bdffac1fc70206a543a15a3528a8e69c85ad Mon Sep 17 00:00:00 2001 From: Armin Kuster Date: Sat, 13 Feb 2016 11:55:53 -0800 Subject: xdelta3: Security fix CVE-2014-9765 CVE-2014-9765 xdelta: buffer overflow in main_get_appheader Signed-off-by: Armin Kuster --- .../xdelta/files/CVE-2014-9765.patch | 311 +++++++++++++++++++++ meta-oe/recipes-support/xdelta/xdelta3_3.0.8.bb | 1 + 2 files changed, 312 insertions(+) create mode 100644 meta-oe/recipes-support/xdelta/files/CVE-2014-9765.patch diff --git a/meta-oe/recipes-support/xdelta/files/CVE-2014-9765.patch b/meta-oe/recipes-support/xdelta/files/CVE-2014-9765.patch new file mode 100644 index 0000000000..572a3c00a6 --- /dev/null +++ b/meta-oe/recipes-support/xdelta/files/CVE-2014-9765.patch @@ -0,0 +1,311 @@ +From ef93ff74203e030073b898c05e8b4860b5d09ef2 Mon Sep 17 00:00:00 2001 +From: "josh.macdonald" +Date: Sun, 12 Oct 2014 05:24:22 +0000 +Subject: [PATCH] Add appheader tests; fix buffer overflow in + main_get_appheader + +Upstream-Status: Backport + +This appears to be fixed in xdelta3 3.0.9 and later via +https://github.com/jmacd/xdelta-devel/commit/ef93ff74203e030073b898c05e8b4860b5d09ef2 + +CVE: CVE-2014-9765 +Signed-off-by: Armin Kuster + +--- + xdelta3-main.h | 5 +- + xdelta3-test.h | 131 +++++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 108 insertions(+), 28 deletions(-) + +diff --git a/xdelta3-main.h b/xdelta3-main.h +index 090b7d9..5146b38 100644 +--- a/xdelta3-main.h ++++ b/xdelta3-main.h +@@ -2810,14 +2810,15 @@ main_get_appheader (xd3_stream *stream, main_file *ifile, + + if (appheadsz > 0) + { ++ const int kMaxArgs = 4; + char *start = (char*)apphead; + char *slash; + int place = 0; +- char *parsed[4]; ++ char *parsed[kMaxArgs]; + + memset (parsed, 0, sizeof (parsed)); + +- while ((slash = strchr (start, '/')) != NULL) ++ while ((slash = strchr (start, '/')) != NULL && place < (kMaxArgs-1)) + { + *slash = 0; + parsed[place++] = start; +diff --git a/xdelta3-test.h b/xdelta3-test.h +index e9848b6..0e10251 100644 +--- a/xdelta3-test.h ++++ b/xdelta3-test.h +@@ -1,5 +1,5 @@ + /* xdelta 3 - delta compression tools and library Copyright (C) 2001, +- * 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012. ++ * 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012. + * Joshua P. MacDonald + * + * This program is free software; you can redistribute it and/or modify +@@ -54,7 +54,7 @@ void mt_init(mtrand *mt, uint32_t seed) { + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + mt->mt_buffer_[i] = +- (1812433253UL * (mt->mt_buffer_[i-1] ^ ++ (1812433253UL * (mt->mt_buffer_[i-1] ^ + (mt->mt_buffer_[i-1] >> 30)) + i); + } + } +@@ -69,20 +69,20 @@ uint32_t mt_random (mtrand *mt) { + int kk; + + for (kk = 0; kk < MT_LEN - MT_IA; kk++) { +- y = (mt->mt_buffer_[kk] & UPPER_MASK) | ++ y = (mt->mt_buffer_[kk] & UPPER_MASK) | + (mt->mt_buffer_[kk + 1] & LOWER_MASK); +- mt->mt_buffer_[kk] = mt->mt_buffer_[kk + MT_IA] ^ ++ mt->mt_buffer_[kk] = mt->mt_buffer_[kk + MT_IA] ^ + (y >> 1) ^ mag01[y & 0x1UL]; + } + for (;kk < MT_LEN - 1; kk++) { +- y = (mt->mt_buffer_[kk] & UPPER_MASK) | ++ y = (mt->mt_buffer_[kk] & UPPER_MASK) | + (mt->mt_buffer_[kk + 1] & LOWER_MASK); +- mt->mt_buffer_[kk] = mt->mt_buffer_[kk + (MT_IA - MT_LEN)] ^ ++ mt->mt_buffer_[kk] = mt->mt_buffer_[kk + (MT_IA - MT_LEN)] ^ + (y >> 1) ^ mag01[y & 0x1UL]; + } +- y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) | ++ y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) | + (mt->mt_buffer_[0] & LOWER_MASK); +- mt->mt_buffer_[MT_LEN - 1] = mt->mt_buffer_[MT_IA - 1] ^ ++ mt->mt_buffer_[MT_LEN - 1] = mt->mt_buffer_[MT_IA - 1] ^ + (y >> 1) ^ mag01[y & 0x1UL]; + mt->mt_index_ = 0; + } +@@ -166,7 +166,7 @@ static int do_cmd (xd3_stream *stream, const char *buf) + { + stream->msg = "abnormal command termination"; + } +- return XD3_INTERNAL; ++ return ret; + } + return 0; + } +@@ -257,8 +257,10 @@ int test_setup (void) + static int + test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) + { +- usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2; +- usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2; ++ usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + ++ TEST_FILE_MEAN / 2; ++ usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + ++ TEST_FILE_MEAN / 2; + uint8_t *buf = (uint8_t*) malloc (ts + ss), *sbuf = buf, *tbuf = buf + ss; + usize_t sadd = 0, sadd_max = (usize_t)(ss * TEST_ADD_RATIO); + FILE *tf = NULL, *sf = NULL; +@@ -409,7 +411,7 @@ test_compare_files (const char* tgt, const char *rec) + { + if (obuf[i] != rbuf[i]) + { +- XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n", ++ XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n", + (int)i, (int)oc, offset, obuf[i], rbuf[i]); + diffs++; + return XD3_INTERNAL; +@@ -421,7 +423,7 @@ test_compare_files (const char* tgt, const char *rec) + + fclose (orig); + fclose (recons); +- if (diffs != 0) ++ if (diffs != 0) + { + return XD3_INTERNAL; + } +@@ -429,12 +431,12 @@ test_compare_files (const char* tgt, const char *rec) + } + + static int +-test_save_copy (const char *origname) ++test_copy_to (const char *from, const char *to) + { + char buf[TESTBUFSIZE]; + int ret; + +- snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", origname, TEST_COPY_FILE); ++ snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", from, to); + + if ((ret = system (buf)) != 0) + { +@@ -445,6 +447,12 @@ test_save_copy (const char *origname) + } + + static int ++test_save_copy (const char *origname) ++{ ++ return test_copy_to(origname, TEST_COPY_FILE); ++} ++ ++static int + test_file_size (const char* file, xoff_t *size) + { + struct stat sbuf; +@@ -499,7 +507,7 @@ test_read_integer_error (xd3_stream *stream, usize_t trunto, const char *msg) + inp = buf->base; + max = buf->base + buf->next - trunto; + +- if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) != ++ if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) != + XD3_INVALID_INPUT || + !MSG_IS (msg)) + { +@@ -1654,11 +1662,11 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore) + if ((buf = (uint8_t*) malloc (TWO_MEGS_AND_DELTA)) == NULL) { return ENOMEM; } + + memset (buf, 0, TWO_MEGS_AND_DELTA); +- for (i = 0; i < (2 << 20); i += 256) ++ for (i = 0; i < (2 << 20); i += 256) + { + int j; + int off = mt_random(& static_mtrand) % 10; +- for (j = 0; j < 256; j++) ++ for (j = 0; j < 256; j++) + { + buf[i + j] = j + off; + } +@@ -1683,11 +1691,11 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore) + } + + /* Test transfer of exactly 32bits worth of data. */ +- if ((ret = test_streaming (stream, +- buf, +- buf + (1 << 20), +- buf + (2 << 20), +- 1 << 12))) ++ if ((ret = test_streaming (stream, ++ buf, ++ buf + (1 << 20), ++ buf + (2 << 20), ++ 1 << 12))) + { + goto fail; + } +@@ -1889,7 +1897,7 @@ test_recode_command2 (xd3_stream *stream, int has_source, + } + + /* First encode */ +- snprintf_func (ecmd, TESTBUFSIZE, "%s %s -f %s %s %s %s %s %s %s", ++ snprintf_func (ecmd, TESTBUFSIZE, "%s %s -f %s %s %s %s %s %s %s", + program_name, test_softcfg_str, + has_adler32 ? "" : "-n ", + has_apphead ? "-A=encode_apphead " : "-A= ", +@@ -1910,7 +1918,7 @@ test_recode_command2 (xd3_stream *stream, int has_source, + snprintf_func (recmd, TESTBUFSIZE, + "%s recode %s -f %s %s %s %s %s", program_name, test_softcfg_str, + recoded_adler32 ? "" : "-n ", +- !change_apphead ? "" : ++ !change_apphead ? "" : + (recoded_apphead ? "-A=recode_apphead " : "-A= "), + recoded_secondary ? "-S djw " : "-S none ", + TEST_DELTA_FILE, +@@ -2361,6 +2369,76 @@ test_no_output (xd3_stream *stream, int ignore) + return 0; + } + ++/* This tests that the default appheader works */ ++static int ++test_appheader (xd3_stream *stream, int ignore) ++{ ++ int i; ++ int ret; ++ char buf[TESTBUFSIZE]; ++ char bogus[TESTBUFSIZE]; ++ xoff_t ssize, tsize; ++ test_setup (); ++ ++ if ((ret = test_make_inputs (stream, &ssize, &tsize))) { return ret; } ++ ++ snprintf_func (buf, TESTBUFSIZE, "%s -q -f -e -s %s %s %s", program_name, ++ TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE); ++ if ((ret = do_cmd (stream, buf))) { return ret; } ++ ++ if ((ret = test_copy_to (program_name, TEST_RECON2_FILE))) { return ret; } ++ ++ snprintf_func (buf, TESTBUFSIZE, "chmod 0700 %s", TEST_RECON2_FILE); ++ if ((ret = do_cmd (stream, buf))) { return ret; } ++ ++ if ((ret = test_save_copy (TEST_TARGET_FILE))) { return ret; } ++ if ((ret = test_copy_to (TEST_SOURCE_FILE, TEST_TARGET_FILE))) { return ret; } ++ ++ if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_COPY_FILE)) == 0) ++ { ++ return XD3_INVALID; // I.e., files are different! ++ } ++ ++ // Test that the target file is restored. ++ snprintf_func (buf, TESTBUFSIZE, "(cd /tmp && %s -q -f -d %s)", ++ TEST_RECON2_FILE, ++ TEST_DELTA_FILE); ++ if ((ret = do_cmd (stream, buf))) { return ret; } ++ ++ if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_COPY_FILE)) != 0) ++ { ++ return ret; ++ } ++ ++ // Test a malicious string w/ entries > 4 in the appheader by having ++ // the encoder write it: ++ for (i = 0; i < TESTBUFSIZE / 4; ++i) ++ { ++ bogus[2*i] = 'G'; ++ bogus[2*i+1] = '/'; ++ } ++ bogus[TESTBUFSIZE/2-1] = 0; ++ ++ snprintf_func (buf, TESTBUFSIZE, ++ "%s -q -f -A=%s -e -s %s %s %s", program_name, bogus, ++ TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE); ++ if ((ret = do_cmd (stream, buf))) { return ret; } ++ // Then read it: ++ snprintf_func (buf, TESTBUFSIZE, "(cd /tmp && %s -q -f -d %s)", ++ TEST_RECON2_FILE, ++ TEST_DELTA_FILE); ++ if ((ret = do_cmd (stream, buf)) == 0) ++ { ++ return XD3_INVALID; // Impossible ++ } ++ if (!WIFEXITED(ret)) ++ { ++ return XD3_INVALID; // Must have crashed! ++ } ++ ++ return 0; ++} ++ + /*********************************************************************** + Source identical optimization + ***********************************************************************/ +@@ -2603,7 +2681,7 @@ test_string_matching (xd3_stream *stream, int ignore) + default: CHECK(0); + } + +- snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d", ++ snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d", + inst->pos, inst->size); + rptr += strlen (rptr); + +@@ -2848,6 +2926,7 @@ xd3_selftest (void) + DO_TEST (force_behavior, 0, 0); + DO_TEST (stdout_behavior, 0, 0); + DO_TEST (no_output, 0, 0); ++ DO_TEST (appheader, 0, 0); + DO_TEST (command_line_arguments, 0, 0); + + #if EXTERNAL_COMPRESSION +-- +2.3.5 + diff --git a/meta-oe/recipes-support/xdelta/xdelta3_3.0.8.bb b/meta-oe/recipes-support/xdelta/xdelta3_3.0.8.bb index baa92e4bb2..2ddf78a0f4 100644 --- a/meta-oe/recipes-support/xdelta/xdelta3_3.0.8.bb +++ b/meta-oe/recipes-support/xdelta/xdelta3_3.0.8.bb @@ -10,6 +10,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=393a5ca445f6965873eca0259a17f833" SRC_URI = "http://xdelta.googlecode.com/files/${BPN}-${PV}.tar.xz \ file://compilation-fix.patch \ file://with-liblzma-configure-option.patch \ + file://CVE-2014-9765.patch \ " SRC_URI[md5sum] = "c3ae3286ce4193de8e03d5bcaccf3bc3" SRC_URI[sha256sum] = "3a86f29c95664fb44b8a40ff22d9bcc3e87aa8c01f0ff75931a7fa78ed3d2e55" -- cgit 1.2.3-korg