mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
staging: erofs: keep corrupted fs from crashing kernel in erofs_readdir()
After commit419d6efc50, 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:3aa8ec716e("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>
This commit is contained in:
parent
9498da46d1
commit
33bac91284
|
|
@ -23,6 +23,21 @@ static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = {
|
||||||
[EROFS_FT_SYMLINK] = DT_LNK,
|
[EROFS_FT_SYMLINK] = DT_LNK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void debug_one_dentry(unsigned char d_type, const char *de_name,
|
||||||
|
unsigned int de_namelen)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_EROFS_FS_DEBUG
|
||||||
|
/* since the on-disk name could not have the trailing '\0' */
|
||||||
|
unsigned char dbg_namebuf[EROFS_NAME_LEN + 1];
|
||||||
|
|
||||||
|
memcpy(dbg_namebuf, de_name, de_namelen);
|
||||||
|
dbg_namebuf[de_namelen] = '\0';
|
||||||
|
|
||||||
|
debugln("found dirent %s de_len %u d_type %d", dbg_namebuf,
|
||||||
|
de_namelen, d_type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int erofs_fill_dentries(struct dir_context *ctx,
|
static int erofs_fill_dentries(struct dir_context *ctx,
|
||||||
void *dentry_blk, unsigned int *ofs,
|
void *dentry_blk, unsigned int *ofs,
|
||||||
unsigned int nameoff, unsigned int maxsize)
|
unsigned int nameoff, unsigned int maxsize)
|
||||||
|
|
@ -33,14 +48,10 @@ static int erofs_fill_dentries(struct dir_context *ctx,
|
||||||
de = dentry_blk + *ofs;
|
de = dentry_blk + *ofs;
|
||||||
while (de < end) {
|
while (de < end) {
|
||||||
const char *de_name;
|
const char *de_name;
|
||||||
int de_namelen;
|
unsigned int de_namelen;
|
||||||
unsigned char d_type;
|
unsigned char d_type;
|
||||||
#ifdef CONFIG_EROFS_FS_DEBUG
|
|
||||||
unsigned int dbg_namelen;
|
|
||||||
unsigned char dbg_namebuf[EROFS_NAME_LEN];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (unlikely(de->file_type < EROFS_FT_MAX))
|
if (de->file_type < EROFS_FT_MAX)
|
||||||
d_type = erofs_filetype_table[de->file_type];
|
d_type = erofs_filetype_table[de->file_type];
|
||||||
else
|
else
|
||||||
d_type = DT_UNKNOWN;
|
d_type = DT_UNKNOWN;
|
||||||
|
|
@ -48,26 +59,20 @@ static int erofs_fill_dentries(struct dir_context *ctx,
|
||||||
nameoff = le16_to_cpu(de->nameoff);
|
nameoff = le16_to_cpu(de->nameoff);
|
||||||
de_name = (char *)dentry_blk + nameoff;
|
de_name = (char *)dentry_blk + nameoff;
|
||||||
|
|
||||||
de_namelen = unlikely(de + 1 >= end) ?
|
/* the last dirent in the block? */
|
||||||
/* last directory entry */
|
if (de + 1 >= end)
|
||||||
strnlen(de_name, maxsize - nameoff) :
|
de_namelen = strnlen(de_name, maxsize - nameoff);
|
||||||
le16_to_cpu(de[1].nameoff) - nameoff;
|
else
|
||||||
|
de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
|
||||||
|
|
||||||
/* a corrupted entry is found */
|
/* a corrupted entry is found */
|
||||||
if (unlikely(de_namelen < 0)) {
|
if (unlikely(nameoff + de_namelen > maxsize ||
|
||||||
|
de_namelen > EROFS_NAME_LEN)) {
|
||||||
DBG_BUGON(1);
|
DBG_BUGON(1);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EROFS_FS_DEBUG
|
debug_one_dentry(d_type, de_name, de_namelen);
|
||||||
dbg_namelen = min(EROFS_NAME_LEN - 1, de_namelen);
|
|
||||||
memcpy(dbg_namebuf, de_name, dbg_namelen);
|
|
||||||
dbg_namebuf[dbg_namelen] = '\0';
|
|
||||||
|
|
||||||
debugln("%s, found de_name %s de_len %d d_type %d", __func__,
|
|
||||||
dbg_namebuf, de_namelen, d_type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!dir_emit(ctx, de_name, de_namelen,
|
if (!dir_emit(ctx, de_name, de_namelen,
|
||||||
le64_to_cpu(de->nid), d_type))
|
le64_to_cpu(de->nid), d_type))
|
||||||
/* stopped by some reason */
|
/* stopped by some reason */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user