patch "staging: erofs: keep corrupted fs from crashing kernel in" added to staging-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
staging: erofs: keep corrupted fs from crashing kernel in
to my staging git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
in the staging-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 33bac912840fe64dbc15556302537dc6a17cac63 Mon Sep 17 00:00:00 2001
From: Gao Xiang <[email protected]>
Date: Fri, 29 Mar 2019 04:14:58 +0800
Subject: staging: erofs: keep corrupted fs from crashing kernel in
erofs_readdir()
After commit 419d6efc50e9, 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.
--- drivers/staging/erofs/dir.c | 45 ++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-)
drivers/staging/erofs/dir.c +25 -20
@@ -23,6 +23,21 @@ static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = { [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,void *dentry_blk,unsigned int *ofs,unsigned int nameoff,unsigned int maxsize)
@@ -33,14 +48,10 @@ static int erofs_fill_dentries(struct dir_context *ctx, de = dentry_blk + *ofs;while (de < end) {const char *de_name; -int de_namelen; +unsigned int de_namelen;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];else d_type =DT_UNKNOWN ;
@@ -48,26 +59,20 @@ static int erofs_fill_dentries(struct dir_context *ctx, nameoff =le16_to_cpu (de->nameoff); de_name = (char *)dentry_blk + nameoff; - de_namelen =unlikely (de +1 >= end) ? -/* last directory entry */ -strnlen (de_name, maxsize - nameoff) : -le16_to_cpu (de[1 ].nameoff) - nameoff; +/* the last dirent in the block? */ +if (de +1 >= end) + de_namelen =strnlen (de_name, maxsize - nameoff); +else + de_namelen =le16_to_cpu (de[1 ].nameoff) - nameoff;/* a corrupted entry is found */ -if (unlikely (de_namelen <0 )) { +if (unlikely (nameoff + de_namelen > maxsize || + de_namelen >EROFS_NAME_LEN )) {DBG_BUGON (1 );return -EIO ; } -#ifdef CONFIG_EROFS_FS_DEBUG - 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 - +debug_one_dentry (d_type, de_name, de_namelen);if (!dir_emit (ctx, de_name, de_namelen,le64_to_cpu (de->nid), d_type))/* stopped by some reason */
Signature · 1 line
2.21.0