aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index 1d7ac3790458..4d45b7189e7e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -427,6 +427,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
427{ 427{
428 ssize_t error; 428 ssize_t error;
429 void *kvalue = NULL; 429 void *kvalue = NULL;
430 void *vvalue = NULL;
430 char kname[XATTR_NAME_MAX + 1]; 431 char kname[XATTR_NAME_MAX + 1];
431 432
432 error = strncpy_from_user(kname, name, sizeof(kname)); 433 error = strncpy_from_user(kname, name, sizeof(kname));
@@ -438,9 +439,13 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
438 if (size) { 439 if (size) {
439 if (size > XATTR_SIZE_MAX) 440 if (size > XATTR_SIZE_MAX)
440 size = XATTR_SIZE_MAX; 441 size = XATTR_SIZE_MAX;
441 kvalue = kzalloc(size, GFP_KERNEL); 442 kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
442 if (!kvalue) 443 if (!kvalue) {
443 return -ENOMEM; 444 vvalue = vmalloc(size);
445 if (!vvalue)
446 return -ENOMEM;
447 kvalue = vvalue;
448 }
444 } 449 }
445 450
446 error = vfs_getxattr(d, kname, kvalue, size); 451 error = vfs_getxattr(d, kname, kvalue, size);
@@ -452,7 +457,10 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
452 than XATTR_SIZE_MAX bytes. Not possible. */ 457 than XATTR_SIZE_MAX bytes. Not possible. */
453 error = -E2BIG; 458 error = -E2BIG;
454 } 459 }
455 kfree(kvalue); 460 if (vvalue)
461 vfree(vvalue);
462 else
463 kfree(kvalue);
456 return error; 464 return error;
457} 465}
458 466