diff options
-rw-r--r-- | include/common.h | 1 | ||||
-rw-r--r-- | lib/common/Makemodule.am | 1 | ||||
-rw-r--r-- | lib/common/filename_sane.c | 26 | ||||
-rw-r--r-- | tar/sqfs2tar.c | 10 | ||||
-rw-r--r-- | unpack/fill_files.c | 6 | ||||
-rw-r--r-- | unpack/restore_fstree.c | 9 |
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; |