Skip to content

Commit

Permalink
ovl: use a minimal buffer in ovl_copy_xattr
Browse files Browse the repository at this point in the history
[ Upstream commit e4ad29fa0d224d05e08b2858e65f112fd8edd4fe ]

Rather than always allocating the high-order XATTR_SIZE_MAX buffer
which is costly and prone to failure, only allocate what is needed and
realloc if necessary.

Fixes coreos/bugs#489

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Cc: <stable@vger.kernel.org>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
  • Loading branch information
Vito Caputo authored and Mohi1117 committed Feb 15, 2018
1 parent 7c64d60 commit 8d286e1
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions fs/overlayfs/copy_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@

int ovl_copy_xattr(struct dentry *old, struct dentry *new)
{
ssize_t list_size, size;
char *buf, *name, *value;
int error;
ssize_t list_size, size, value_size = 0;
char *buf, *name, *value = NULL;
int uninitialized_var(error);

if (!old->d_inode->i_op->getxattr ||
!new->d_inode->i_op->getxattr)
Expand All @@ -41,29 +41,40 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
if (!buf)
return -ENOMEM;

error = -ENOMEM;
value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
if (!value)
goto out;

list_size = vfs_listxattr(old, buf, list_size);
if (list_size <= 0) {
error = list_size;
goto out_free_value;
goto out;
}

for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX);
retry:
size = vfs_getxattr(old, name, value, value_size);
if (size == -ERANGE)
size = vfs_getxattr(old, name, NULL, 0);

if (size < 0) {
error = size;
goto out_free_value;
break;
}

if (size > value_size) {
void *new;

new = krealloc(value, size, GFP_KERNEL);
if (!new) {
error = -ENOMEM;
break;
}
value = new;
value_size = size;
goto retry;
}

error = vfs_setxattr(new, name, value, size, 0);
if (error)
goto out_free_value;
break;
}

out_free_value:
kfree(value);
out:
kfree(buf);
Expand Down

0 comments on commit 8d286e1

Please sign in to comment.