From 7f8f8a43cae54b88ca06ba3674a79204ee698a54 Mon Sep 17 00:00:00 2001 From: mm Date: Wed, 12 Oct 2016 10:28:22 +0000 Subject: MFC r306670: Sync libarchive with vendor including security fixes. Important vendor bugfixes (relevant to FreeBSD): #747: Out of bounds read in mtree parser #761: heap-based buffer overflow in read_Header (7-zip) #794: Invalid file on bsdtar command line results in internal errors (1) PR: 213092 (1) --- contrib/libarchive/tar/subst.c | 1 + contrib/libarchive/tar/test/main.c | 46 ++++++++++++++++++++++- contrib/libarchive/tar/test/test.h | 4 ++ contrib/libarchive/tar/test/test_option_H_upper.c | 4 +- contrib/libarchive/tar/test/test_option_L_upper.c | 12 +++--- contrib/libarchive/tar/test/test_option_U_upper.c | 4 +- contrib/libarchive/tar/test/test_option_n.c | 2 +- contrib/libarchive/tar/write.c | 2 + 8 files changed, 62 insertions(+), 13 deletions(-) (limited to 'contrib/libarchive/tar') diff --git a/contrib/libarchive/tar/subst.c b/contrib/libarchive/tar/subst.c index 37905dc..48370b2 100644 --- a/contrib/libarchive/tar/subst.c +++ b/contrib/libarchive/tar/subst.c @@ -84,6 +84,7 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) if (rule == NULL) lafe_errc(1, errno, "Out of memory"); rule->next = NULL; + rule->result = NULL; if (subst->last_rule == NULL) subst->first_rule = rule; diff --git a/contrib/libarchive/tar/test/main.c b/contrib/libarchive/tar/test/main.c index 6ebe10e..8bf1d36 100644 --- a/contrib/libarchive/tar/test/main.c +++ b/contrib/libarchive/tar/test/main.c @@ -130,6 +130,13 @@ __FBSDID("$FreeBSD$"); # include #endif +mode_t umasked(mode_t expected_mode) +{ + mode_t mode = umask(0); + umask(mode); + return expected_mode & ~mode; +} + /* Path to working directory for current test */ const char *testworkdir; #ifdef PROGRAM @@ -1361,6 +1368,31 @@ assertion_file_birthtime_recent(const char *file, int line, return assertion_file_time(file, line, pathname, 0, 0, 'b', 1); } +/* Verify mode of 'pathname'. */ +int +assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode) +{ + int mode; + int r; + + assertion_count(file, line); +#if defined(_WIN32) && !defined(__CYGWIN__) + failure_start(file, line, "assertFileMode not yet implemented for Windows"); +#else + { + struct stat st; + r = lstat(pathname, &st); + mode = (int)(st.st_mode & 0777); + } + if (r == 0 && mode == expected_mode) + return (1); + failure_start(file, line, "File %s has mode %o, expected %o", + pathname, mode, expected_mode); +#endif + failure_finish(NULL); + return (0); +} + /* Verify mtime of 'pathname'. */ int assertion_file_mtime(const char *file, int line, @@ -1579,8 +1611,12 @@ assertion_make_dir(const char *file, int line, const char *dirname, int mode) if (0 == _mkdir(dirname)) return (1); #else - if (0 == mkdir(dirname, mode)) - return (1); + if (0 == mkdir(dirname, mode)) { + if (0 == chmod(dirname, mode)) { + assertion_file_mode(file, line, dirname, mode); + return (1); + } + } #endif failure_start(file, line, "Could not create directory %s", dirname); failure_finish(NULL); @@ -1629,6 +1665,11 @@ assertion_make_file(const char *file, int line, failure_finish(NULL); return (0); } + if (0 != chmod(path, mode)) { + failure_start(file, line, "Could not chmod %s", path); + failure_finish(NULL); + return (0); + } if (contents != NULL) { ssize_t wsize; @@ -1645,6 +1686,7 @@ assertion_make_file(const char *file, int line, } } close(fd); + assertion_file_mode(file, line, path, mode); return (1); #endif } diff --git a/contrib/libarchive/tar/test/test.h b/contrib/libarchive/tar/test/test.h index c5d2363..340eadc 100644 --- a/contrib/libarchive/tar/test/test.h +++ b/contrib/libarchive/tar/test/test.h @@ -241,6 +241,7 @@ int assertion_file_birthtime_recent(const char *, int, const char *); int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **); int assertion_file_contents(const char *, int, const void *, int, const char *); int assertion_file_exists(const char *, int, const char *); +int assertion_file_mode(const char *, int, const char *, int); int assertion_file_mtime(const char *, int, const char *, long, long); int assertion_file_mtime_recent(const char *, int, const char *); int assertion_file_nlinks(const char *, int, const char *, int); @@ -326,6 +327,9 @@ void copy_reference_file(const char *); */ void extract_reference_files(const char **); +/* Subtract umask from mode */ +mode_t umasked(mode_t expected_mode); + /* Path to working directory for current test */ extern const char *testworkdir; diff --git a/contrib/libarchive/tar/test/test_option_H_upper.c b/contrib/libarchive/tar/test/test_option_H_upper.c index 7ddd917..adc294b 100644 --- a/contrib/libarchive/tar/test/test_option_H_upper.c +++ b/contrib/libarchive/tar/test/test_option_H_upper.c @@ -83,10 +83,10 @@ DEFINE_TEST(test_option_H_upper) assertChdir("test3"); assertEqualInt(0, systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); - assertIsDir("ld1", 0755); + assertIsDir("ld1", umasked(0755)); assertIsSymlink("d1/linkX", "fileX"); assertIsSymlink("d1/link1", "file1"); - assertIsReg("link2", 0644); + assertIsReg("link2", umasked(0644)); assertIsSymlink("linkY", "d1/fileY"); assertChdir(".."); } diff --git a/contrib/libarchive/tar/test/test_option_L_upper.c b/contrib/libarchive/tar/test/test_option_L_upper.c index 57abe41..f5a3c5a 100644 --- a/contrib/libarchive/tar/test/test_option_L_upper.c +++ b/contrib/libarchive/tar/test/test_option_L_upper.c @@ -69,10 +69,10 @@ DEFINE_TEST(test_option_L_upper) assertChdir("test2"); assertEqualInt(0, systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); - assertIsDir("ld1", 0755); - assertIsReg("d1/link1", 0644); + assertIsDir("ld1", umasked(0755)); + assertIsReg("d1/link1", umasked(0644)); assertIsSymlink("d1/linkX", "fileX"); - assertIsReg("link2", 0644); + assertIsReg("link2", umasked(0644)); assertIsSymlink("linkY", "d1/fileY"); assertChdir(".."); @@ -83,10 +83,10 @@ DEFINE_TEST(test_option_L_upper) assertChdir("test3"); assertEqualInt(0, systemf("%s -xf archive.tar >c.out 2>c.err", testprog)); - assertIsDir("ld1", 0755); - assertIsReg("d1/link1", 0644); + assertIsDir("ld1", umasked(0755)); + assertIsReg("d1/link1", umasked(0644)); assertIsSymlink("d1/linkX", "fileX"); - assertIsReg("link2", 0644); + assertIsReg("link2", umasked(0644)); assertIsSymlink("linkY", "d1/fileY"); assertChdir(".."); } diff --git a/contrib/libarchive/tar/test/test_option_U_upper.c b/contrib/libarchive/tar/test/test_option_U_upper.c index 4d77cb0..2c43e00 100644 --- a/contrib/libarchive/tar/test/test_option_U_upper.c +++ b/contrib/libarchive/tar/test/test_option_U_upper.c @@ -135,7 +135,7 @@ DEFINE_TEST(test_option_U_upper) assertMakeSymlink("d1/file1", "d1/realfile1"); assertEqualInt(0, systemf("%s -xf ../archive.tar d1/file1 >test.out 2>test.err", testprog)); - assertIsReg("d1/file1", 0644); + assertIsReg("d1/file1", umasked(0644)); assertFileContents("d1/file1", 8, "d1/file1"); assertFileContents("realfile1", 9, "d1/realfile1"); assertEmptyFile("test.out"); @@ -150,7 +150,7 @@ DEFINE_TEST(test_option_U_upper) assertMakeSymlink("d1/file1", "d1/realfile1"); assertEqualInt(0, systemf("%s -xPUf ../archive.tar d1/file1 >test.out 2>test.err", testprog)); - assertIsReg("d1/file1", 0644); + assertIsReg("d1/file1", umasked(0644)); assertFileContents("d1/file1", 8, "d1/file1"); assertFileContents("realfile1", 9, "d1/realfile1"); assertEmptyFile("test.out"); diff --git a/contrib/libarchive/tar/test/test_option_n.c b/contrib/libarchive/tar/test/test_option_n.c index 4017dd9..18ab614 100644 --- a/contrib/libarchive/tar/test/test_option_n.c +++ b/contrib/libarchive/tar/test/test_option_n.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_option_n) systemf("%s -xf archive.tar >x.out 2>x.err", testprog)); assertEmptyFile("x.out"); assertEmptyFile("x.err"); - assertIsDir("d1", 0755); + assertIsDir("d1", umasked(0755)); assertFileNotExists("d1/file1"); assertChdir(".."); } diff --git a/contrib/libarchive/tar/write.c b/contrib/libarchive/tar/write.c index 30fb224..18193de 100644 --- a/contrib/libarchive/tar/write.c +++ b/contrib/libarchive/tar/write.c @@ -886,6 +886,8 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) "%s", archive_error_string(disk)); if (r == ARCHIVE_FATAL || r == ARCHIVE_FAILED) { bsdtar->return_value = 1; + archive_entry_free(entry); + archive_read_close(disk); return; } else if (r < ARCHIVE_WARN) continue; -- cgit v1.1