aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/copy_up.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 394e87f8340f..758012bfd5f0 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -22,9 +22,9 @@
22 22
23int ovl_copy_xattr(struct dentry *old, struct dentry *new) 23int ovl_copy_xattr(struct dentry *old, struct dentry *new)
24{ 24{
25 ssize_t list_size, size; 25 ssize_t list_size, size, value_size = 0;
26 char *buf, *name, *value; 26 char *buf, *name, *value = NULL;
27 int error; 27 int uninitialized_var(error);
28 28
29 if (!old->d_inode->i_op->getxattr || 29 if (!old->d_inode->i_op->getxattr ||
30 !new->d_inode->i_op->getxattr) 30 !new->d_inode->i_op->getxattr)
@@ -41,29 +41,40 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
41 if (!buf) 41 if (!buf)
42 return -ENOMEM; 42 return -ENOMEM;
43 43
44 error = -ENOMEM;
45 value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
46 if (!value)
47 goto out;
48
49 list_size = vfs_listxattr(old, buf, list_size); 44 list_size = vfs_listxattr(old, buf, list_size);
50 if (list_size <= 0) { 45 if (list_size <= 0) {
51 error = list_size; 46 error = list_size;
52 goto out_free_value; 47 goto out;
53 } 48 }
54 49
55 for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { 50 for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
56 size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX); 51retry:
52 size = vfs_getxattr(old, name, value, value_size);
53 if (size == -ERANGE)
54 size = vfs_getxattr(old, name, NULL, 0);
55
57 if (size < 0) { 56 if (size < 0) {
58 error = size; 57 error = size;
59 goto out_free_value; 58 break;
59 }
60
61 if (size > value_size) {
62 void *new;
63
64 new = krealloc(value, size, GFP_KERNEL);
65 if (!new) {
66 error = -ENOMEM;
67 break;
68 }
69 value = new;
70 value_size = size;
71 goto retry;
60 } 72 }
73
61 error = vfs_setxattr(new, name, value, size, 0); 74 error = vfs_setxattr(new, name, value, size, 0);
62 if (error) 75 if (error)
63 goto out_free_value; 76 break;
64 } 77 }
65
66out_free_value:
67 kfree(value); 78 kfree(value);
68out: 79out:
69 kfree(buf); 80 kfree(buf);