diff options
author | lei lu <llfamsec@gmail.com> | 2024-05-28 20:30:40 +0200 |
---|---|---|
committer | Dave Kleikamp <dave.kleikamp@oracle.com> | 2024-06-27 15:43:07 +0200 |
commit | d0fa70aca54c8643248e89061da23752506ec0d4 (patch) | |
tree | b27ab203cdd4e8c1223b70d0d97b52cfc0071e04 /fs/jfs | |
parent | jfs: Fix shift-out-of-bounds in dbDiscardAG (diff) | |
download | linux-d0fa70aca54c8643248e89061da23752506ec0d4.tar.xz linux-d0fa70aca54c8643248e89061da23752506ec0d4.zip |
jfs: don't walk off the end of ealist
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>
Diffstat (limited to 'fs/jfs')
-rw-r--r-- | fs/jfs/xattr.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 0fb7afac298e..ab9b85ce7ff7 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -795,7 +795,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; @@ -815,9 +815,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 */ @@ -832,6 +839,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, memcpy(data, value, size); goto release; } + } not_found: size = -ENODATA; release: @@ -859,7 +867,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); @@ -874,9 +882,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; } |