diff options
-rw-r--r-- | fs/overlayfs/copy_up.c | 39 |
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 | ||
23 | int ovl_copy_xattr(struct dentry *old, struct dentry *new) | 23 | int 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); | 51 | retry: |
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 | |||
66 | out_free_value: | ||
67 | kfree(value); | 78 | kfree(value); |
68 | out: | 79 | out: |
69 | kfree(buf); | 80 | kfree(buf); |