summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorMartin Jansa <martin.jansa@gmail.com>2019-03-10 20:12:01 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-03-25 23:12:03 +0000
commit2333147fa6be430bbb64381d7c3eaf2f3f4ead1f (patch)
tree1cf981764be45bf32619d7d327c83a9beeb1bd6c /meta
parente0fdb98b0f09d6a5c7e2f72dce480c56710f3697 (diff)
downloadpoky-2333147fa6be430bbb64381d7c3eaf2f3f4ead1f.tar.gz
busybox: backport fix for issues introduced by CVE-2011-5325.patch
(From OE-Core rev: d0555e89514f2641387ef061f9ffcd1c8ced008c) Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com> Reviewed-by: Tom Rini <trini@konsulko.com> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-core/busybox/busybox/CVE-2011-5325-fix.patch393
-rw-r--r--meta/recipes-core/busybox/busybox_1.27.2.bb1
2 files changed, 394 insertions, 0 deletions
diff --git a/meta/recipes-core/busybox/busybox/CVE-2011-5325-fix.patch b/meta/recipes-core/busybox/busybox/CVE-2011-5325-fix.patch
new file mode 100644
index 0000000000..a8d7e4bd50
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/CVE-2011-5325-fix.patch
@@ -0,0 +1,393 @@
1From 3e1e224fd031ae3927acda70f6e1fa55193e5b68 Mon Sep 17 00:00:00 2001
2From: Denys Vlasenko <vda.linux@googlemail.com>
3Date: Tue, 20 Feb 2018 15:57:45 +0100
4Subject: [PATCH] tar,unzip: postpone creation of symlinks with "suspicious"
5 targets
6
7This mostly reverts commit bc9bbeb2b81001e8731cd2ae501c8fccc8d87cc7
8"libarchive: do not extract unsafe symlinks unless $EXTRACT_UNSAFE_SYMLINKS=1"
9
10Users report that it is somewhat too restrictive. See
11https://bugs.busybox.net/show_bug.cgi?id=8411
12
13In particular, this interferes with unpacking of busybox-based
14filesystems with links like "sbin/applet" -> "../bin/busybox".
15
16The change is made smaller by deleting ARCHIVE_EXTRACT_QUIET flag -
17it is unused since 2010, and removing conditionals on it
18allows commonalizing some error message codes.
19
20function old new delta
21create_or_remember_symlink - 94 +94
22create_symlinks_from_list - 64 +64
23tar_main 1002 1006 +4
24unzip_main 2732 2724 -8
25data_extract_all 984 891 -93
26unsafe_symlink_target 147 - -147
27------------------------------------------------------------------------------
28(add/remove: 2/1 grow/shrink: 1/2 up/down: 162/-248) Total: -86 bytes
29
30Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
31
32Upstream-Status: Backport from 1.28.2 [https://git.busybox.net/busybox/commit/?h=1_28_stable&id=37277a23fe48b13313f5d96084d890ed21d5fd8b]
33
34Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
35---
36 archival/libarchive/data_extract_all.c | 50 +++++++++-------
37 archival/libarchive/unsafe_symlink_target.c | 63 +++++++++------------
38 archival/tar.c | 2 +
39 archival/unzip.c | 29 ++++++----
40 include/bb_archive.h | 23 +++++---
41 testsuite/tar.tests | 10 ++--
42 6 files changed, 95 insertions(+), 82 deletions(-)
43
44diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
45index b828b656d..dad8d7d87 100644
46--- a/archival/libarchive/data_extract_all.c
47+++ b/archival/libarchive/data_extract_all.c
48@@ -108,9 +108,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
49 }
50 }
51 else if (existing_sb.st_mtime >= file_header->mtime) {
52- if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
53- && !S_ISDIR(file_header->mode)
54- ) {
55+ if (!S_ISDIR(file_header->mode)) {
56 bb_error_msg("%s not created: newer or "
57 "same age file exists", dst_name);
58 }
59@@ -126,7 +124,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
60 /* Handle hard links separately */
61 if (hard_link) {
62 res = link(hard_link, dst_name);
63- if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
64+ if (res != 0) {
65 /* shared message */
66 bb_perror_msg("can't create %slink '%s' to '%s'",
67 "hard", dst_name, hard_link
68@@ -166,10 +164,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
69 }
70 case S_IFDIR:
71 res = mkdir(dst_name, file_header->mode);
72- if ((res == -1)
73+ if ((res != 0)
74 && (errno != EISDIR) /* btw, Linux doesn't return this */
75 && (errno != EEXIST)
76- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
77 ) {
78 bb_perror_msg("can't make dir %s", dst_name);
79 }
80@@ -177,27 +174,38 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
81 case S_IFLNK:
82 /* Symlink */
83 //TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
84- if (!unsafe_symlink_target(file_header->link_target)) {
85- res = symlink(file_header->link_target, dst_name);
86- if (res != 0
87- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
88- ) {
89- /* shared message */
90- bb_perror_msg("can't create %slink '%s' to '%s'",
91- "sym",
92- dst_name, file_header->link_target
93- );
94- }
95- }
96+
97+ /* To avoid a directory traversal attack via symlinks,
98+ * do not restore symlinks with ".." components
99+ * or symlinks starting with "/", unless a magic
100+ * envvar is set.
101+ *
102+ * For example, consider a .tar created via:
103+ * $ tar cvf bug.tar anything.txt
104+ * $ ln -s /tmp symlink
105+ * $ tar --append -f bug.tar symlink
106+ * $ rm symlink
107+ * $ mkdir symlink
108+ * $ tar --append -f bug.tar symlink/evil.py
109+ *
110+ * This will result in an archive that contains:
111+ * $ tar --list -f bug.tar
112+ * anything.txt
113+ * symlink [-> /tmp]
114+ * symlink/evil.py
115+ *
116+ * Untarring bug.tar would otherwise place evil.py in '/tmp'.
117+ */
118+ create_or_remember_symlink(&archive_handle->symlink_placeholders,
119+ file_header->link_target,
120+ dst_name);
121 break;
122 case S_IFSOCK:
123 case S_IFBLK:
124 case S_IFCHR:
125 case S_IFIFO:
126 res = mknod(dst_name, file_header->mode, file_header->device);
127- if ((res == -1)
128- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
129- ) {
130+ if (res != 0) {
131 bb_perror_msg("can't create node %s", dst_name);
132 }
133 break;
134diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
135index ee46e28f8..8dcafeaa1 100644
136--- a/archival/libarchive/unsafe_symlink_target.c
137+++ b/archival/libarchive/unsafe_symlink_target.c
138@@ -5,44 +5,37 @@
139 #include "libbb.h"
140 #include "bb_archive.h"
141
142-int FAST_FUNC unsafe_symlink_target(const char *target)
143+void FAST_FUNC create_or_remember_symlink(llist_t **symlink_placeholders,
144+ const char *target,
145+ const char *linkname)
146 {
147- const char *dot;
148-
149- if (target[0] == '/') {
150- const char *var;
151-unsafe:
152- var = getenv("EXTRACT_UNSAFE_SYMLINKS");
153- if (var) {
154- if (LONE_CHAR(var, '1'))
155- return 0; /* pretend it's safe */
156- return 1; /* "UNSAFE!" */
157- }
158- bb_error_msg("skipping unsafe symlink to '%s' in archive,"
159- " set %s=1 to extract",
160- target,
161- "EXTRACT_UNSAFE_SYMLINKS"
162+ if (target[0] == '/' || strstr(target, "..")) {
163+ llist_add_to(symlink_placeholders,
164+ xasprintf("%s%c%s", linkname, '\0', target)
165+ );
166+ return;
167+ }
168+ if (symlink(target, linkname) != 0) {
169+ /* shared message */
170+ bb_perror_msg_and_die("can't create %slink '%s' to '%s'",
171+ "sym", linkname, target
172 );
173- /* Prevent further messages */
174- setenv("EXTRACT_UNSAFE_SYMLINKS", "0", 0);
175- return 1; /* "UNSAFE!" */
176 }
177+}
178
179- dot = target;
180- for (;;) {
181- dot = strchr(dot, '.');
182- if (!dot)
183- return 0; /* safe target */
184+void FAST_FUNC create_symlinks_from_list(llist_t *list)
185+{
186+ while (list) {
187+ char *target;
188
189- /* Is it a path component starting with ".."? */
190- if ((dot[1] == '.')
191- && (dot == target || dot[-1] == '/')
192- /* Is it exactly ".."? */
193- && (dot[2] == '/' || dot[2] == '\0')
194- ) {
195- goto unsafe;
196- }
197- /* NB: it can even be trailing ".", should only add 1 */
198- dot += 1;
199+ target = list->data + strlen(list->data) + 1;
200+ if (symlink(target, list->data)) {
201+ /* shared message */
202+ bb_error_msg_and_die("can't create %slink '%s' to '%s'",
203+ "sym",
204+ list->data, target
205+ );
206+ }
207+ list = list->link;
208 }
209-}
210\ No newline at end of file
211+}
212diff --git a/archival/tar.c b/archival/tar.c
213index 7598b71e3..bde86330c 100644
214--- a/archival/tar.c
215+++ b/archival/tar.c
216@@ -1252,6 +1252,8 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
217 while (get_header_tar(tar_handle) == EXIT_SUCCESS)
218 bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */
219
220+ create_symlinks_from_list(tar_handle->symlink_placeholders);
221+
222 /* Check that every file that should have been extracted was */
223 while (tar_handle->accept) {
224 if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
225diff --git a/archival/unzip.c b/archival/unzip.c
226index 270e261b7..2f53ab7a4 100644
227--- a/archival/unzip.c
228+++ b/archival/unzip.c
229@@ -335,7 +335,10 @@ static void unzip_create_leading_dirs(const char *fn)
230 free(name);
231 }
232
233-static void unzip_extract_symlink(zip_header_t *zip, const char *dst_fn)
234+#if ENABLE_FEATURE_UNZIP_CDF
235+static void unzip_extract_symlink(llist_t **symlink_placeholders,
236+ zip_header_t *zip,
237+ const char *dst_fn)
238 {
239 char *target;
240
241@@ -361,17 +364,12 @@ static void unzip_extract_symlink(zip_header_t *zip, const char *dst_fn)
242 target[xstate.mem_output_size] = '\0';
243 #endif
244 }
245- if (!unsafe_symlink_target(target)) {
246-//TODO: libbb candidate
247- if (symlink(target, dst_fn)) {
248- /* shared message */
249- bb_perror_msg_and_die("can't create %slink '%s' to '%s'",
250- "sym", dst_fn, target
251- );
252- }
253- }
254+ create_or_remember_symlink(symlink_placeholders,
255+ target,
256+ dst_fn);
257 free(target);
258 }
259+#endif
260
261 static void unzip_extract(zip_header_t *zip, int dst_fd)
262 {
263@@ -464,6 +462,9 @@ int unzip_main(int argc, char **argv)
264 llist_t *zaccept = NULL;
265 llist_t *zreject = NULL;
266 char *base_dir = NULL;
267+#if ENABLE_FEATURE_UNZIP_CDF
268+ llist_t *symlink_placeholders = NULL;
269+#endif
270 int i, opt;
271 char key_buf[80]; /* must match size used by my_fgets80 */
272 struct stat stat_buf;
273@@ -894,8 +895,8 @@ int unzip_main(int argc, char **argv)
274 }
275 #if ENABLE_FEATURE_UNZIP_CDF
276 if (S_ISLNK(file_mode)) {
277- if (dst_fd != STDOUT_FILENO) /* no -p */
278- unzip_extract_symlink(&zip, dst_fn);
279+ if (dst_fd != STDOUT_FILENO) /* not -p? */
280+ unzip_extract_symlink(&symlink_placeholders, &zip, dst_fn);
281 } else
282 #endif
283 {
284@@ -931,6 +932,10 @@ int unzip_main(int argc, char **argv)
285 total_entries++;
286 }
287
288+#if ENABLE_FEATURE_UNZIP_CDF
289+ create_symlinks_from_list(symlink_placeholders);
290+#endif
291+
292 if (listing && quiet <= 1) {
293 if (!verbose) {
294 // " Length Date Time Name\n"
295diff --git a/include/bb_archive.h b/include/bb_archive.h
296index 1e4da3c33..436eb0fe3 100644
297--- a/include/bb_archive.h
298+++ b/include/bb_archive.h
299@@ -64,6 +64,9 @@ typedef struct archive_handle_t {
300 /* Currently processed file's header */
301 file_header_t *file_header;
302
303+ /* List of symlink placeholders */
304+ llist_t *symlink_placeholders;
305+
306 /* Process the header component, e.g. tar -t */
307 void FAST_FUNC (*action_header)(const file_header_t *);
308
309@@ -119,15 +122,14 @@ typedef struct archive_handle_t {
310 #define ARCHIVE_RESTORE_DATE (1 << 0)
311 #define ARCHIVE_CREATE_LEADING_DIRS (1 << 1)
312 #define ARCHIVE_UNLINK_OLD (1 << 2)
313-#define ARCHIVE_EXTRACT_QUIET (1 << 3)
314-#define ARCHIVE_EXTRACT_NEWER (1 << 4)
315-#define ARCHIVE_DONT_RESTORE_OWNER (1 << 5)
316-#define ARCHIVE_DONT_RESTORE_PERM (1 << 6)
317-#define ARCHIVE_NUMERIC_OWNER (1 << 7)
318-#define ARCHIVE_O_TRUNC (1 << 8)
319-#define ARCHIVE_REMEMBER_NAMES (1 << 9)
320+#define ARCHIVE_EXTRACT_NEWER (1 << 3)
321+#define ARCHIVE_DONT_RESTORE_OWNER (1 << 4)
322+#define ARCHIVE_DONT_RESTORE_PERM (1 << 5)
323+#define ARCHIVE_NUMERIC_OWNER (1 << 6)
324+#define ARCHIVE_O_TRUNC (1 << 7)
325+#define ARCHIVE_REMEMBER_NAMES (1 << 8)
326 #if ENABLE_RPM
327-#define ARCHIVE_REPLACE_VIA_RENAME (1 << 10)
328+#define ARCHIVE_REPLACE_VIA_RENAME (1 << 9)
329 #endif
330
331
332@@ -196,7 +198,10 @@ void seek_by_jump(int fd, off_t amount) FAST_FUNC;
333 void seek_by_read(int fd, off_t amount) FAST_FUNC;
334
335 const char *strip_unsafe_prefix(const char *str) FAST_FUNC;
336-int unsafe_symlink_target(const char *target) FAST_FUNC;
337+void create_or_remember_symlink(llist_t **symlink_placeholders,
338+ const char *target,
339+ const char *linkname) FAST_FUNC;
340+void create_symlinks_from_list(llist_t *list) FAST_FUNC;
341
342 void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC;
343 const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC;
344diff --git a/testsuite/tar.tests b/testsuite/tar.tests
345index 127eeaaee..21cef49fe 100755
346--- a/testsuite/tar.tests
347+++ b/testsuite/tar.tests
348@@ -279,7 +279,7 @@ optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
349 testing "tar does not extract into symlinks" "\
350 >>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
351 " "\
352-tar: skipping unsafe symlink to '/tmp/passwd' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
353+tar: can't create symlink 'passwd' to '/tmp/passwd'
354 0
355 " \
356 "" "\
357@@ -299,7 +299,7 @@ optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
358 testing "tar -k does not extract into symlinks" "\
359 >>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
360 " "\
361-tar: skipping unsafe symlink to '/tmp/passwd' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
362+tar: can't create symlink 'passwd' to '/tmp/passwd'
363 0
364 " \
365 "" "\
366@@ -324,11 +324,11 @@ rm -rf etc usr
367 ' "\
368 etc/ssl/certs/3b2716e5.0
369 etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
370-tar: skipping unsafe symlink to '/usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
371 etc/ssl/certs/f80cc7f6.0
372 usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
373 0
374 etc/ssl/certs/3b2716e5.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
375+etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem -> /usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
376 etc/ssl/certs/f80cc7f6.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
377 " \
378 "" ""
379@@ -346,9 +346,9 @@ ls symlink/bb_test_evilfile
380 ' "\
381 anything.txt
382 symlink
383-tar: skipping unsafe symlink to '/tmp' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
384 symlink/bb_test_evilfile
385-0
386+tar: can't create symlink 'symlink' to '/tmp'
387+1
388 ls: /tmp/bb_test_evilfile: No such file or directory
389 ls: bb_test_evilfile: No such file or directory
390 symlink/bb_test_evilfile
391--
3922.17.1
393
diff --git a/meta/recipes-core/busybox/busybox_1.27.2.bb b/meta/recipes-core/busybox/busybox_1.27.2.bb
index bab29728ee..716a0650fc 100644
--- a/meta/recipes-core/busybox/busybox_1.27.2.bb
+++ b/meta/recipes-core/busybox/busybox_1.27.2.bb
@@ -43,6 +43,7 @@ SRC_URI = "http://www.busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
43 file://runlevel \ 43 file://runlevel \
44 file://makefile-libbb-race.patch \ 44 file://makefile-libbb-race.patch \
45 file://CVE-2011-5325.patch \ 45 file://CVE-2011-5325.patch \
46 file://CVE-2011-5325-fix.patch \
46 file://CVE-2017-15873.patch \ 47 file://CVE-2017-15873.patch \
47 file://busybox-CVE-2017-16544.patch \ 48 file://busybox-CVE-2017-16544.patch \
48 file://busybox-fix-lzma-segfaults.patch \ 49 file://busybox-fix-lzma-segfaults.patch \