diff options
-rw-r--r-- | fs/nfs/nfs3acl.c | 4 | ||||
-rw-r--r-- | fs/nfs_common/nfsacl.c | 22 | ||||
-rw-r--r-- | fs/posix_acl.c | 17 | ||||
-rw-r--r-- | include/linux/posix_acl.h | 1 |
4 files changed, 31 insertions, 13 deletions
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 9f88c5f4c7e2..274342771655 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -311,8 +311,8 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
311 | if (!nfs_server_capable(inode, NFS_CAP_ACLS)) | 311 | if (!nfs_server_capable(inode, NFS_CAP_ACLS)) |
312 | goto out; | 312 | goto out; |
313 | 313 | ||
314 | /* We are doing this here, because XDR marshalling can only | 314 | /* We are doing this here because XDR marshalling does not |
315 | return -ENOMEM. */ | 315 | * return any results, it BUGs. */ |
316 | status = -ENOSPC; | 316 | status = -ENOSPC; |
317 | if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES) | 317 | if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES) |
318 | goto out; | 318 | goto out; |
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index a3e78bd18679..84c27d69d421 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c | |||
@@ -42,6 +42,11 @@ struct nfsacl_encode_desc { | |||
42 | gid_t gid; | 42 | gid_t gid; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct nfsacl_simple_acl { | ||
46 | struct posix_acl acl; | ||
47 | struct posix_acl_entry ace[4]; | ||
48 | }; | ||
49 | |||
45 | static int | 50 | static int |
46 | xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | 51 | xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) |
47 | { | 52 | { |
@@ -99,17 +104,22 @@ int nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
99 | .uid = inode->i_uid, | 104 | .uid = inode->i_uid, |
100 | .gid = inode->i_gid, | 105 | .gid = inode->i_gid, |
101 | }; | 106 | }; |
107 | struct nfsacl_simple_acl aclbuf; | ||
102 | int err; | 108 | int err; |
103 | struct posix_acl *acl2 = NULL; | ||
104 | 109 | ||
105 | if (entries > NFS_ACL_MAX_ENTRIES || | 110 | if (entries > NFS_ACL_MAX_ENTRIES || |
106 | xdr_encode_word(buf, base, entries)) | 111 | xdr_encode_word(buf, base, entries)) |
107 | return -EINVAL; | 112 | return -EINVAL; |
108 | if (encode_entries && acl && acl->a_count == 3) { | 113 | if (encode_entries && acl && acl->a_count == 3) { |
109 | /* Fake up an ACL_MASK entry. */ | 114 | struct posix_acl *acl2 = &aclbuf.acl; |
110 | acl2 = posix_acl_alloc(4, GFP_KERNEL); | 115 | |
111 | if (!acl2) | 116 | /* Avoid the use of posix_acl_alloc(). nfsacl_encode() is |
112 | return -ENOMEM; | 117 | * invoked in contexts where a memory allocation failure is |
118 | * fatal. Fortunately this fake ACL is small enough to | ||
119 | * construct on the stack. */ | ||
120 | memset(acl2, 0, sizeof(acl2)); | ||
121 | posix_acl_init(acl2, 4); | ||
122 | |||
113 | /* Insert entries in canonical order: other orders seem | 123 | /* Insert entries in canonical order: other orders seem |
114 | to confuse Solaris VxFS. */ | 124 | to confuse Solaris VxFS. */ |
115 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ | 125 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ |
@@ -120,8 +130,6 @@ int nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
120 | nfsacl_desc.acl = acl2; | 130 | nfsacl_desc.acl = acl2; |
121 | } | 131 | } |
122 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); | 132 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); |
123 | if (acl2) | ||
124 | posix_acl_release(acl2); | ||
125 | if (!err) | 133 | if (!err) |
126 | err = 8 + nfsacl_desc.desc.elem_size * | 134 | err = 8 + nfsacl_desc.desc.elem_size * |
127 | nfsacl_desc.desc.array_len; | 135 | nfsacl_desc.desc.array_len; |
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 | ||
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index d68283a898bb..54211c1cd926 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h | |||
@@ -71,6 +71,7 @@ posix_acl_release(struct posix_acl *acl) | |||
71 | 71 | ||
72 | /* posix_acl.c */ | 72 | /* posix_acl.c */ |
73 | 73 | ||
74 | extern void posix_acl_init(struct posix_acl *, int); | ||
74 | extern struct posix_acl *posix_acl_alloc(int, gfp_t); | 75 | extern struct posix_acl *posix_acl_alloc(int, gfp_t); |
75 | extern struct posix_acl *posix_acl_clone(const struct posix_acl *, gfp_t); | 76 | extern struct posix_acl *posix_acl_clone(const struct posix_acl *, gfp_t); |
76 | extern int posix_acl_valid(const struct posix_acl *); | 77 | extern int posix_acl_valid(const struct posix_acl *); |