diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2011-01-20 22:05:38 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-25 15:24:47 -0500 |
commit | f61f6da0d53842e849bab7f69e1431bd3de1136d (patch) | |
tree | 8433904f645695338b98d3dc831631ffd6f129e5 /fs/posix_acl.c | |
parent | 731f3f482ad3b2c58a1af2d0a9a634a82803706a (diff) |
NFS: Prevent memory allocation failure in nfsacl_encode()
nfsacl_encode() allocates memory in certain cases. This of course
is not guaranteed to work.
Since commit 9f06c719 "SUNRPC: New xdr_streams XDR encoder API", the
kernel's XDR encoders can't return a result indicating possibly a
failure, so a memory allocation failure in nfsacl_encode() has become
fatal (ie, the XDR code Oopses) in some cases.
However, the allocated memory is a tiny fixed amount, on the order
of 40-50 bytes. We can easily use a stack-allocated buffer for
this, with only a wee bit of nose-holding.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/posix_acl.c')
-rw-r--r-- | fs/posix_acl.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 39df95a0ec25..b1cf6bf4b41d 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | 24 | ||
25 | EXPORT_SYMBOL(posix_acl_init); | ||
25 | EXPORT_SYMBOL(posix_acl_alloc); | 26 | EXPORT_SYMBOL(posix_acl_alloc); |
26 | EXPORT_SYMBOL(posix_acl_clone); | 27 | EXPORT_SYMBOL(posix_acl_clone); |
27 | EXPORT_SYMBOL(posix_acl_valid); | 28 | EXPORT_SYMBOL(posix_acl_valid); |
@@ -32,6 +33,16 @@ EXPORT_SYMBOL(posix_acl_chmod_masq); | |||
32 | EXPORT_SYMBOL(posix_acl_permission); | 33 | EXPORT_SYMBOL(posix_acl_permission); |
33 | 34 | ||
34 | /* | 35 | /* |
36 | * Init a fresh posix_acl | ||
37 | */ | ||
38 | void | ||
39 | posix_acl_init(struct posix_acl *acl, int count) | ||
40 | { | ||
41 | atomic_set(&acl->a_refcount, 1); | ||
42 | acl->a_count = count; | ||
43 | } | ||
44 | |||
45 | /* | ||
35 | * Allocate a new ACL with the specified number of entries. | 46 | * Allocate a new ACL with the specified number of entries. |
36 | */ | 47 | */ |
37 | struct posix_acl * | 48 | struct posix_acl * |
@@ -40,10 +51,8 @@ posix_acl_alloc(int count, gfp_t flags) | |||
40 | const size_t size = sizeof(struct posix_acl) + | 51 | const size_t size = sizeof(struct posix_acl) + |
41 | count * sizeof(struct posix_acl_entry); | 52 | count * sizeof(struct posix_acl_entry); |
42 | struct posix_acl *acl = kmalloc(size, flags); | 53 | struct posix_acl *acl = kmalloc(size, flags); |
43 | if (acl) { | 54 | if (acl) |
44 | atomic_set(&acl->a_refcount, 1); | 55 | posix_acl_init(acl, count); |
45 | acl->a_count = count; | ||
46 | } | ||
47 | return acl; | 56 | return acl; |
48 | } | 57 | } |
49 | 58 | ||