]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
jfs: don't walk off the end of ealist
authorlei lu <llfamsec@gmail.com>
Tue, 28 May 2024 18:30:40 +0000 (02:30 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 27 Jul 2024 08:33:44 +0000 (10:33 +0200)
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>
fs/jfs/xattr.c

index e8b12e708428a9c8bca488d0e8d2e7d63ec97b3a..37b984692ca901cc8589b19a8e96cca42c0faa57 100644 (file)
@@ -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;
        }