summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/common.h1
-rw-r--r--lib/common/Makemodule.am1
-rw-r--r--lib/common/filename_sane.c26
-rw-r--r--tar/sqfs2tar.c10
-rw-r--r--unpack/fill_files.c6
-rw-r--r--unpack/restore_fstree.c9
6 files changed, 53 insertions, 0 deletions
diff --git a/include/common.h b/include/common.h
index 17d709e..ba42054 100644
--- a/include/common.h
+++ b/include/common.h
@@ -140,6 +140,7 @@ void sqfs_writer_cleanup(sqfs_writer_t *sqfs);
void sqfs_perror(const char *file, const char *action, int error_code);
+bool is_filename_sane(const char *name);
/*
A wrapper around mkdir() that behaves like 'mkdir -p'. It tries to create
diff --git a/lib/common/Makemodule.am b/lib/common/Makemodule.am
index db366af..4f4562b 100644
--- a/lib/common/Makemodule.am
+++ b/lib/common/Makemodule.am
@@ -6,5 +6,6 @@ libcommon_a_SOURCES += lib/common/data_writer.c include/common.h
libcommon_a_SOURCES += lib/common/get_path.c lib/common/io_stdin.c
libcommon_a_SOURCES += lib/common/writer.c lib/common/perror.c
libcommon_a_SOURCES += lib/common/dirstack.c lib/common/mkdir_p.c
+libcommon_a_SOURCES += lib/common/filename_sane.c
noinst_LIBRARIES += libcommon.a
diff --git a/lib/common/filename_sane.c b/lib/common/filename_sane.c
new file mode 100644
index 0000000..6b497c3
--- /dev/null
+++ b/lib/common/filename_sane.c
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * filename_sane.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "common.h"
+
+bool is_filename_sane(const char *name)
+{
+ if (name[0] == '.') {
+ if (name[1] == '\0')
+ return false;
+
+ if (name[1] == '.' && name[2] == '\0')
+ return false;
+ }
+
+ while (*name != '\0') {
+ if (*name == '/')
+ return false;
+ ++name;
+ }
+
+ return true;
+}
diff --git a/tar/sqfs2tar.c b/tar/sqfs2tar.c
index 3e64b45..1e05cd4 100644
--- a/tar/sqfs2tar.c
+++ b/tar/sqfs2tar.c
@@ -266,6 +266,16 @@ static int write_tree_dfs(const sqfs_tree_node_t *n)
if (n->parent == NULL && S_ISDIR(n->inode->base.mode))
goto skip_hdr;
+ if (!is_filename_sane((const char *)n->name)) {
+ fprintf(stderr, "Found a file named '%s', skipping.\n",
+ n->name);
+ if (dont_skip) {
+ fputs("Not allowed to skip files, aborting!\n", stderr);
+ return -1;
+ }
+ return 0;
+ }
+
name = sqfs_tree_node_get_path(n);
if (name == NULL) {
perror("resolving tree node path");
diff --git a/unpack/fill_files.c b/unpack/fill_files.c
index 481c398..e6444b2 100644
--- a/unpack/fill_files.c
+++ b/unpack/fill_files.c
@@ -114,6 +114,12 @@ static void clear_file_list(void)
static int gen_file_list_dfs(const sqfs_tree_node_t *n)
{
+ if (!is_filename_sane((const char *)n->name)) {
+ fprintf(stderr, "Found an entry named '%s', skipping.\n",
+ n->name);
+ return 0;
+ }
+
if (S_ISREG(n->inode->base.mode))
return add_file(n);
diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c
index 1dadce4..6995d47 100644
--- a/unpack/restore_fstree.c
+++ b/unpack/restore_fstree.c
@@ -12,6 +12,12 @@ static int create_node(const sqfs_tree_node_t *n, int flags)
int fd, ret;
char *name;
+ if (!is_filename_sane((const char *)n->name)) {
+ fprintf(stderr, "Found an entry named '%s', skipping.\n",
+ n->name);
+ return 0;
+ }
+
if (!(flags & UNPACK_QUIET)) {
name = sqfs_tree_node_get_path(n);
if (name != NULL) {
@@ -154,6 +160,9 @@ static int set_attribs(sqfs_xattr_reader_t *xattr,
{
const sqfs_tree_node_t *c;
+ if (!is_filename_sane((const char *)n->name))
+ return 0;
+
if (S_ISDIR(n->inode->base.mode)) {
if (pushd((const char *)n->name))
return -1;