FAILED: patch "[PATCH] erofs: fix the out-of-bounds nameoff handling for trailing" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x d18a3b5d337fa412a38e776e6b4b857a58836575
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026050132-undercoat-undercoat-0f5b@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d18a3b5d337fa412a38e776e6b4b857a58836575 Mon Sep 17 00:00:00 2001
From: Gao Xiang <[email protected]>
Date: Tue, 21 Apr 2026 15:59:52 +0800
Subject: [PATCH] erofs: fix the out-of-bounds nameoff handling for trailing
dirents
Currently we already have boundary-checks for nameoffs, but the trailing dirents are special since the namelens are calculated with strnlen() with unchecked nameoffs.
If a crafted EROFS has a trailing dirent with nameoff >= maxsize, maxsize - nameoff can underflow, causing strnlen() to read past the directory block.
nameoff0 should also be verified to be a multiple of sizeof(struct erofs_dirent) as well [1].
[1] https://sashiko.dev/#/patchset/20260416063511.3173774-1-hsiangkao%40linux.alibaba.com
fs/erofs/dir.c +15 -13
@@ -19,20 +19,18 @@ static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx,const char *de_name = (char *)dentry_blk + nameoff;unsigned int de_namelen; -/* the last dirent in the block? */ -if (de +1 >= end) - de_namelen =strnlen (de_name, maxsize - nameoff); -else +/* non-trailing dirent in the directory block? */ +if (de +1 < end) de_namelen =le16_to_cpu (de[1 ].nameoff) - nameoff; +else if (maxsize <= nameoff) + goto err_bogus; +else + de_namelen =strnlen (de_name, maxsize - nameoff); -/* a corrupted entry is found */ -if (nameoff + de_namelen > maxsize || - de_namelen >EROFS_NAME_LEN ) { -erofs_err (dir->i_sb,"bogus dirent @ nid %llu" , -EROFS_I (dir)->nid); -DBG_BUGON (1 ); -return -EFSCORRUPTED ; - } +/* a corrupted entry is found (including negative namelen) */ +if (!in_range32 (de_namelen,1 ,EROFS_NAME_LEN ) || + nameoff + de_namelen > maxsize) + goto err_bogus; if (!dir_emit(ctx, de_name, de_namelen, erofs_nid_to_ino64(EROFS_SB(dir->i_sb),
@@ -42,6 +40,10 @@ static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, ctx->pos +=sizeof (struct erofs_dirent ); }return 0 ; +err_bogus: +erofs_err (dir->i_sb,"bogus dirent @ nid %llu" ,EROFS_I (dir)->nid); +DBG_BUGON (1 ); +return -EFSCORRUPTED ; }static int erofs_readdir (struct file *f,struct dir_context *ctx)
@@ -88,7 +90,7 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) } nameoff =le16_to_cpu (de->nameoff); -if (nameoff <sizeof (struct erofs_dirent ) || nameoff >= bsz) { +if (!nameoff || nameoff >= bsz || (nameoff %sizeof (*de))) {erofs_err (sb,"invalid de[0].nameoff %u @ nid %llu" , nameoff,EROFS_I (dir)->nid); err = -EFSCORRUPTED ;
Sasha Levin
maintainerPATCH 1/1 erofs: fix the out-of-bounds nameoff handling for trailing dirents
From: Gao Xiang <[email protected]>
[ Upstream commit d18a3b5d337fa412a38e776e6b4b857a58836575 ]
Currently we already have boundary-checks for nameoffs, but the trailing dirents are special since the namelens are calculated with strnlen() with unchecked nameoffs.
If a crafted EROFS has a trailing dirent with nameoff >= maxsize, maxsize - nameoff can underflow, causing strnlen() to read past the directory block.
nameoff0 should also be verified to be a multiple of sizeof(struct erofs_dirent) as well [1].
[1] https://sashiko.dev/#/patchset/20260416063511.3173774-1-hsiangkao%40linux.alibaba.com
--- fs/erofs/dir.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-)
fs/erofs/dir.c +16 -14
@@ -37,20 +37,18 @@ static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, nameoff =le16_to_cpu (de->nameoff); de_name = (char *)dentry_blk + nameoff; -/* the last dirent in the block? */ -if (de +1 >= end) - de_namelen =strnlen (de_name, maxsize - nameoff); -else +/* non-trailing dirent in the directory block? */ +if (de +1 < end) de_namelen =le16_to_cpu (de[1 ].nameoff) - nameoff; +else if (maxsize <= nameoff) + goto err_bogus; +else + de_namelen =strnlen (de_name, maxsize - nameoff); -/* a corrupted entry is found */ -if (nameoff + de_namelen > maxsize || - de_namelen >EROFS_NAME_LEN ) { -erofs_err (dir->i_sb,"bogus dirent @ nid %llu" , -EROFS_I (dir)->nid); -DBG_BUGON (1 ); -return -EFSCORRUPTED ; - } +/* a corrupted entry is found (including negative namelen) */ +if (!in_range32 (de_namelen,1 ,EROFS_NAME_LEN ) || + nameoff + de_namelen > maxsize) + goto err_bogus;debug_one_dentry (d_type, de_name, de_namelen); if (!dir_emit(ctx, de_name, de_namelen,
@@ -62,6 +60,10 @@ static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, } *ofs = maxsize;return 0 ; +err_bogus: +erofs_err (dir->i_sb,"bogus dirent @ nid %llu" ,EROFS_I (dir)->nid); +DBG_BUGON (1 ); +return -EFSCORRUPTED ; }static int erofs_readdir (struct file *f,struct dir_context *ctx)
@@ -95,8 +97,8 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) nameoff =le16_to_cpu (de->nameoff); -if (nameoff <sizeof (struct erofs_dirent ) || - nameoff >=PAGE_SIZE ) { +if (!nameoff || nameoff >=PAGE_SIZE || + (nameoff %sizeof (struct erofs_dirent ))) {erofs_err (dir->i_sb,"invalid de[0].nameoff %u @ nid %llu" , nameoff,EROFS_I (dir)->nid);
Signature · 1 line
2.53.0
Re: [PATCH 5.15.y] erofs: fix the out-of-bounds nameoff handling for trailing dirents
Quoted 17 lines · Sasha Levin
From: Gao Xiang <[email protected]>
[ Upstream commit
d18a3b5d337fa412a38e776e6b4b857a58836575]Currently we already have boundary-checks for nameoffs, but the trailing dirents are special since the namelens are calculated with
strnlen()with unchecked nameoffs.If a crafted EROFS has a trailing dirent with nameoff >= maxsize, maxsize - nameoff can underflow, causing
strnlen()to read past the directory block.nameoff0 should also be verified to be a multiple of
sizeof(struct erofs_dirent)as well [1].[1] https://sashiko.dev/#/patchset/20260416063511.3173774-1-hsiangkao%40linux.alibaba.com
Quoted 10 lines
Fixes 3aa8ec716e52 ("staging: erofs: add directory operations")Fixes 33bac912840f ("staging: erofs: keep corrupted fs from crashing kernel in erofs_readdir()")Reported-by Yuhao Jiang <[email protected]>Reported-by Junrui Luo <[email protected]>Signed-off-by Gao Xiang <[email protected]>Reviewed-by Chao Yu <[email protected]>[ replaced upstream `bsz` with `PAGE_SIZE` and `sizeof(*de)` with `sizeof(struct erofs_dirent)` ]Signed-off-by Sasha Levin <[email protected]>
Looks good to me.
Thanks,
Gao Xiang