diff options
Diffstat (limited to 'fs/xattr.c')
-rw-r--r-- | fs/xattr.c | 16 |
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 | ||