Commit d0fa70ac authored by lei lu's avatar lei lu Committed by Dave Kleikamp
Browse files

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: default avatarlei lu <llfamsec@gmail.com>
Signed-off-by: default avatarDave Kleikamp <dave.kleikamp@oracle.com>
parent 7063b802
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -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;
	}