Skip to content
Merged
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
179 changes: 179 additions & 0 deletions SPECS/busybox/CVE-2026-26157.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
From aa0edb24046518878890e19a67f39da34829d8ed Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Mon, 16 Feb 2026 08:43:24 +0000
Subject: [PATCH] tar: strip unsafe hardlink components; adjust unsafe prefix
handling and messages per GNU tar 1.34; update symlink handling and path
traversal guards; add skip_unsafe_prefix and strip_unsafe_prefix APIs; update
httpd_ratelimit_cgi messages formatting

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport of https://github.com/mirror/busybox/commit/3fb6b31c716669e12f75a2accd31bb7685b1a1cb.patch
---
archival/libarchive/data_extract_all.c | 7 ++---
archival/libarchive/get_header_tar.c | 11 ++++++--
archival/libarchive/unsafe_prefix.c | 31 +++++++++++++++++----
archival/libarchive/unsafe_symlink_target.c | 1 +
archival/tar.c | 2 +-
archival/unzip.c | 2 +-
include/bb_archive.h | 3 +-
7 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index 8a69711..b84b960 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -66,8 +66,8 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
}
#endif
#if ENABLE_FEATURE_PATH_TRAVERSAL_PROTECTION
- /* Strip leading "/" and up to last "/../" path component */
- dst_name = (char *)strip_unsafe_prefix(dst_name);
+ /* Skip leading "/" and past last ".." path component */
+ dst_name = (char *)skip_unsafe_prefix(dst_name);
#endif
// ^^^ This may be a problem if some applets do need to extract absolute names.
// (Probably will need to invent ARCHIVE_ALLOW_UNSAFE_NAME flag).
@@ -185,8 +185,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)

/* To avoid a directory traversal attack via symlinks,
* do not restore symlinks with ".." components
- * or symlinks starting with "/", unless a magic
- * envvar is set.
+ * or symlinks starting with "/"
*
* For example, consider a .tar created via:
* $ tar cvf bug.tar anything.txt
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index d26868b..dc0f7e0 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -452,8 +452,15 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
#endif

/* Everything up to and including last ".." component is stripped */
- overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name));
-//TODO: do the same for file_header->link_target?
+ strip_unsafe_prefix(file_header->name);
+ if (file_header->link_target) {
+ /* GNU tar 1.34 examples:
+ * tar: Removing leading '/' from hard link targets
+ * tar: Removing leading '../' from hard link targets
+ * tar: Removing leading 'etc/../' from hard link targets
+ */
+ strip_unsafe_prefix(file_header->link_target);
+ }

/* Strip trailing '/' in directories */
/* Must be done after mode is set as '/' is used to check if it's a directory */
diff --git a/archival/libarchive/unsafe_prefix.c b/archival/libarchive/unsafe_prefix.c
index 6670811..3acf891 100644
--- a/archival/libarchive/unsafe_prefix.c
+++ b/archival/libarchive/unsafe_prefix.c
@@ -5,11 +5,11 @@
#include "libbb.h"
#include "bb_archive.h"

-const char* FAST_FUNC strip_unsafe_prefix(const char *str)
+const char* FAST_FUNC skip_unsafe_prefix(const char *str)
{
const char *cp = str;
while (1) {
- char *cp2;
+ const char *cp2;
if (*cp == '/') {
cp++;
continue;
@@ -22,10 +22,25 @@ const char* FAST_FUNC strip_unsafe_prefix(const char *str)
cp += 3;
continue;
}
- cp2 = strstr(cp, "/../");
+ cp2 = cp;
+ find_dotdot:
+ cp2 = strstr(cp2, "/..");
if (!cp2)
- break;
- cp = cp2 + 4;
+ break; /* No (more) malicious components */
+ /* We found "/..something" */
+ cp2 += 3;
+ if (*cp2 != '/') {
+ if (*cp2 == '\0') {
+ /* Trailing "/..": malicious, return "" */
+ /* (causes harmless errors trying to create or hardlink a file named "") */
+ return cp2;
+ }
+ /* "/..name" is not malicious, look for next "/.." */
+ goto find_dotdot;
+ }
+ /* Found "/../": malicious, advance past it */
+ cp = cp2 + 1;
+
}
if (cp != str) {
static smallint warned = 0;
@@ -37,3 +52,9 @@ const char* FAST_FUNC strip_unsafe_prefix(const char *str)
}
return cp;
}
+
+
+void FAST_FUNC strip_unsafe_prefix(char *str)
+{
+ overlapping_strcpy(str, skip_unsafe_prefix(str));
+}
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
index f8dc803..d764c89 100644
--- a/archival/libarchive/unsafe_symlink_target.c
+++ b/archival/libarchive/unsafe_symlink_target.c
@@ -36,6 +36,7 @@ void FAST_FUNC create_links_from_list(llist_t *list)
*list->data ? "hard" : "sym",
list->data + 1, target
);
+ /* Note: GNU tar 1.34 errors out only _after_ all links are (attempted to be) created */
}
list = list->link;
}
diff --git a/archival/tar.c b/archival/tar.c
index 9de3759..cf8c2d1 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -475,7 +475,7 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state,
DBG("writeFileToTarball('%s')", fileName);

