diff options
author | Guo Xuenan <guoxuenan@huawei.com> | 2023-09-05 10:32:07 +0800 |
---|---|---|
committer | Gao Xiang <hsiangkao@linux.alibaba.com> | 2023-09-05 10:51:52 +0800 |
commit | ac9eb76f1e02b630a29f45b8628e8e3b24d7448d (patch) | |
tree | 29de527d3414e1af1928bc12a0a6cbcac6a3d9cc | |
parent | 9776675eef7706d8f9240b50844b023ff32c49d0 (diff) | |
download | erofs-utils-ac9eb76f1e02b630a29f45b8628e8e3b24d7448d.tar.gz |
erofs-utils: fsck: refuse illegel filename
In some crafted erofs images, fsck.erofs may write outside the
destination directory, which may be used to do some dangerous things.
This commit fixes by checking all directory entry names with a '/'
character when fscking. Squashfs also met the same situation [1],
and have already fixed it here [2].
[1] https://github.com/plougher/squashfs-tools/issues/72
[2] https://github.com/plougher/squashfs-tools/commit/79b5a555058eef4e1e7ff220c344d39f8cd09646
Fixes: 412c8f908132 ("erofs-utils: fsck: add --extract=X support to extract to path X")
Reviewed-by: Guo Xuenan <guoxuenan@huawei.com>
Signed-off-by: Guo Xuenan <guoxuenan@huawei.com>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20230905023207.70314-1-hsiangkao@linux.alibaba.com
-rw-r--r-- | lib/dir.c | 17 |
1 files changed, 17 insertions, 0 deletions
@@ -4,6 +4,19 @@ #include "erofs/print.h" #include "erofs/dir.h" +/* filename should not have a '/' in the name string */ +static bool erofs_validate_filename(const char *dname, int size) +{ + char *name = (char *)dname; + + while (name - dname < size && *name != '\0') { + if (*name == '/') + return false; + ++name; + } + return true; +} + static int traverse_dirents(struct erofs_dir_context *ctx, void *dentry_blk, unsigned int lblk, unsigned int next_nameoff, unsigned int maxsize, @@ -102,6 +115,10 @@ static int traverse_dirents(struct erofs_dir_context *ctx, } break; } + } else if (fsck && + !erofs_validate_filename(de_name, de_namelen)) { + errmsg = "corrupted dirent with illegal filename"; + goto out; } ret = ctx->cb(ctx); if (ret) { |