diff options
Diffstat (limited to 'fs/nfs_common/nfsacl.c')
-rw-r--r-- | fs/nfs_common/nfsacl.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index fc1c52571c03..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 | { |
@@ -72,9 +77,20 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | |||
72 | return 0; | 77 | return 0; |
73 | } | 78 | } |
74 | 79 | ||
75 | unsigned int | 80 | /** |
76 | nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | 81 | * nfsacl_encode - Encode an NFSv3 ACL |
77 | struct posix_acl *acl, int encode_entries, int typeflag) | 82 | * |
83 | * @buf: destination xdr_buf to contain XDR encoded ACL | ||
84 | * @base: byte offset in xdr_buf where XDR'd ACL begins | ||
85 | * @inode: inode of file whose ACL this is | ||
86 | * @acl: posix_acl to encode | ||
87 | * @encode_entries: whether to encode ACEs as well | ||
88 | * @typeflag: ACL type: NFS_ACL_DEFAULT or zero | ||
89 | * | ||
90 | * Returns size of encoded ACL in bytes or a negative errno value. | ||
91 | */ | ||
92 | int nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | ||
93 | struct posix_acl *acl, int encode_entries, int typeflag) | ||
78 | { | 94 | { |
79 | int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0; | 95 | int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0; |
80 | struct nfsacl_encode_desc nfsacl_desc = { | 96 | struct nfsacl_encode_desc nfsacl_desc = { |
@@ -88,17 +104,22 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
88 | .uid = inode->i_uid, | 104 | .uid = inode->i_uid, |
89 | .gid = inode->i_gid, | 105 | .gid = inode->i_gid, |
90 | }; | 106 | }; |
107 | struct nfsacl_simple_acl aclbuf; | ||
91 | int err; | 108 | int err; |
92 | struct posix_acl *acl2 = NULL; | ||
93 | 109 | ||
94 | if (entries > NFS_ACL_MAX_ENTRIES || | 110 | if (entries > NFS_ACL_MAX_ENTRIES || |
95 | xdr_encode_word(buf, base, entries)) | 111 | xdr_encode_word(buf, base, entries)) |
96 | return -EINVAL; | 112 | return -EINVAL; |
97 | if (encode_entries && acl && acl->a_count == 3) { | 113 | if (encode_entries && acl && acl->a_count == 3) { |
98 | /* Fake up an ACL_MASK entry. */ | 114 | struct posix_acl *acl2 = &aclbuf.acl; |
99 | acl2 = posix_acl_alloc(4, GFP_KERNEL); | 115 | |
100 | if (!acl2) | 116 | /* Avoid the use of posix_acl_alloc(). nfsacl_encode() is |
101 | 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 | |||
102 | /* Insert entries in canonical order: other orders seem | 123 | /* Insert entries in canonical order: other orders seem |
103 | to confuse Solaris VxFS. */ | 124 | to confuse Solaris VxFS. */ |
104 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ | 125 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ |
@@ -109,8 +130,6 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
109 | nfsacl_desc.acl = acl2; | 130 | nfsacl_desc.acl = acl2; |
110 | } | 131 | } |
111 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); | 132 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); |
112 | if (acl2) | ||
113 | posix_acl_release(acl2); | ||
114 | if (!err) | 133 | if (!err) |
115 | err = 8 + nfsacl_desc.desc.elem_size * | 134 | err = 8 + nfsacl_desc.desc.elem_size * |
116 | nfsacl_desc.desc.array_len; | 135 | nfsacl_desc.desc.array_len; |
@@ -224,9 +243,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl) | |||
224 | return 0; | 243 | return 0; |
225 | } | 244 | } |
226 | 245 | ||
227 | unsigned int | 246 | /** |
228 | nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt, | 247 | * nfsacl_decode - Decode an NFSv3 ACL |
229 | struct posix_acl **pacl) | 248 | * |
249 | * @buf: xdr_buf containing XDR'd ACL data to decode | ||
250 | * @base: byte offset in xdr_buf where XDR'd ACL begins | ||
251 | * @aclcnt: count of ACEs in decoded posix_acl | ||
252 | * @pacl: buffer in which to place decoded posix_acl | ||
253 | * | ||
254 | * Returns the length of the decoded ACL in bytes, or a negative errno value. | ||
255 | */ | ||
256 | int nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt, | ||
257 | struct posix_acl **pacl) | ||
230 | { | 258 | { |
231 | struct nfsacl_decode_desc nfsacl_desc = { | 259 | struct nfsacl_decode_desc nfsacl_desc = { |
232 | .desc = { | 260 | .desc = { |