aboutsummaryrefslogtreecommitdiffstats
path: root/main/squashfs-tools/0004-Unsquashfs-additional-write-outside-destination-dire.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/squashfs-tools/0004-Unsquashfs-additional-write-outside-destination-dire.patch')
-rw-r--r--main/squashfs-tools/0004-Unsquashfs-additional-write-outside-destination-dire.patch320
1 files changed, 0 insertions, 320 deletions
diff --git a/main/squashfs-tools/0004-Unsquashfs-additional-write-outside-destination-dire.patch b/main/squashfs-tools/0004-Unsquashfs-additional-write-outside-destination-dire.patch
deleted file mode 100644
index 662fc62c0fd..00000000000
--- a/main/squashfs-tools/0004-Unsquashfs-additional-write-outside-destination-dire.patch
+++ /dev/null
@@ -1,320 +0,0 @@
-From 6bfefb7f73e183d1b6b4cd21a57d478f93e034ab Mon Sep 17 00:00:00 2001
-From: Phillip Lougher <phillip@squashfs.org.uk>
-Date: Sun, 12 Sep 2021 23:50:06 +0100
-Subject: [PATCH 4/5] Unsquashfs: additional write outside destination
- directory exploit fix
-
-An issue on github (https://github.com/plougher/squashfs-tools/issues/72)
-showed how some specially crafted Squashfs filesystems containing
-invalid file names (with '/' and '..') can cause Unsquashfs to write
-files outside of the destination directory.
-
-Since then it has been shown that specially crafted Squashfs filesystems
-that contain a symbolic link pointing outside of the destination directory,
-coupled with an identically named file within the same directory, can
-cause Unsquashfs to write files outside of the destination directory.
-
-Specifically the symbolic link produces a pathname pointing outside
-of the destination directory, which is then followed when writing the
-duplicate identically named file within the directory.
-
-This commit fixes this exploit by explictly checking for duplicate
-filenames within a directory. As directories in v2.1, v3.x, and v4.0
-filesystems are sorted, this is achieved by checking for consecutively
-identical filenames. Additionally directories are checked to
-ensure they are sorted, to avoid attempts to evade the duplicate
-check.
-
-Version 1.x and 2.0 filesystems (where the directories were unsorted)
-are sorted and then the above duplicate filename check is applied.
-
-Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
----
- squashfs-tools/Makefile | 6 +-
- squashfs-tools/unsquash-1.c | 6 ++
- squashfs-tools/unsquash-12.c | 110 +++++++++++++++++++++++++++++++++
- squashfs-tools/unsquash-1234.c | 21 +++++++
- squashfs-tools/unsquash-2.c | 16 +++++
- squashfs-tools/unsquash-3.c | 6 ++
- squashfs-tools/unsquash-4.c | 6 ++
- squashfs-tools/unsquashfs.h | 4 ++
- 8 files changed, 173 insertions(+), 2 deletions(-)
- create mode 100644 squashfs-tools/unsquash-12.c
-
-diff --git a/squashfs-tools/Makefile b/squashfs-tools/Makefile
-index 5795d0d..417f2ba 100755
---- a/squashfs-tools/Makefile
-+++ b/squashfs-tools/Makefile
-@@ -160,8 +160,8 @@ MKSQUASHFS_OBJS = mksquashfs.o read_fs.o action.o swap.o pseudo.o compressor.o \
- caches-queues-lists.o reader.o tar.o
-
- UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \
-- unsquash-4.o unsquash-123.o unsquash-34.o unsquash-1234.o swap.o \
-- compressor.o unsquashfs_info.o
-+ unsquash-4.o unsquash-123.o unsquash-34.o unsquash-1234.o unsquash-12.o \
-+ swap.o compressor.o unsquashfs_info.o
-
- CFLAGS ?= -O2
- CFLAGS += $(EXTRA_CFLAGS) $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 \
-@@ -393,6 +393,8 @@ unsquash-34.o: unsquashfs.h unsquash-34.c unsquashfs_error.h
-
- unsquash-1234.o: unsquash-1234.c unsquashfs_error.h
-
-+unsquash-1234.o: unsquash-12.c
-+
- unsquashfs_xattr.o: unsquashfs_xattr.c unsquashfs.h squashfs_fs.h xattr.h unsquashfs_error.h
-
- unsquashfs_info.o: unsquashfs.h squashfs_fs.h unsquashfs_error.h
-diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c
-index b604434..88866fc 100644
---- a/squashfs-tools/unsquash-1.c
-+++ b/squashfs-tools/unsquash-1.c
-@@ -370,6 +370,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
- }
- }
-
-+ /* check directory for duplicate names. Need to sort directory first */
-+ sort_directory(dir);
-+ if(check_directory(dir) == FALSE) {
-+ ERROR("File system corrupted: directory has duplicate names\n");
-+ goto corrupted;
-+ }
- return dir;
-
- corrupted:
-diff --git a/squashfs-tools/unsquash-12.c b/squashfs-tools/unsquash-12.c
-new file mode 100644
-index 0000000..61bf128
---- /dev/null
-+++ b/squashfs-tools/unsquash-12.c
-@@ -0,0 +1,110 @@
-+/*
-+ * Unsquash a squashfs filesystem. This is a highly compressed read only
-+ * filesystem.
-+ *
-+ * Copyright (c) 2021
-+ * Phillip Lougher <phillip@squashfs.org.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2,
-+ * or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * unsquash-12.c
-+ *
-+ * Helper functions used by unsquash-1 and unsquash-2.
-+ */
-+
-+#include "unsquashfs.h"
-+
-+/*
-+ * Bottom up linked list merge sort.
-+ *
-+ */
-+void sort_directory(struct dir *dir)
-+{
-+ struct dir_ent *cur, *l1, *l2, *next;
-+ int len1, len2, stride = 1;
-+
-+ if(dir->dir_count < 2)
-+ return;
-+
-+ /*
-+ * We can consider our linked-list to be made up of stride length
-+ * sublists. Eacn iteration around this loop merges adjacent
-+ * stride length sublists into larger 2*stride sublists. We stop
-+ * when stride becomes equal to the entire list.
-+ *
-+ * Initially stride = 1 (by definition a sublist of 1 is sorted), and
-+ * these 1 element sublists are merged into 2 element sublists, which
-+ * are then merged into 4 element sublists and so on.
-+ */
-+ do {
-+ l2 = dir->dirs; /* head of current linked list */
-+ cur = NULL; /* empty output list */
-+
-+ /*
-+ * Iterate through the linked list, merging adjacent sublists.
-+ * On each interation l2 points to the next sublist pair to be
-+ * merged (if there's only one sublist left this is simply added
-+ * to the output list)
-+ */
-+ while(l2) {
-+ l1 = l2;
-+ for(len1 = 0; l2 && len1 < stride; len1 ++, l2 = l2->next);
-+ len2 = stride;
-+
-+ /*
-+ * l1 points to first sublist.
-+ * l2 points to second sublist.
-+ * Merge them onto the output list
-+ */
-+ while(len1 && l2 && len2) {
-+ if(strcmp(l1->name, l2->name) <= 0) {
-+ next = l1;
-+ l1 = l1->next;
-+ len1 --;
-+ } else {
-+ next = l2;
-+ l2 = l2->next;
-+ len2 --;
-+ }
-+
-+ if(cur) {
-+ cur->next = next;
-+ cur = next;
-+ } else
-+ dir->dirs = cur = next;
-+ }
-+ /*
-+ * One sublist is now empty, copy the other one onto the
-+ * output list
-+ */
-+ for(; len1; len1 --, l1 = l1->next) {
-+ if(cur) {
-+ cur->next = l1;
-+ cur = l1;
-+ } else
-+ dir->dirs = cur = l1;
-+ }
-+ for(; l2 && len2; len2 --, l2 = l2->next) {
-+ if(cur) {
-+ cur->next = l2;
-+ cur = l2;
-+ } else
-+ dir->dirs = cur = l2;
-+ }
-+ }
-+ cur->next = NULL;
-+ stride = stride << 1;
-+ } while(stride < dir->dir_count);
-+}
-diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c
-index e389f8d..98a81ed 100644
---- a/squashfs-tools/unsquash-1234.c
-+++ b/squashfs-tools/unsquash-1234.c
-@@ -72,3 +72,24 @@ void squashfs_closedir(struct dir *dir)
-
- free(dir);
- }
-+
-+
-+/*
-+ * Check directory for duplicate names. As the directory should be sorted,
-+ * duplicates will be consecutive. Obviously we also need to check if the
-+ * directory has been deliberately unsorted, to evade this check.
-+ */
-+int check_directory(struct dir *dir)
-+{
-+ int i;
-+ struct dir_ent *ent;
-+
-+ if(dir->dir_count < 2)
-+ return TRUE;
-+
-+ for(ent = dir->dirs, i = 0; i < dir->dir_count - 1; ent = ent->next, i++)
-+ if(strcmp(ent->name, ent->next->name) >= 0)
-+ return FALSE;
-+
-+ return TRUE;
-+}
-diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c
-index 956f96f..0e36f7d 100644
---- a/squashfs-tools/unsquash-2.c
-+++ b/squashfs-tools/unsquash-2.c
-@@ -29,6 +29,7 @@
- static squashfs_fragment_entry_2 *fragment_table;
- static unsigned int *uid_table, *guid_table;
- static squashfs_operations ops;
-+static int needs_sorting = FALSE;
-
-
- static void read_block_list(unsigned int *block_list, long long start,
-@@ -463,6 +464,17 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
- }
- }
-
-+ if(needs_sorting)
-+ sort_directory(dir);
-+
-+ /* check directory for duplicate names and sorting */
-+ if(check_directory(dir) == FALSE) {
-+ if(needs_sorting)
-+ ERROR("File system corrupted: directory has duplicate names\n");
-+ else
-+ ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
-+ goto corrupted;
-+ }
- return dir;
-
- corrupted:
-@@ -596,6 +608,10 @@ int read_super_2(squashfs_operations **s_ops, void *s)
- * 2.x filesystems use gzip compression.
- */
- comp = lookup_compressor("gzip");
-+
-+ if(sBlk_3->s_minor == 0)
-+ needs_sorting = TRUE;
-+
- return TRUE;
- }
-
-diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c
-index 835a574..0123562 100644
---- a/squashfs-tools/unsquash-3.c
-+++ b/squashfs-tools/unsquash-3.c
-@@ -497,6 +497,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
- }
- }
-
-+ /* check directory for duplicate names and sorting */
-+ if(check_directory(dir) == FALSE) {
-+ ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
-+ goto corrupted;
-+ }
-+
- return dir;
-
- corrupted:
-diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c
-index fd7ab6c..7443d55 100644
---- a/squashfs-tools/unsquash-4.c
-+++ b/squashfs-tools/unsquash-4.c
-@@ -434,6 +434,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
- }
- }
-
-+ /* check directory for duplicate names and sorting */
-+ if(check_directory(dir) == FALSE) {
-+ ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
-+ goto corrupted;
-+ }
-+
- return dir;
-
- corrupted:
-diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h
-index f8cf78c..bf2a80d 100644
---- a/squashfs-tools/unsquashfs.h
-+++ b/squashfs-tools/unsquashfs.h
-@@ -293,4 +293,8 @@ extern long long *alloc_index_table(int);
- /* unsquash-1234.c */
- extern int check_name(char *, int);
- extern void squashfs_closedir(struct dir *);
-+extern int check_directory(struct dir *);
-+
-+/* unsquash-12.c */
-+extern void sort_directory(struct dir *);
- #endif
---
-2.33.1
-