/* Strip leading '/' and such (must be before memorizing hardlink's name) */
- header_name = strip_unsafe_prefix(fileName);
+ header_name = skip_unsafe_prefix(fileName);

if (header_name[0] == '\0')
return TRUE;
diff --git a/archival/unzip.c b/archival/unzip.c
index fc92ac6..7b29d77 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -842,7 +842,7 @@ int unzip_main(int argc, char **argv)
unzip_skip(zip.fmt.extra_len);

/* Guard against "/abspath", "/../" and similar attacks */
- overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn));
+ strip_unsafe_prefix(dst_fn);

/* Filter zip entries */
if (find_list_entry(zreject, dst_fn)
diff --git a/include/bb_archive.h b/include/bb_archive.h
index e0ef8fc..1dc77f3 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -202,7 +202,8 @@ char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC;
void seek_by_jump(int fd, off_t amount) FAST_FUNC;
void seek_by_read(int fd, off_t amount) FAST_FUNC;

-const char *strip_unsafe_prefix(const char *str) FAST_FUNC;
+const char *skip_unsafe_prefix(const char *str) FAST_FUNC;
+void strip_unsafe_prefix(char *str) FAST_FUNC;
void create_or_remember_link(llist_t **link_placeholders,
const char *target,
const char *linkname,
--
2.45.4

14 changes: 12 additions & 2 deletions SPECS/busybox/busybox.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: Statically linked binary providing simplified versions of system commands
Name: busybox
Version: 1.35.0
Release: 17%{?dist}
Release: 18%{?dist}
License: GPLv2
Vendor: Microsoft Corporation
Distribution: Mariner
Expand All @@ -24,6 +24,7 @@ Patch10: CVE-2023-42365.patch
Patch11: CVE-2023-42366.patch
Patch12: CVE-2022-48174.patch
Patch13: CVE-2023-39810.patch
Patch14: CVE-2026-26157.patch
BuildRequires: gcc
BuildRequires: glibc-static >= 2.35-10%{?dist}
BuildRequires: libselinux-devel >= 1.27.7-2
Expand Down Expand Up @@ -90,6 +91,12 @@ mkdir -p %{buildroot}/%{_mandir}/man1
install -m 644 docs/busybox.static.1 %{buildroot}/%{_mandir}/man1/busybox.1
install -m 644 docs/busybox.petitboot.1 %{buildroot}/%{_mandir}/man1/busybox.petitboot.1

%check
cd testsuite
# CVE-2026-26157: hardened tar extraction blocks symlink + hardlink write attacks
# These tests validate insecure legacy behavior and are expected to fail
./runtest --skip "tar-symlink-attack,tar-symlink-hardlink-coexist"

%files
%license LICENSE
%doc README
Expand All @@ -103,9 +110,12 @@ install -m 644 docs/busybox.petitboot.1 %{buildroot}/%{_mandir}/man1/busybox.pet
%{_mandir}/man1/busybox.petitboot.1.gz

%changelog
* Tue Feb 03 2026 Aditya Singh <v-aditysing@microsoft.com> - 1.35.0-17
* Thu Feb 19 2026 Aditya Singh <v-aditysing@microsoft.com> - 1.35.0-18
- Bump to rebuild with updated glibc

* Mon Feb 16 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.35.0-17
- Patch for CVE-2026-26157

* Wed Jan 28 2026 Kanishk Bansal <kanbansal@microsoft.com> - 1.35.0-16
- Bump to rebuild with updated glibc

Expand Down
Loading