]> Pileus Git - ~andy/linux/blobdiff - fs/xattr.c
fs/xattr.c:getxattr(): improve handling of allocation failures
[~andy/linux] / fs / xattr.c
index 1d7ac379045879b827b196f0d7a7420fe33c783d..4d45b7189e7eaa352da0567b8fe4a2d1b738c999 100644 (file)
@@ -427,6 +427,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
 {
        ssize_t error;
        void *kvalue = NULL;
+       void *vvalue = NULL;
        char kname[XATTR_NAME_MAX + 1];
 
        error = strncpy_from_user(kname, name, sizeof(kname));
@@ -438,9 +439,13 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
        if (size) {
                if (size > XATTR_SIZE_MAX)
                        size = XATTR_SIZE_MAX;
-               kvalue = kzalloc(size, GFP_KERNEL);
-               if (!kvalue)
-                       return -ENOMEM;
+               kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+               if (!kvalue) {
+                       vvalue = vmalloc(size);
+                       if (!vvalue)
+                               return -ENOMEM;
+                       kvalue = vvalue;
+               }
        }
 
        error = vfs_getxattr(d, kname, kvalue, size);
@@ -452,7 +457,10 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
                   than XATTR_SIZE_MAX bytes. Not possible. */
                error = -E2BIG;
        }
-       kfree(kvalue);
+       if (vvalue)
+               vfree(vvalue);
+       else
+               kfree(kvalue);
        return error;
 }