aboutsummaryrefslogtreecommitdiff
path: root/archival/libarchive/unsafe_symlink_target.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-10 11:52:42 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-10 11:52:42 +0200
commitbc9bbeb2b81001e8731cd2ae501c8fccc8d87cc7 (patch)
tree72672bb0c187b93f1fba99012cf0c4e716214298 /archival/libarchive/unsafe_symlink_target.c
parent0cf64c8b5d86d603903397bfce87dea5a862caec (diff)
downloadbusybox-bc9bbeb2b81001e8731cd2ae501c8fccc8d87cc7.tar.gz
libarchive: do not extract unsafe symlinks unless $EXTRACT_UNSAFE_SYMLINKS=1
function old new delta unsafe_symlink_target - 147 +147 unzip_main 2711 2732 +21 copy_file 1657 1678 +21 tar_main 999 971 -28 data_extract_all 1038 984 -54 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 2/2 up/down: 189/-82) Total: 107 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'archival/libarchive/unsafe_symlink_target.c')
-rw-r--r--archival/libarchive/unsafe_symlink_target.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
new file mode 100644
index 000000000..441ba8b24
--- /dev/null
+++ b/archival/libarchive/unsafe_symlink_target.c
@@ -0,0 +1,48 @@
+/* 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"
+
+int FAST_FUNC unsafe_symlink_target(const char *target)
+{
+ const char *dot;
+
+ if (target[0] == '/') {
+ const char *var;
+ unsafe:
+ var = getenv("EXTRACT_UNSAFE_SYMLINKS");
+ if (var) {
+ if (LONE_CHAR(var, '1'))
+ return 0; /* pretend it's safe */
+ return 1; /* "UNSAFE!" */
+ }
+ bb_error_msg("skipping unsafe symlink to '%s' in archive,"
+ " set %s=1 to extract",
+ target,
+ "EXTRACT_UNSAFE_SYMLINKS"
+ );
+ /* Prevent further messages */
+ setenv("EXTRACT_UNSAFE_SYMLINKS", "0", 0);
+ return 1; /* "UNSAFE!" */
+ }
+
+ dot = target;
+ for (;;) {
+ dot = strchr(dot, '.');
+ if (!dot)
+ return 0; /* safe target */
+
+ /* Is it a path component starting with ".."? */
+ if ((dot[1] == '.')
+ && (dot == target || dot[-1] == '/')
+ /* Is it exactly ".."? */
+ && (dot[2] == '/' || dot[2] == '\0')
+ ) {
+ goto unsafe;
+ }
+ /* NB: it can even be trailing ".", should only add 1 */
+ dot += 1;
+ }
+}