mirror of
https://git.busybox.net/busybox
synced 2025-05-10 04:33:59 +02:00
Create new configure option for archival/libarchive based extractions to disallow path traversals. As this is a paranoid option and might introduce backward incompatibility, default it to no. Fixes: CVE-2023-39810 Based on the patch by Peter Kaestle <peter.kaestle@nokia.com> function old new delta data_extract_all 921 945 +24 strip_unsafe_prefix 101 102 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 25/0) Total: 25 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
39 lines
793 B
C
39 lines
793 B
C
/* vi: set sw=4 ts=4: */
|
|
/*
|
|
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
|
*/
|
|
#include "libbb.h"
|
|
#include "bb_archive.h"
|
|
|
|
const char* FAST_FUNC strip_unsafe_prefix(const char *str)
|
|
{
|
|
const char *cp = str;
|
|
while (1) {
|
|
char *cp2;
|
|
if (*cp == '/') {
|
|
cp++;
|
|
continue;
|
|
}
|
|
/* We are called lots of times.
|
|
* is_prefixed_with(cp, "../") is slower than open-coding it,
|
|
* with minimal code growth (~few bytes).
|
|
*/
|
|
if (cp[0] == '.' && cp[1] == '.' && cp[2] == '/') {
|
|
cp += 3;
|
|
continue;
|
|
}
|
|
cp2 = strstr(cp, "/../");
|
|
if (!cp2)
|
|
break;
|
|
cp = cp2 + 4;
|
|
}
|
|
if (cp != str) {
|
|
static smallint warned = 0;
|
|
if (!warned) {
|
|
warned = 1;
|
|
bb_error_msg("removing leading '%.*s' from member names",
|
|
(int)(cp - str), str);
|
|
}
|
|
}
|
|
return cp;
|
|
}
|