Commit e4ad29fa authored by Vito Caputo's avatar Vito Caputo Committed by Miklos Szeredi

ovl: use a minimal buffer in ovl_copy_xattr

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 https://github.com/coreos/bugs/issues/489Signed-off-by: default avatarMiklos Szeredi <miklos@szeredi.hu>
Cc: <stable@vger.kernel.org>
parent 97daf8b9
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
int ovl_copy_xattr(struct dentry *old, struct dentry *new) int ovl_copy_xattr(struct dentry *old, struct dentry *new)
{ {
ssize_t list_size, size; ssize_t list_size, size, value_size = 0;
char *buf, *name, *value; char *buf, *name, *value = NULL;
int error; int uninitialized_var(error);
if (!old->d_inode->i_op->getxattr || if (!old->d_inode->i_op->getxattr ||
!new->d_inode->i_op->getxattr) !new->d_inode->i_op->getxattr)
...@@ -41,29 +41,40 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) ...@@ -41,29 +41,40 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
error = -ENOMEM;
value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
if (!value)
goto out;
list_size = vfs_listxattr(old, buf, list_size); list_size = vfs_listxattr(old, buf, list_size);
if (list_size <= 0) { if (list_size <= 0) {
error = list_size; error = list_size;
goto out_free_value; goto out;
} }
for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { 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) { if (size < 0) {
error = size; 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); error = vfs_setxattr(new, name, value, size, 0);
if (error) if (error)
goto out_free_value; break;
} }
out_free_value:
kfree(value); kfree(value);
out: out:
kfree(buf); kfree(buf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment