From: lei lu llfamsec@gmail.com
stable inclusion from stable-v4.19.319 commit 7f91bd0f2941fa36449ce1a15faaa64f840d9746 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAG918 CVE: CVE-2024-41017
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit d0fa70aca54c8643248e89061da23752506ec0d4 upstream.
Add a check before visiting the members of ea to make sure each ea stays within the ealist.
Signed-off-by: lei lu llfamsec@gmail.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zhao Wenhui zhaowenhui8@huawei.com --- fs/jfs/xattr.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index e8b12e708428..37b984692ca9 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -810,7 +810,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, size_t buf_size) { struct jfs_ea_list *ealist; - struct jfs_ea *ea; + struct jfs_ea *ea, *ealist_end; struct ea_buffer ea_buf; int xattr_size; ssize_t size; @@ -830,9 +830,16 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, goto not_found;
ealist = (struct jfs_ea_list *) ea_buf.xattr; + ealist_end = END_EALIST(ealist);
/* Find the named attribute */ - for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) + for (ea = FIRST_EA(ealist); ea < ealist_end; ea = NEXT_EA(ea)) { + if (unlikely(ea + 1 > ealist_end) || + unlikely(NEXT_EA(ea) > ealist_end)) { + size = -EUCLEAN; + goto release; + } + if ((namelen == ea->namelen) && memcmp(name, ea->name, namelen) == 0) { /* Found it */ @@ -847,6 +854,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, memcpy(data, value, size); goto release; } + } not_found: size = -ENODATA; release: @@ -874,7 +882,7 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) ssize_t size = 0; int xattr_size; struct jfs_ea_list *ealist; - struct jfs_ea *ea; + struct jfs_ea *ea, *ealist_end; struct ea_buffer ea_buf;
down_read(&JFS_IP(inode)->xattr_sem); @@ -889,9 +897,16 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) goto release;
ealist = (struct jfs_ea_list *) ea_buf.xattr; + ealist_end = END_EALIST(ealist);
/* compute required size of list */ - for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { + for (ea = FIRST_EA(ealist); ea < ealist_end; ea = NEXT_EA(ea)) { + if (unlikely(ea + 1 > ealist_end) || + unlikely(NEXT_EA(ea) > ealist_end)) { + size = -EUCLEAN; + goto release; + } + if (can_list(ea)) size += name_size(ea) + 1; }