mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-24 10:39:52 +00:00
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/489 Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Cc: <stable@vger.kernel.org>
This commit is contained in:
parent
97daf8b97a
commit
e4ad29fa0d
1 changed files with 25 additions and 14 deletions
|
@ -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)
|
||||||
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue