Skip to content

Commit 33bac91

Browse files
Gao Xianggregkh
authored andcommitted
staging: erofs: keep corrupted fs from crashing kernel in erofs_readdir()
After commit 419d6ef, kernel cannot be crashed in the namei path. However, corrupted nameoff can do harm in the process of readdir for scenerios without dm-verity as well. Fix it now. Fixes: 3aa8ec7 ("staging: erofs: add directory operations") Cc: <stable@vger.kernel.org> # 4.19+ Signed-off-by: Gao Xiang <gaoxiang25@huawei.com> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 9498da4 commit 33bac91

File tree

1 file changed

+25
-20
lines changed
  • drivers/staging/erofs

1 file changed

+25
-20
lines changed

drivers/staging/erofs/dir.c

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = {
2323
[EROFS_FT_SYMLINK] = DT_LNK,
2424
};
2525

26+
static void debug_one_dentry(unsigned char d_type, const char *de_name,
27+
unsigned int de_namelen)
28+
{
29+
#ifdef CONFIG_EROFS_FS_DEBUG
30+
/* since the on-disk name could not have the trailing '\0' */
31+
unsigned char dbg_namebuf[EROFS_NAME_LEN + 1];
32+
33+
memcpy(dbg_namebuf, de_name, de_namelen);
34+
dbg_namebuf[de_namelen] = '\0';
35+
36+
debugln("found dirent %s de_len %u d_type %d", dbg_namebuf,
37+
de_namelen, d_type);
38+
#endif
39+
}
40+
2641
static int erofs_fill_dentries(struct dir_context *ctx,
2742
void *dentry_blk, unsigned int *ofs,
2843
unsigned int nameoff, unsigned int maxsize)
@@ -33,41 +48,31 @@ static int erofs_fill_dentries(struct dir_context *ctx,
3348
de = dentry_blk + *ofs;
3449
while (de < end) {
3550
const char *de_name;
36-
int de_namelen;
51+
unsigned int de_namelen;
3752
unsigned char d_type;
38-
#ifdef CONFIG_EROFS_FS_DEBUG
39-
unsigned int dbg_namelen;
40-
unsigned char dbg_namebuf[EROFS_NAME_LEN];
41-
#endif
4253

43-
if (unlikely(de->file_type < EROFS_FT_MAX))
54+
if (de->file_type < EROFS_FT_MAX)
4455
d_type = erofs_filetype_table[de->file_type];
4556
else
4657
d_type = DT_UNKNOWN;
4758

4859
nameoff = le16_to_cpu(de->nameoff);
4960
de_name = (char *)dentry_blk + nameoff;
5061

51-
de_namelen = unlikely(de + 1 >= end) ?
52-
/* last directory entry */
53-
strnlen(de_name, maxsize - nameoff) :
54-
le16_to_cpu(de[1].nameoff) - nameoff;
62+
/* the last dirent in the block? */
63+
if (de + 1 >= end)
64+
de_namelen = strnlen(de_name, maxsize - nameoff);
65+
else
66+
de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
5567

5668
/* a corrupted entry is found */
57-
if (unlikely(de_namelen < 0)) {
69+
if (unlikely(nameoff + de_namelen > maxsize ||
70+
de_namelen > EROFS_NAME_LEN)) {
5871
DBG_BUGON(1);
5972
return -EIO;
6073
}
6174

62-
#ifdef CONFIG_EROFS_FS_DEBUG
63-
dbg_namelen = min(EROFS_NAME_LEN - 1, de_namelen);
64-
memcpy(dbg_namebuf, de_name, dbg_namelen);
65-
dbg_namebuf[dbg_namelen] = '\0';
66-
67-
debugln("%s, found de_name %s de_len %d d_type %d", __func__,
68-
dbg_namebuf, de_namelen, d_type);
69-
#endif
70-
75+
debug_one_dentry(d_type, de_name, de_namelen);
7176
if (!dir_emit(ctx, de_name, de_namelen,
7277
le64_to_cpu(de->nid), d_type))
7378
/* stopped by some reason */

0 commit comments

Comments
 (0)