diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-10-07 15:54:41 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-10-07 15:59:07 +0200 |
commit | e21bf0b60c1b9d67fe7553105b6440c3fce7c0bb (patch) | |
tree | 168f84bbf1d741e624a339074debcde441b2e2eb | |
parent | c973bcc1039b64ec00acaf8e8d61b9f5229da56f (diff) |
Do an explicit "is filename sane" check
Until now, filenames containing '/' or being equal to '..' or '.' where
not handled explicitly, because they are canonicalized later, which
will then fail.
This commit adds an explicit check to make those fail immediately with
a clear, specific error message.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-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; |