Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
334 changes: 334 additions & 0 deletions SPECS/libarchive/CVE-2026-16517.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
From e8558e206301e86ccbdfd0cfa872f83bd4db91e0 Mon Sep 17 00:00:00 2001
From: datauwu <209150516+datauwu@users.noreply.github.com>
Date: Fri, 3 Jul 2026 17:36:50 +0800
Subject: [PATCH] zip: avoid signed overflow in encrypted size checks

Avoid adding the encryption overhead directly to entry sizes when deciding
whether Zip64 is needed or when updating the stored compressed size.

For the Zip64 decision, compare against ZIP_4GB_MAX - additional_size. For
stored encrypted entries, use archive_ckd_add_i64() so the size update and
overflow check happen together.

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/libarchive/libarchive/commit/1c6e7b491f60fce335c20a9692f870d1f1ca39aa.patch

---
libarchive/archive_integer.h | 267 ++++++++++++++++++++++
libarchive/archive_write_set_format_zip.c | 12 +-
2 files changed, 276 insertions(+), 3 deletions(-)
create mode 100644 libarchive/archive_integer.h

diff --git a/libarchive/archive_integer.h b/libarchive/archive_integer.h
new file mode 100644
index 0000000..1e71592
--- /dev/null
+++ b/libarchive/archive_integer.h
@@ -0,0 +1,267 @@
+/*-
+ * Copyright (c) 2026 Tobias Stoeckmann
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ARCHIVE_INTEGER_H_INCLUDED
+#define ARCHIVE_INTEGER_H_INCLUDED
+
+#include "archive_platform.h"
+
+/* Note: This is a purely internal header! */
+/* Do not use this outside of libarchive internal code! */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifdef HAVE_INTSAFE_H
+#define ENABLE_INTSAFE_SIGNED_FUNCTIONS
+#include <intsafe.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_STDCKDINT_H
+#include <stdckdint.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#ifdef HAVE_STDCKDINT_H
+#define USE_STDCKDINT 1
+#elif (__GNUC__ >= 5 && !defined(__INTEL_COMPILER))
+#define USE_BUILTIN 1
+#elif __has_builtin(__builtin_add_overflow)
+#define USE_BUILTIN 1
+#elif defined HAVE_INTSAFE_H
+#define USE_INTSAFE 1
+#endif
+
+/*
+ * Disabling inline keyword for compilers known to choke on it:
+ * - Watcom C++ in C code. (For any version?)
+ * - SGI MIPSpro
+ * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
+ * - IBM VisualAge 6 (XL v6)
+ * - Sun WorkShop C (SunPro) before 5.9
+ */
+#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
+#define inline
+#elif defined(__IBMC__) && __IBMC__ < 700
+#define inline
+#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590
+#define inline
+#elif defined(_MSC_VER) || defined(__osf__)
+#define inline __inline
+#endif
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_add_i64(int64_t *result, int64_t a, int64_t b)
+{
+#if USE_STDCKDINT
+ return ckd_add(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_add_overflow(a, b, result);
+#elif USE_INTSAFE
+ LONGLONG res;
+ int ret;
+
+ ret = LongLongAdd(a, b, &res);
+ *result = (int64_t)res;
+ return ret;
+#else
+ if ((b > 0 && a > INT64_MAX - b) ||
+ (b < 0 && a < INT64_MIN - b))
+ return 1;
+
+ *result = a + b;
+ return 0;
+#endif
+}
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_add_size(size_t *result, size_t a, size_t b)
+{
+#if USE_STDCKDINT
+ return ckd_add(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_add_overflow(a, b, result);
+#elif USE_INTSAFE
+ return SizeTAdd(a, b, result);
+#else
+ if (a > SIZE_MAX - b)
+ return 1;
+ *result = a + b;
+ return 0;
+#endif
+}
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_add_u64(uint64_t *result, uint64_t a, uint64_t b)
+{
+#if USE_STDCKDINT
+ return ckd_add(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_add_overflow(a, b, result);
+#elif USE_INTSAFE
+ ULONGLONG res;
+ int ret;
+
+ ret = ULongLongAdd(a, b, &res);
+ *result = (uint64_t)res;
+ return ret;
+#else
+ if (a > UINT64_MAX - b)
+ return 1;
+ *result = a + b;
+ return 0;
+#endif
+}
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_mul_i64(int64_t *result, int64_t a, int64_t b)
+{
+#if USE_STDCKDINT
+ return ckd_mul(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_mul_overflow(a, b, result);
+#elif USE_INTSAFE
+ LONGLONG res;
+ int ret;
+
+ ret = LongLongMult(a, b, &res);
+ *result = (int64_t)res;
+ return ret;
+#else
+ if ((a > 0 && b > 0 && a > INT64_MAX / b) ||
+ (a < 0 && b > 0 && a < INT64_MIN / b) ||
+ (a > 0 && b < 0 && b < INT64_MIN / a) ||
+ (a < 0 && b < 0 && a < INT64_MAX / b))
+ return 1;
+
+ *result = a * b;
+ return 0;
+#endif
+}
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_mul_size(size_t *result, size_t a, size_t b)
+{
+#if USE_STDCKDINT
+ return ckd_mul(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_mul_overflow(a, b, result);
+#elif USE_INTSAFE
+ return SizeTMult(a, b, result);
+#else
+ if (b != 0 && a > SIZE_MAX / b)
+ return 1;
+ *result = a * b;
+ return 0;
+#endif
+}
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_mul_u64(uint64_t *result, uint64_t a, uint64_t b)
+{
+#if USE_STDCKDINT
+ return ckd_mul(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_mul_overflow(a, b, result);
+#elif USE_INTSAFE
+ ULONGLONG res;
+ int ret;
+
+ ret = ULongLongMult(a, b, &res);
+ *result = (uint64_t)res;
+ return ret;
+#else
+ if (b != 0 && a > UINT64_MAX / b)
+ return 1;
+ *result = a * b;
+ return 0;
+#endif
+}
+
+/* Returns 0 on success, a non-zero value otherwise. */
+static inline int
+archive_ckd_sub_i64(int64_t *result, int64_t a, int64_t b)
+{
+#if USE_STDCKDINT
+ return ckd_sub(result, a, b);
+#elif USE_BUILTIN
+ return __builtin_sub_overflow(a, b, result);
+#elif USE_INTSAFE
+ LONGLONG res;
+ int ret;
+
+ ret = LongLongSub(a, b, &res);
+ *result = (int64_t)res;
+ return ret;
+#else
+ if ((b > 0 && a < INT64_MIN + b) ||
+ (b < 0 && a > INT64_MAX + b))
+ return 1;
+
+ *result = a - b;
+ return 0;
+#endif
+}
+
+#if !defined(TIME_MAX)
+#define TIME_MAX (((time_t)0 < (time_t)-1) ? (time_t)~0 : \
+ sizeof(time_t) == sizeof(long long) ? (time_t)LLONG_MAX : \
+ sizeof(time_t) == sizeof(long) ? (time_t)LONG_MAX : \
+ sizeof(time_t) == sizeof(int) ? (time_t)INT_MAX : \
+ sizeof(time_t) == sizeof(short) ? (time_t)SHRT_MAX : \
+ 1 /* I give up */)
+#endif
+#if !defined(TIME_MIN)
+#define TIME_MIN (((time_t)0 < (time_t)-1) ? (time_t)0 : \
+ sizeof(time_t) == sizeof(long long) ? (time_t)LLONG_MIN : \
+ sizeof(time_t) == sizeof(long) ? (time_t)LONG_MIN : \
+ sizeof(time_t) == sizeof(int) ? (time_t)INT_MIN : \
+ sizeof(time_t) == sizeof(short) ? (time_t)SHRT_MIN : \
+ -1 /* I give up */)
+#endif
+
+#endif
diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c
index a9f2877..e267736 100644
--- a/libarchive/archive_write_set_format_zip.c
+++ b/libarchive/archive_write_set_format_zip.c
@@ -53,6 +53,7 @@
#include "archive_entry.h"
#include "archive_entry_locale.h"
#include "archive_hmac_private.h"
+#include "archive_integer.h"
#include "archive_private.h"
#include "archive_random_private.h"
#include "archive_write_private.h"
@@ -714,8 +715,13 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
default:
break;
}
- if (zip->entry_compression == COMPRESSION_STORE)
- zip->entry_compressed_size += additional_size;
+ if (zip->entry_compression == COMPRESSION_STORE &&
+ archive_ckd_add_i64(&zip->entry_compressed_size,
+ zip->entry_compressed_size, additional_size)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "File size too large for encrypted ZIP entry");
+ return (ARCHIVE_FAILED);
+ }
}

/*
@@ -729,7 +735,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
* (compression might make file larger)
*/
if ((zip->flags & ZIP_FLAG_FORCE_ZIP64)
- || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX)
+ || (zip->entry_uncompressed_size > ZIP_4GB_MAX - additional_size)
|| (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED
&& zip->entry_compression != COMPRESSION_STORE)) {
MIN_VERSION_NEEDED(45);
--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/libarchive/libarchive.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: Multi-format archive and compression library
Name: libarchive
Version: 3.7.7
Release: 7%{?dist}
Release: 8%{?dist}
# Certain files have individual licenses. For more details see contents of "COPYING".
License: BSD AND Public Domain AND (ASL 2.0 OR CC0 1.0 OR OpenSSL)
Vendor: Microsoft Corporation
Expand All @@ -22,6 +22,7 @@ Patch10: CVE-2026-4426.patch
Patch11: CVE-2026-5121.patch
Patch12: CVE-2026-14164.patch
Patch13: CVE-2026-15028.patch
Patch14: CVE-2026-16517.patch
Provides: bsdtar = %{version}-%{release}

BuildRequires: xz-libs
Expand Down Expand Up @@ -79,6 +80,9 @@ make %{?_smp_mflags} check
%{_libdir}/pkgconfig/*.pc

%changelog
* Thu Aug 06 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.7.7-8
- Patch for CVE-2026-16517

* Wed Jul 22 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.7.7-7
- Patch for CVE-2026-15028, CVE-2026-14164

Expand Down
4 changes: 2 additions & 2 deletions toolkit/resources/manifests/package/pkggen_core_aarch64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ openssl-static-3.3.7-4.azl3.aarch64.rpm
libcap-2.69-15.azl3.aarch64.rpm
libcap-devel-2.69-15.azl3.aarch64.rpm
debugedit-5.0-3.azl3.aarch64.rpm
libarchive-3.7.7-7.azl3.aarch64.rpm
libarchive-devel-3.7.7-7.azl3.aarch64.rpm
libarchive-3.7.7-8.azl3.aarch64.rpm
libarchive-devel-3.7.7-8.azl3.aarch64.rpm
rpm-4.18.2-1.azl3.aarch64.rpm
rpm-build-4.18.2-1.azl3.aarch64.rpm
rpm-build-libs-4.18.2-1.azl3.aarch64.rpm
Expand Down
4 changes: 2 additions & 2 deletions toolkit/resources/manifests/package/pkggen_core_x86_64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ openssl-static-3.3.7-4.azl3.x86_64.rpm
libcap-2.69-15.azl3.x86_64.rpm
libcap-devel-2.69-15.azl3.x86_64.rpm
debugedit-5.0-3.azl3.x86_64.rpm
libarchive-3.7.7-7.azl3.x86_64.rpm
libarchive-devel-3.7.7-7.azl3.x86_64.rpm
libarchive-3.7.7-8.azl3.x86_64.rpm
libarchive-devel-3.7.7-8.azl3.x86_64.rpm
rpm-4.18.2-1.azl3.x86_64.rpm
rpm-build-4.18.2-1.azl3.x86_64.rpm
rpm-build-libs-4.18.2-1.azl3.x86_64.rpm
Expand Down
6 changes: 3 additions & 3 deletions toolkit/resources/manifests/package/toolchain_aarch64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ krb5-devel-1.21.3-5.azl3.aarch64.rpm
krb5-lang-1.21.3-5.azl3.aarch64.rpm
libacl-2.4.0-1.azl3.aarch64.rpm
libacl-devel-2.4.0-1.azl3.aarch64.rpm
libarchive-3.7.7-7.azl3.aarch64.rpm
libarchive-debuginfo-3.7.7-7.azl3.aarch64.rpm
libarchive-devel-3.7.7-7.azl3.aarch64.rpm
libarchive-3.7.7-8.azl3.aarch64.rpm
libarchive-debuginfo-3.7.7-8.azl3.aarch64.rpm
libarchive-devel-3.7.7-8.azl3.aarch64.rpm
libassuan-2.5.6-1.azl3.aarch64.rpm
libassuan-debuginfo-2.5.6-1.azl3.aarch64.rpm
libassuan-devel-2.5.6-1.azl3.aarch64.rpm
Expand Down
Loading
Loading