aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xattr.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index a14d842ccb21..d14afbae3c13 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
@@ -492,13 +493,18 @@ listxattr(struct dentry *d, char __user *list, size_t size)
492{ 493{
493 ssize_t error; 494 ssize_t error;
494 char *klist = NULL; 495 char *klist = NULL;
496 char *vlist = NULL; /* If non-NULL, we used vmalloc() */
495 497
496 if (size) { 498 if (size) {
497 if (size > XATTR_LIST_MAX) 499 if (size > XATTR_LIST_MAX)
498 size = XATTR_LIST_MAX; 500 size = XATTR_LIST_MAX;
499 klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL); 501 klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
500 if (!klist) 502 if (!klist) {
501 return -ENOMEM; 503 vlist = vmalloc(size);
504 if (!vlist)
505 return -ENOMEM;
506 klist = vlist;
507 }
502 } 508 }
503 509
504 error = vfs_listxattr(d, klist, size); 510 error = vfs_listxattr(d, klist, size);
@@ -510,7 +516,10 @@ listxattr(struct dentry *d, char __user *list, size_t size)
510 than XATTR_LIST_MAX bytes. Not possible. */ 516 than XATTR_LIST_MAX bytes. Not possible. */
511 error = -E2BIG; 517 error = -E2BIG;
512 } 518 }
513 kfree(klist); 519 if (vlist)
520 vfree(vlist);
521 else
522 kfree(klist);
514 return error; 523 return error;
515} 524}
516 525