fix CVE-2021-36976,CVE-2021-31566,fix fuzz test

This commit is contained in:
wangkerong 2022-04-09 09:46:01 +08:00
parent e87663e75d
commit 20594b8750
4 changed files with 302 additions and 1 deletions

View File

@ -0,0 +1,212 @@
From ede459d2ebb879f5eedb6f7abea203be0b334230 Mon Sep 17 00:00:00 2001
From: Martin Matuska <martin@matuska.org>
Date: Wed, 17 Nov 2021 21:06:00 +0100
Subject: [PATCH] archive_write_disk_posix: fix writing fflags broken in
8a1bd5c
The fixup list was erroneously assumed to be directories only.
Only in the case of critical file flags modification (e.g. SF_IMMUTABLE
on BSD systems), other file types (e.g. regular files or symbolic links)
may be added to the fixup list. We still need to verify that we are writing
to the correct file type, so compare the archive entry file type with
the file type of the file to be modified.
Fixes #1617
Conflict:NA
Reference:https://github.com/libarchive/libarchive/commit/ede459d2ebb879f5eedb6f7abea203be0b334230
说明:这是CVE-2021-31556的后置补丁CVE-2021-31556虽然已在基线tar包修复但我们仍然建议合入该补丁并且以该CVE号来命名
---
libarchive/archive_write_disk_posix.c | 87 +++++++++++++++++++++++----
1 file changed, 75 insertions(+), 12 deletions(-)
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index aadc58718..7e57aac2e 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -173,6 +173,7 @@ struct fixup_entry {
struct fixup_entry *next;
struct archive_acl acl;
mode_t mode;
+ __LA_MODE_T filetype;
int64_t atime;
int64_t birthtime;
int64_t mtime;
@@ -357,6 +358,7 @@ struct archive_write_disk {
static int la_opendirat(int, const char *);
static int la_mktemp(struct archive_write_disk *);
+static int la_verify_filetype(mode_t, __LA_MODE_T);
static void fsobj_error(int *, struct archive_string *, int, const char *,
const char *);
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
@@ -464,6 +466,39 @@ la_opendirat(int fd, const char *path) {
#endif
}
+static int
+la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
+ int ret = 0;
+
+ switch (filetype) {
+ case AE_IFREG:
+ ret = (S_ISREG(mode));
+ break;
+ case AE_IFDIR:
+ ret = (S_ISDIR(mode));
+ break;
+ case AE_IFLNK:
+ ret = (S_ISLNK(mode));
+ break;
+ case AE_IFSOCK:
+ ret = (S_ISSOCK(mode));
+ break;
+ case AE_IFCHR:
+ ret = (S_ISCHR(mode));
+ break;
+ case AE_IFBLK:
+ ret = (S_ISBLK(mode));
+ break;
+ case AE_IFIFO:
+ ret = (S_ISFIFO(mode));
+ break;
+ default:
+ break;
+ }
+
+ return (ret);
+}
+
static int
lazy_stat(struct archive_write_disk *a)
{
@@ -822,6 +857,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->fixup |= TODO_MODE_BASE;
fe->mode = a->mode;
}
@@ -832,6 +868,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->mode = a->mode;
fe->fixup |= TODO_TIMES;
if (archive_entry_atime_is_set(entry)) {
@@ -865,6 +902,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->fixup |= TODO_ACLS;
archive_acl_copy(&fe->acl, archive_entry_acl(entry));
}
@@ -877,6 +915,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->mac_metadata = malloc(metadata_size);
if (fe->mac_metadata != NULL) {
memcpy(fe->mac_metadata, metadata,
@@ -891,6 +930,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->fixup |= TODO_FFLAGS;
/* TODO: Complete this.. defer fflags from below. */
}
@@ -2463,7 +2503,7 @@ _archive_write_disk_close(struct archive *_a)
struct fixup_entry *next, *p;
struct stat st;
char *c;
- int fd, ret;
+ int fd, ret, openflags;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
@@ -2490,32 +2530,53 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup == 0)
goto skip_fixup_entry;
else {
- fd = open(p->name, O_BINARY | O_NOFOLLOW | O_RDONLY
+ /*
+ * We need to verify if the type of the file
+ * we are going to open matches the file type
+ * of the fixup entry.
+ */
+ openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
+ | O_CLOEXEC;
#if defined(O_DIRECTORY)
- | O_DIRECTORY
+ if (p->filetype == AE_IFDIR)
+ openflags |= O_DIRECTORY;
#endif
- | O_CLOEXEC);
+ fd = open(p->name, openflags);
+
+#if defined(O_DIRECTORY)
/*
- ` * If we don't support O_DIRECTORY,
- * or open() has failed, we must stat()
- * to verify that we are opening a directory
+ * If we support O_DIRECTORY and open was
+ * successful we can skip the file type check
+ * for directories. For other file types
+ * we need to verify via fstat() or lstat()
*/
-#if defined(O_DIRECTORY)
- if (fd == -1) {
+ if (fd == -1 || p->filetype != AE_IFDIR) {
+#if HAVE_FSTAT
+ if (fd > 0 && (
+ fstat(fd, &st) != 0 ||
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0)) {
+ goto skip_fixup_entry;
+ } else
+#endif
if (lstat(p->name, &st) != 0 ||
- !S_ISDIR(st.st_mode)) {
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0) {
goto skip_fixup_entry;
}
}
#else
#if HAVE_FSTAT
if (fd > 0 && (
- fstat(fd, &st) != 0 || !S_ISDIR(st.st_mode))) {
+ fstat(fd, &st) != 0 ||
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0)) {
goto skip_fixup_entry;
} else
#endif
if (lstat(p->name, &st) != 0 ||
- !S_ISDIR(st.st_mode)) {
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0) {
goto skip_fixup_entry;
}
#endif
@@ -2689,6 +2750,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
fe->next = a->fixup_list;
a->fixup_list = fe;
fe->fixup = 0;
+ fe->filetype = 0;
fe->name = strdup(pathname);
return (fe);
}
@@ -3811,6 +3873,7 @@ set_fflags(struct archive_write_disk *a)
le = current_fixup(a, a->name);
if (le == NULL)
return (ARCHIVE_FATAL);
+ le->filetype = archive_entry_filetype(a->entry);
le->fixup |= TODO_FFLAGS;
le->fflags_set = set;
/* Store the mode if it's not already there. */

View File

@ -0,0 +1,58 @@
From a7ce8a6aa7b710986ab918761c8d2ff1b0e9f537 Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Sat, 28 Aug 2021 11:58:00 +0000
Subject: [PATCH] Fix size_t cast in read_mac_metadata_blob
The size_t data type on 32 bit systems is smaller than int64_t. Check
the int64_t value before casting to size_t. If the value is too large
then stop operation instead of continuing operation with truncated
value.
Conflict:NA
Reference:https://github.com/libarchive/libarchive/commit/a7ce8a6aa7b710986ab918761c8d2ff1b0e9f537
---
libarchive/archive_read_support_format_tar.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c
index 7e8febacf..773796a5d 100644
--- a/libarchive/archive_read_support_format_tar.c
+++ b/libarchive/archive_read_support_format_tar.c
@@ -1396,6 +1396,7 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
{
int64_t size;
+ size_t msize;
const void *data;
const char *p, *name;
const wchar_t *wp, *wname;
@@ -1434,6 +1435,11 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
/* Read the body as a Mac OS metadata blob. */
size = archive_entry_size(entry);
+ msize = (size_t)size;
+ if (size < 0 || (uintmax_t)msize != (uintmax_t)size) {
+ *unconsumed = 0;
+ return (ARCHIVE_FATAL);
+ }
/*
* TODO: Look beyond the body here to peek at the next header.
@@ -1447,13 +1453,13 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
* Q: Is the above idea really possible? Even
* when there are GNU or pax extension entries?
*/
- data = __archive_read_ahead(a, (size_t)size, NULL);
+ data = __archive_read_ahead(a, msize, NULL);
if (data == NULL) {
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
- archive_entry_copy_mac_metadata(entry, data, (size_t)size);
- *unconsumed = (size_t)((size + 511) & ~ 511);
+ archive_entry_copy_mac_metadata(entry, data, msize);
+ *unconsumed = (msize + 511) & ~ 511;
tar_flush_unconsumed(a, unconsumed);
return (tar_read_header(a, tar, entry, unconsumed));
}

View File

@ -0,0 +1,24 @@
From 1ab606af27d6b3fa07a638b7f04efadbc8ef75b4 Mon Sep 17 00:00:00 2001
From: zhangnaru <zhangnaru@huawei.com>
Date: Tue, 28 Jul 2020 15:05:03 +0800
Subject: [PATCH] there need to add the init of child to solve the
problem in oss-fuzz
---
libarchive/filter_fork_posix.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libarchive/filter_fork_posix.c b/libarchive/filter_fork_posix.c
index ac255c4..62085a7 100644
--- a/libarchive/filter_fork_posix.c
+++ b/libarchive/filter_fork_posix.c
@@ -76,7 +76,7 @@ int
__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
pid_t *out_child)
{
- pid_t child;
+ pid_t child = -1;
int stdin_pipe[2], stdout_pipe[2], tmp;
#if HAVE_POSIX_SPAWNP
posix_spawn_file_actions_t actions;
--
2.23.0

View File

@ -2,7 +2,7 @@
Name: libarchive
Version: 3.5.2
Release: 2
Release: 3
Summary: Multi-format archive and compression library
License: BSD
@ -14,6 +14,10 @@ BuildRequires: lzo-devel e2fsprogs-devel libacl-devel libattr-devel
BuildRequires: openssl-devel libxml2-devel lz4-devel automake libzstd-devel
Patch6000: backport-libarchive-3.5.2-symlink-fix.patch
Patch6001: backport-CVE-2021-36976.patch
Patch6002: backport-CVE-2021-31566.patch
Patch9000: libarchive-uninitialized-value.patch
%description
%{name} is an open-source BSD-licensed C programming library that
@ -186,6 +190,9 @@ run_testsuite
%{_bindir}/bsdcat
%changelog
* Sat Apr 09 2022 wangkerong <wangkerong@h-paetners.com> - 3.5.2-3
- fix CVE-2021-36976,CVE-2021-31566,fix fuzz test
* Sat Mar 26 2022 wangkerong <wangkerong@h-paetners.com> - 3.5.2-2
- Eanable make check