aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-04-05 18:30:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-04-05 18:30:34 -0400
commit5d32c88f0b94061b3af2e3ade92422407282eb12 (patch)
tree2e1f81aa47b2cf59625c8fba17199617e33802e6 /fs/xattr.c
parent43f63c8711ce02226b7bbdafeba7b8031faf3fb4 (diff)
parentdac23b0d0513916498d40412818bd2c581b365f7 (diff)
Merge branch 'akpm' (Andrew's patch-bomb)
Merge batch of fixes from Andrew Morton: "The simple_open() cleanup was held back while I wanted for laggards to merge things. I still need to send a few checkpoint/restore patches. I've been wobbly about merging them because I'm wobbly about the overall prospects for success of the project. But after speaking with Pavel at the LSF conference, it sounds like they're further toward completion than I feared - apparently davem is at the "has stopped complaining" stage regarding the net changes. So I need to go back and re-review those patchs and their (lengthy) discussion." * emailed from Andrew Morton <akpm@linux-foundation.org>: (16 patches) memcg swap: use mem_cgroup_uncharge_swap fix backlight: add driver for DA9052/53 PMIC v1 C6X: use set_current_blocked() and block_sigmask() MAINTAINERS: add entry for sparse checker MAINTAINERS: fix REMOTEPROC F: typo alpha: use set_current_blocked() and block_sigmask() simple_open: automatically convert to simple_open() scripts/coccinelle/api/simple_open.cocci: semantic patch for simple_open() libfs: add simple_open() hugetlbfs: remove unregister_filesystem() when initializing module drivers/rtc/rtc-88pm860x.c: fix rtc irq enable callback fs/xattr.c:setxattr(): improve handling of allocation failures fs/xattr.c:listxattr(): fall back to vmalloc() if kmalloc() failed fs/xattr.c: suppress page allocation failure warnings from sys_listxattr() sysrq: use SEND_SIG_FORCED instead of force_sig() proc: fix mount -t proc -o AAA
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index d6dfd247bb2..3c8c1cc333c 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -19,8 +19,9 @@
19#include <linux/export.h> 19#include <linux/export.h>
20#include <linux/fsnotify.h> 20#include <linux/fsnotify.h>
21#include <linux/audit.h> 21#include <linux/audit.h>
22#include <asm/uaccess.h> 22#include <linux/vmalloc.h>
23 23
24#include <asm/uaccess.h>
24 25
25/* 26/*
26 * Check permissions for extended attribute access. This is a bit complicated 27 * Check permissions for extended attribute access. This is a bit complicated
@@ -320,6 +321,7 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
320{ 321{
321 int error; 322 int error;
322 void *kvalue = NULL; 323 void *kvalue = NULL;
324 void *vvalue = NULL; /* If non-NULL, we used vmalloc() */
323 char kname[XATTR_NAME_MAX + 1]; 325 char kname[XATTR_NAME_MAX + 1];
324 326
325 if (flags & ~(XATTR_CREATE|XATTR_REPLACE)) 327 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
@@ -334,13 +336,25 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
334 if (size) { 336 if (size) {
335 if (size > XATTR_SIZE_MAX) 337 if (size > XATTR_SIZE_MAX)
336 return -E2BIG; 338 return -E2BIG;
337 kvalue = memdup_user(value, size); 339 kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
338 if (IS_ERR(kvalue)) 340 if (!kvalue) {
339 return PTR_ERR(kvalue); 341 vvalue = vmalloc(size);
342 if (!vvalue)
343 return -ENOMEM;
344 kvalue = vvalue;
345 }
346 if (copy_from_user(kvalue, value, size)) {
347 error = -EFAULT;
348 goto out;
349 }
340 } 350 }
341 351
342 error = vfs_setxattr(d, kname, kvalue, size, flags); 352 error = vfs_setxattr(d, kname, kvalue, size, flags);
343 kfree(kvalue); 353out:
354 if (vvalue)
355 vfree(vvalue);
356 else
357 kfree(kvalue);
344 return error; 358 return error;
345} 359}
346 360
@@ -492,13 +506,18 @@ listxattr(struct dentry *d, char __user *list, size_t size)
492{ 506{
493 ssize_t error; 507 ssize_t error;
494 char *klist = NULL; 508 char *klist = NULL;
509 char *vlist = NULL; /* If non-NULL, we used vmalloc() */
495 510
496 if (size) { 511 if (size) {
497 if (size > XATTR_LIST_MAX) 512 if (size > XATTR_LIST_MAX)
498 size = XATTR_LIST_MAX; 513 size = XATTR_LIST_MAX;
499 klist = kmalloc(size, GFP_KERNEL); 514 klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
500 if (!klist) 515 if (!klist) {
501 return -ENOMEM; 516 vlist = vmalloc(size);
517 if (!vlist)
518 return -ENOMEM;
519 klist = vlist;
520 }
502 } 521 }
503 522
504 error = vfs_listxattr(d, klist, size); 523 error = vfs_listxattr(d, klist, size);
@@ -510,7 +529,10 @@ listxattr(struct dentry *d, char __user *list, size_t size)
510 than XATTR_LIST_MAX bytes. Not possible. */ 529 than XATTR_LIST_MAX bytes. Not possible. */
511 error = -E2BIG; 530 error = -E2BIG;
512 } 531 }
513 kfree(klist); 532 if (vlist)
533 vfree(vlist);
534 else
535 kfree(klist);
514 return error; 536 return error;
515} 537}
516 538