]> Pileus Git - ~andy/linux/blobdiff - fs/xattr.c
Btrfs: change integrity checker to support big blocks
[~andy/linux] / fs / xattr.c
index d14afbae3c135973c66b9c88d4c5315836b86137..3c8c1cc333c7c79dfa105049a62d8b6e1c28661c 100644 (file)
@@ -321,6 +321,7 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
 {
        int error;
        void *kvalue = NULL;
+       void *vvalue = NULL;    /* If non-NULL, we used vmalloc() */
        char kname[XATTR_NAME_MAX + 1];
 
        if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
@@ -335,13 +336,25 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
        if (size) {
                if (size > XATTR_SIZE_MAX)
                        return -E2BIG;
-               kvalue = memdup_user(value, size);
-               if (IS_ERR(kvalue))
-                       return PTR_ERR(kvalue);
+               kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
+               if (!kvalue) {
+                       vvalue = vmalloc(size);
+                       if (!vvalue)
+                               return -ENOMEM;
+                       kvalue = vvalue;
+               }
+               if (copy_from_user(kvalue, value, size)) {
+                       error = -EFAULT;
+                       goto out;
+               }
        }
 
        error = vfs_setxattr(d, kname, kvalue, size, flags);
-       kfree(kvalue);
+out:
+       if (vvalue)
+               vfree(vvalue);
+       else
+               kfree(kvalue);
        return error;
 }