aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuo Xuenan <guoxuenan@huawei.com>2023-09-05 10:32:07 +0800
committerGao Xiang <hsiangkao@linux.alibaba.com>2023-09-05 10:51:52 +0800
commitac9eb76f1e02b630a29f45b8628e8e3b24d7448d (patch)
tree29de527d3414e1af1928bc12a0a6cbcac6a3d9cc
parent9776675eef7706d8f9240b50844b023ff32c49d0 (diff)
downloaderofs-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.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/lib/dir.c b/lib/dir.c
index fff0bc0..1223cbc 100644
--- a/lib/dir.c
+++ b/lib/dir.c
@@ -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) {