Skip to content

Commit 64f8e20

Browse files
CBL-Mariner-Botazurelinux-securityarchana25-msjslobodzian
authored
[AUTO-CHERRYPICK] [AutoPR- Security] Patch busybox for CVE-2026-26157 [HIGH] - branch main (#15926)
Co-authored-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> Co-authored-by: Archana Shettigar <v-shettigara@microsoft.com> Co-authored-by: jslobodzian <joslobo@microsoft.com>
1 parent df96124 commit 64f8e20

File tree

2 files changed

+191
-2
lines changed

2 files changed

+191
-2
lines changed

SPECS/busybox/CVE-2026-26157.patch

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
From aa0edb24046518878890e19a67f39da34829d8ed Mon Sep 17 00:00:00 2001
2+
From: AllSpark <allspark@microsoft.com>
3+
Date: Mon, 16 Feb 2026 08:43:24 +0000
4+
Subject: [PATCH] tar: strip unsafe hardlink components; adjust unsafe prefix
5+
handling and messages per GNU tar 1.34; update symlink handling and path
6+
traversal guards; add skip_unsafe_prefix and strip_unsafe_prefix APIs; update
7+
httpd_ratelimit_cgi messages formatting
8+
9+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
10+
Upstream-reference: AI Backport of https://github.com/mirror/busybox/commit/3fb6b31c716669e12f75a2accd31bb7685b1a1cb.patch
11+
---
12+
archival/libarchive/data_extract_all.c | 7 ++---
13+
archival/libarchive/get_header_tar.c | 11 ++++++--
14+
archival/libarchive/unsafe_prefix.c | 31 +++++++++++++++++----
15+
archival/libarchive/unsafe_symlink_target.c | 1 +
16+
archival/tar.c | 2 +-
17+
archival/unzip.c | 2 +-
18+
include/bb_archive.h | 3 +-
19+
7 files changed, 43 insertions(+), 14 deletions(-)
20+
21+
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
22+
index 8a69711..b84b960 100644
23+
--- a/archival/libarchive/data_extract_all.c
24+
+++ b/archival/libarchive/data_extract_all.c
25+
@@ -66,8 +66,8 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
26+
}
27+
#endif
28+
#if ENABLE_FEATURE_PATH_TRAVERSAL_PROTECTION
29+
- /* Strip leading "/" and up to last "/../" path component */
30+
- dst_name = (char *)strip_unsafe_prefix(dst_name);
31+
+ /* Skip leading "/" and past last ".." path component */
32+
+ dst_name = (char *)skip_unsafe_prefix(dst_name);
33+
#endif
34+
// ^^^ This may be a problem if some applets do need to extract absolute names.
35+
// (Probably will need to invent ARCHIVE_ALLOW_UNSAFE_NAME flag).
36+
@@ -185,8 +185,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
37+
38+
/* To avoid a directory traversal attack via symlinks,
39+
* do not restore symlinks with ".." components
40+
- * or symlinks starting with "/", unless a magic
41+
- * envvar is set.
42+
+ * or symlinks starting with "/"
43+
*
44+
* For example, consider a .tar created via:
45+
* $ tar cvf bug.tar anything.txt
46+
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
47+
index d26868b..dc0f7e0 100644
48+
--- a/archival/libarchive/get_header_tar.c
49+
+++ b/archival/libarchive/get_header_tar.c
50+
@@ -452,8 +452,15 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
51+
#endif
52+
53+
/* Everything up to and including last ".." component is stripped */
54+
- overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name));
55+
-//TODO: do the same for file_header->link_target?
56+
+ strip_unsafe_prefix(file_header->name);
57+
+ if (file_header->link_target) {
58+
+ /* GNU tar 1.34 examples:
59+
+ * tar: Removing leading '/' from hard link targets
60+
+ * tar: Removing leading '../' from hard link targets
61+
+ * tar: Removing leading 'etc/../' from hard link targets
62+
+ */
63+
+ strip_unsafe_prefix(file_header->link_target);
64+
+ }
65+
66+
/* Strip trailing '/' in directories */
67+
/* Must be done after mode is set as '/' is used to check if it's a directory */
68+
diff --git a/archival/libarchive/unsafe_prefix.c b/archival/libarchive/unsafe_prefix.c
69+
index 6670811..3acf891 100644
70+
--- a/archival/libarchive/unsafe_prefix.c
71+
+++ b/archival/libarchive/unsafe_prefix.c
72+
@@ -5,11 +5,11 @@
73+
#include "libbb.h"
74+
#include "bb_archive.h"
75+
76+
-const char* FAST_FUNC strip_unsafe_prefix(const char *str)
77+
+const char* FAST_FUNC skip_unsafe_prefix(const char *str)
78+
{
79+
const char *cp = str;
80+
while (1) {
81+
- char *cp2;
82+
+ const char *cp2;
83+
if (*cp == '/') {
84+
cp++;
85+
continue;
86+
@@ -22,10 +22,25 @@ const char* FAST_FUNC strip_unsafe_prefix(const char *str)
87+
cp += 3;
88+
continue;
89+
}
90+
- cp2 = strstr(cp, "/../");
91+
+ cp2 = cp;
92+
+ find_dotdot:
93+
+ cp2 = strstr(cp2, "/..");
94+
if (!cp2)
95+
- break;
96+
- cp = cp2 + 4;
97+
+ break; /* No (more) malicious components */
98+
+ /* We found "/..something" */
99+
+ cp2 += 3;
100+
+ if (*cp2 != '/') {
101+
+ if (*cp2 == '\0') {
102+
+ /* Trailing "/..": malicious, return "" */
103+
+ /* (causes harmless errors trying to create or hardlink a file named "") */
104+
+ return cp2;
105+
+ }
106+
+ /* "/..name" is not malicious, look for next "/.." */
107+
+ goto find_dotdot;
108+
+ }
109+
+ /* Found "/../": malicious, advance past it */
110+
+ cp = cp2 + 1;
111+
+
112+
}
113+
if (cp != str) {
114+
static smallint warned = 0;
115+
@@ -37,3 +52,9 @@ const char* FAST_FUNC strip_unsafe_prefix(const char *str)
116+
}
117+
return cp;
118+
}
119+
+
120+
+
121+
+void FAST_FUNC strip_unsafe_prefix(char *str)
122+
+{
123+
+ overlapping_strcpy(str, skip_unsafe_prefix(str));
124+
+}
125+
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
126+
index f8dc803..d764c89 100644
127+
--- a/archival/libarchive/unsafe_symlink_target.c
128+
+++ b/archival/libarchive/unsafe_symlink_target.c
129+
@@ -36,6 +36,7 @@ void FAST_FUNC create_links_from_list(llist_t *list)
130+
*list->data ? "hard" : "sym",
131+
list->data + 1, target
132+
);
133+
+ /* Note: GNU tar 1.34 errors out only _after_ all links are (attempted to be) created */
134+
}
135+
list = list->link;
136+
}
137+
diff --git a/archival/tar.c b/archival/tar.c
138+
index 9de3759..cf8c2d1 100644
139+
--- a/archival/tar.c
140+
+++ b/archival/tar.c
141+
@@ -475,7 +475,7 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state,
142+
DBG("writeFileToTarball('%s')", fileName);
143+
144+
/* Strip leading '/' and such (must be before memorizing hardlink's name) */
145+
- header_name = strip_unsafe_prefix(fileName);
146+
+ header_name = skip_unsafe_prefix(fileName);
147+
148+
if (header_name[0] == '\0')
149+
return TRUE;
150+
diff --git a/archival/unzip.c b/archival/unzip.c
151+
index fc92ac6..7b29d77 100644
152+
--- a/archival/unzip.c
153+
+++ b/archival/unzip.c
154+
@@ -842,7 +842,7 @@ int unzip_main(int argc, char **argv)
155+
unzip_skip(zip.fmt.extra_len);
156+
157+
/* Guard against "/abspath", "/../" and similar attacks */
158+
- overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn));
159+
+ strip_unsafe_prefix(dst_fn);
160+
161+
/* Filter zip entries */
162+
if (find_list_entry(zreject, dst_fn)
163+
diff --git a/include/bb_archive.h b/include/bb_archive.h
164+
index e0ef8fc..1dc77f3 100644
165+
--- a/include/bb_archive.h
166+
+++ b/include/bb_archive.h
167+
@@ -202,7 +202,8 @@ char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC;
168+
void seek_by_jump(int fd, off_t amount) FAST_FUNC;
169+
void seek_by_read(int fd, off_t amount) FAST_FUNC;
170+
171+
-const char *strip_unsafe_prefix(const char *str) FAST_FUNC;
172+
+const char *skip_unsafe_prefix(const char *str) FAST_FUNC;
173+
+void strip_unsafe_prefix(char *str) FAST_FUNC;
174+
void create_or_remember_link(llist_t **link_placeholders,
175+
const char *target,
176+
const char *linkname,
177+
--
178+
2.45.4
179+

SPECS/busybox/busybox.spec

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Summary: Statically linked binary providing simplified versions of system commands
22
Name: busybox
33
Version: 1.35.0
4-
Release: 17%{?dist}
4+
Release: 18%{?dist}
55
License: GPLv2
66
Vendor: Microsoft Corporation
77
Distribution: Mariner
@@ -24,6 +24,7 @@ Patch10: CVE-2023-42365.patch
2424
Patch11: CVE-2023-42366.patch
2525
Patch12: CVE-2022-48174.patch
2626
Patch13: CVE-2023-39810.patch
27+
Patch14: CVE-2026-26157.patch
2728
BuildRequires: gcc
2829
BuildRequires: glibc-static >= 2.35-10%{?dist}
2930
BuildRequires: libselinux-devel >= 1.27.7-2
@@ -90,6 +91,12 @@ mkdir -p %{buildroot}/%{_mandir}/man1
9091
install -m 644 docs/busybox.static.1 %{buildroot}/%{_mandir}/man1/busybox.1
9192
install -m 644 docs/busybox.petitboot.1 %{buildroot}/%{_mandir}/man1/busybox.petitboot.1
9293

94+
%check
95+
cd testsuite
96+
# CVE-2026-26157: hardened tar extraction blocks symlink + hardlink write attacks
97+
# These tests validate insecure legacy behavior and are expected to fail
98+
./runtest --skip "tar-symlink-attack,tar-symlink-hardlink-coexist"
99+
93100
%files
94101
%license LICENSE
95102
%doc README
@@ -103,9 +110,12 @@ install -m 644 docs/busybox.petitboot.1 %{buildroot}/%{_mandir}/man1/busybox.pet
103110
%{_mandir}/man1/busybox.petitboot.1.gz
104111

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

116+
* Mon Feb 16 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.35.0-17
117+
- Patch for CVE-2026-26157
118+
109119
* Wed Jan 28 2026 Kanishk Bansal <kanbansal@microsoft.com> - 1.35.0-16
110120
- Bump to rebuild with updated glibc
111121

0 commit comments

Comments
 (0)