Merge branch 'address-masking'
[linux-2.6-microblaze.git] / fs / jfs / xattr.c
index 8577ad4..0fb05e3 100644 (file)
@@ -434,6 +434,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
        int rc;
        int quota_allocation = 0;
 
        int rc;
        int quota_allocation = 0;
 
+       memset(&ea_buf->new_ea, 0, sizeof(ea_buf->new_ea));
+
        /* When fsck.jfs clears a bad ea, it doesn't clear the size */
        if (ji->ea.flag == 0)
                ea_size = 0;
        /* When fsck.jfs clears a bad ea, it doesn't clear the size */
        if (ji->ea.flag == 0)
                ea_size = 0;
@@ -557,9 +559,11 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 
       size_check:
        if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
 
       size_check:
        if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
+               int size = min_t(int, EALIST_SIZE(ea_buf->xattr), ea_size);
+
                printk(KERN_ERR "ea_get: invalid extended attribute\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
                printk(KERN_ERR "ea_get: invalid extended attribute\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
-                                    ea_buf->xattr, ea_size, 1);
+                                    ea_buf->xattr, size, 1);
                ea_release(inode, ea_buf);
                rc = -EIO;
                goto clean_up;
                ea_release(inode, ea_buf);
                rc = -EIO;
                goto clean_up;
@@ -795,7 +799,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
                       size_t buf_size)
 {
        struct jfs_ea_list *ealist;
                       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;
        struct ea_buffer ea_buf;
        int xattr_size;
        ssize_t size;
@@ -815,9 +819,16 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
                goto not_found;
 
        ealist = (struct jfs_ea_list *) ea_buf.xattr;
                goto not_found;
 
        ealist = (struct jfs_ea_list *) ea_buf.xattr;
+       ealist_end = END_EALIST(ealist);
 
        /* Find the named attribute */
 
        /* 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 */
                if ((namelen == ea->namelen) &&
                    memcmp(name, ea->name, namelen) == 0) {
                        /* Found it */
@@ -832,6 +843,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
                        memcpy(data, value, size);
                        goto release;
                }
                        memcpy(data, value, size);
                        goto release;
                }
+       }
       not_found:
        size = -ENODATA;
       release:
       not_found:
        size = -ENODATA;
       release:
@@ -859,7 +871,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;
        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);
        struct ea_buffer ea_buf;
 
        down_read(&JFS_IP(inode)->xattr_sem);
@@ -874,9 +886,16 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
                goto release;
 
        ealist = (struct jfs_ea_list *) ea_buf.xattr;
                goto release;
 
        ealist = (struct jfs_ea_list *) ea_buf.xattr;
+       ealist_end = END_EALIST(ealist);
 
        /* compute required size of list */
 
        /* 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;
        }
                if (can_list(ea))
                        size += name_size(ea) + 1;
        }
@@ -985,7 +1004,7 @@ static const struct xattr_handler jfs_trusted_xattr_handler = {
        .set = jfs_xattr_set,
 };
 
        .set = jfs_xattr_set,
 };
 
-const struct xattr_handler *jfs_xattr_handlers[] = {
+const struct xattr_handler * const jfs_xattr_handlers[] = {
        &jfs_os2_xattr_handler,
        &jfs_user_xattr_handler,
        &jfs_security_xattr_handler,
        &jfs_os2_xattr_handler,
        &jfs_user_xattr_handler,
        &jfs_security_xattr_handler,