aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r--fs/nfsd/nfs4acl.c491
1 files changed, 238 insertions, 253 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 5d94555cdc83..832673b14587 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -61,9 +61,11 @@
61 61
62/* flags used to simulate posix default ACLs */ 62/* flags used to simulate posix default ACLs */
63#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ 63#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
64 | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE) 64 | NFS4_ACE_DIRECTORY_INHERIT_ACE)
65 65
66#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS | NFS4_ACE_IDENTIFIER_GROUP) 66#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
67 | NFS4_ACE_INHERIT_ONLY_ACE \
68 | NFS4_ACE_IDENTIFIER_GROUP)
67 69
68#define MASK_EQUAL(mask1, mask2) \ 70#define MASK_EQUAL(mask1, mask2) \
69 ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) ) 71 ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
@@ -87,12 +89,19 @@ mask_from_posix(unsigned short perm, unsigned int flags)
87} 89}
88 90
89static u32 91static u32
90deny_mask(u32 allow_mask, unsigned int flags) 92deny_mask_from_posix(unsigned short perm, u32 flags)
91{ 93{
92 u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP; 94 u32 mask = 0;
93 if (!(flags & NFS4_ACL_DIR)) 95
94 ret &= ~NFS4_ACE_DELETE_CHILD; 96 if (perm & ACL_READ)
95 return ret; 97 mask |= NFS4_READ_MODE;
98 if (perm & ACL_WRITE)
99 mask |= NFS4_WRITE_MODE;
100 if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
101 mask |= NFS4_ACE_DELETE_CHILD;
102 if (perm & ACL_EXECUTE)
103 mask |= NFS4_EXECUTE_MODE;
104 return mask;
96} 105}
97 106
98/* XXX: modify functions to return NFS errors; they're only ever 107/* XXX: modify functions to return NFS errors; they're only ever
@@ -126,108 +135,151 @@ struct ace_container {
126}; 135};
127 136
128static short ace2type(struct nfs4_ace *); 137static short ace2type(struct nfs4_ace *);
129static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); 138static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
130static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int); 139 unsigned int);
131int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); 140void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
132static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
133 141
134struct nfs4_acl * 142struct nfs4_acl *
135nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, 143nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
136 unsigned int flags) 144 unsigned int flags)
137{ 145{
138 struct nfs4_acl *acl; 146 struct nfs4_acl *acl;
139 int error = -EINVAL; 147 int size = 0;
140 148
141 if ((pacl != NULL && 149 if (pacl) {
142 (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) || 150 if (posix_acl_valid(pacl) < 0)
143 (dpacl != NULL && 151 return ERR_PTR(-EINVAL);
144 (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0))) 152 size += 2*pacl->a_count;
145 goto out_err;
146
147 acl = nfs4_acl_new();
148 if (acl == NULL) {
149 error = -ENOMEM;
150 goto out_err;
151 } 153 }
152 154 if (dpacl) {
153 if (pacl != NULL) { 155 if (posix_acl_valid(dpacl) < 0)
154 error = _posix_to_nfsv4_one(pacl, acl, 156 return ERR_PTR(-EINVAL);
155 flags & ~NFS4_ACL_TYPE_DEFAULT); 157 size += 2*dpacl->a_count;
156 if (error < 0)
157 goto out_acl;
158 } 158 }
159 159
160 if (dpacl != NULL) { 160 /* Allocate for worst case: one (deny, allow) pair each: */
161 error = _posix_to_nfsv4_one(dpacl, acl, 161 acl = nfs4_acl_new(size);
162 flags | NFS4_ACL_TYPE_DEFAULT); 162 if (acl == NULL)
163 if (error < 0) 163 return ERR_PTR(-ENOMEM);
164 goto out_acl;
165 }
166 164
167 return acl; 165 if (pacl)
166 _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
168 167
169out_acl: 168 if (dpacl)
170 nfs4_acl_free(acl); 169 _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
171out_err:
172 acl = ERR_PTR(error);
173 170
174 return acl; 171 return acl;
175} 172}
176 173
177static int 174struct posix_acl_summary {
178nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype, 175 unsigned short owner;
179 uid_t owner, unsigned int flags) 176 unsigned short users;
177 unsigned short group;
178 unsigned short groups;
179 unsigned short other;
180 unsigned short mask;
181};
182
183static void
184summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
180{ 185{
181 int error; 186 struct posix_acl_entry *pa, *pe;
182 187 pas->users = 0;
183 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, 188 pas->groups = 0;
184 eflag, mask, whotype, owner); 189 pas->mask = 07;
185 if (error < 0) 190
186 return error; 191 pe = acl->a_entries + acl->a_count;
187 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 192
188 eflag, deny_mask(mask, flags), whotype, owner); 193 FOREACH_ACL_ENTRY(pa, acl, pe) {
189 return error; 194 switch (pa->e_tag) {
195 case ACL_USER_OBJ:
196 pas->owner = pa->e_perm;
197 break;
198 case ACL_GROUP_OBJ:
199 pas->group = pa->e_perm;
200 break;
201 case ACL_USER:
202 pas->users |= pa->e_perm;
203 break;
204 case ACL_GROUP:
205 pas->groups |= pa->e_perm;
206 break;
207 case ACL_OTHER:
208 pas->other = pa->e_perm;
209 break;
210 case ACL_MASK:
211 pas->mask = pa->e_perm;
212 break;
213 }
214 }
215 /* We'll only care about effective permissions: */
216 pas->users &= pas->mask;
217 pas->group &= pas->mask;
218 pas->groups &= pas->mask;
190} 219}
191 220
192/* We assume the acl has been verified with posix_acl_valid. */ 221/* We assume the acl has been verified with posix_acl_valid. */
193static int 222static void
194_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, 223_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
195 unsigned int flags) 224 unsigned int flags)
196{ 225{
197 struct posix_acl_entry *pa, *pe, *group_owner_entry; 226 struct posix_acl_entry *pa, *group_owner_entry;
198 int error = -EINVAL; 227 struct nfs4_ace *ace;
199 u32 mask, mask_mask; 228 struct posix_acl_summary pas;
229 unsigned short deny;
200 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? 230 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
201 NFS4_INHERITANCE_FLAGS : 0); 231 NFS4_INHERITANCE_FLAGS : 0);
202 232
203 BUG_ON(pacl->a_count < 3); 233 BUG_ON(pacl->a_count < 3);
204 pe = pacl->a_entries + pacl->a_count; 234 summarize_posix_acl(pacl, &pas);
205 pa = pe - 2; /* if mask entry exists, it's second from the last. */
206 if (pa->e_tag == ACL_MASK)
207 mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
208 else
209 mask_mask = 0;
210 235
211 pa = pacl->a_entries; 236 pa = pacl->a_entries;
212 BUG_ON(pa->e_tag != ACL_USER_OBJ); 237 ace = acl->aces + acl->naces;
213 mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
214 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
215 if (error < 0)
216 goto out;
217 pa++;
218 238
219 while (pa->e_tag == ACL_USER) { 239 /* We could deny everything not granted by the owner: */
220 mask = mask_from_posix(pa->e_perm, flags); 240 deny = ~pas.owner;
221 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 241 /*
222 eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id); 242 * but it is equivalent (and simpler) to deny only what is not
223 if (error < 0) 243 * granted by later entries:
224 goto out; 244 */
245 deny &= pas.users | pas.group | pas.groups | pas.other;
246 if (deny) {
247 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
248 ace->flag = eflag;
249 ace->access_mask = deny_mask_from_posix(deny, flags);
250 ace->whotype = NFS4_ACL_WHO_OWNER;
251 ace++;
252 acl->naces++;
253 }
225 254
255 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
256 ace->flag = eflag;
257 ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
258 ace->whotype = NFS4_ACL_WHO_OWNER;
259 ace++;
260 acl->naces++;
261 pa++;
226 262
227 error = nfs4_acl_add_pair(acl, eflag, mask, 263 while (pa->e_tag == ACL_USER) {
228 NFS4_ACL_WHO_NAMED, pa->e_id, flags); 264 deny = ~(pa->e_perm & pas.mask);
229 if (error < 0) 265 deny &= pas.groups | pas.group | pas.other;
230 goto out; 266 if (deny) {
267 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
268 ace->flag = eflag;
269 ace->access_mask = deny_mask_from_posix(deny, flags);
270 ace->whotype = NFS4_ACL_WHO_NAMED;
271 ace->who = pa->e_id;
272 ace++;
273 acl->naces++;
274 }
275 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
276 ace->flag = eflag;
277 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
278 flags);
279 ace->whotype = NFS4_ACL_WHO_NAMED;
280 ace->who = pa->e_id;
281 ace++;
282 acl->naces++;
231 pa++; 283 pa++;
232 } 284 }
233 285
@@ -236,67 +288,65 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
236 288
237 /* allow ACEs */ 289 /* allow ACEs */
238 290
239 if (pacl->a_count > 3) {
240 BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
241 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
242 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
243 NFS4_ACL_WHO_GROUP, 0);
244 if (error < 0)
245 goto out;
246 }
247 group_owner_entry = pa; 291 group_owner_entry = pa;
248 mask = mask_from_posix(pa->e_perm, flags); 292
249 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, 293 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
250 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, 294 ace->flag = eflag;
251 NFS4_ACL_WHO_GROUP, 0); 295 ace->access_mask = mask_from_posix(pas.group, flags);
252 if (error < 0) 296 ace->whotype = NFS4_ACL_WHO_GROUP;
253 goto out; 297 ace++;
298 acl->naces++;
254 pa++; 299 pa++;
255 300
256 while (pa->e_tag == ACL_GROUP) { 301 while (pa->e_tag == ACL_GROUP) {
257 mask = mask_from_posix(pa->e_perm, flags); 302 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
258 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 303 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
259 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, 304 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
260 NFS4_ACL_WHO_NAMED, pa->e_id); 305 flags);
261 if (error < 0) 306 ace->whotype = NFS4_ACL_WHO_NAMED;
262 goto out; 307 ace->who = pa->e_id;
263 308 ace++;
264 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, 309 acl->naces++;
265 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
266 NFS4_ACL_WHO_NAMED, pa->e_id);
267 if (error < 0)
268 goto out;
269 pa++; 310 pa++;
270 } 311 }
271 312
272 /* deny ACEs */ 313 /* deny ACEs */
273 314
274 pa = group_owner_entry; 315 pa = group_owner_entry;
275 mask = mask_from_posix(pa->e_perm, flags); 316
276 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 317 deny = ~pas.group & pas.other;
277 NFS4_ACE_IDENTIFIER_GROUP | eflag, 318 if (deny) {
278 deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0); 319 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
279 if (error < 0) 320 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
280 goto out; 321 ace->access_mask = deny_mask_from_posix(deny, flags);
322 ace->whotype = NFS4_ACL_WHO_GROUP;
323 ace++;
324 acl->naces++;
325 }
281 pa++; 326 pa++;
327
282 while (pa->e_tag == ACL_GROUP) { 328 while (pa->e_tag == ACL_GROUP) {
283 mask = mask_from_posix(pa->e_perm, flags); 329 deny = ~(pa->e_perm & pas.mask);
284 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 330 deny &= pas.other;
285 NFS4_ACE_IDENTIFIER_GROUP | eflag, 331 if (deny) {
286 deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id); 332 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
287 if (error < 0) 333 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
288 goto out; 334 ace->access_mask = mask_from_posix(deny, flags);
335 ace->whotype = NFS4_ACL_WHO_NAMED;
336 ace->who = pa->e_id;
337 ace++;
338 acl->naces++;
339 }
289 pa++; 340 pa++;
290 } 341 }
291 342
292 if (pa->e_tag == ACL_MASK) 343 if (pa->e_tag == ACL_MASK)
293 pa++; 344 pa++;
294 BUG_ON(pa->e_tag != ACL_OTHER); 345 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
295 mask = mask_from_posix(pa->e_perm, flags); 346 ace->flag = eflag;
296 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags); 347 ace->access_mask = mask_from_posix(pa->e_perm, flags);
297 348 ace->whotype = NFS4_ACL_WHO_EVERYONE;
298out: 349 acl->naces++;
299 return error;
300} 350}
301 351
302static void 352static void
@@ -342,46 +392,6 @@ sort_pacl(struct posix_acl *pacl)
342 return; 392 return;
343} 393}
344 394
345int
346nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
347 struct posix_acl **dpacl, unsigned int flags)
348{
349 struct nfs4_acl *dacl;
350 int error = -ENOMEM;
351
352 *pacl = NULL;
353 *dpacl = NULL;
354
355 dacl = nfs4_acl_new();
356 if (dacl == NULL)
357 goto out;
358
359 error = nfs4_acl_split(acl, dacl);
360 if (error)
361 goto out_acl;
362
363 *pacl = _nfsv4_to_posix_one(acl, flags);
364 if (IS_ERR(*pacl)) {
365 error = PTR_ERR(*pacl);
366 *pacl = NULL;
367 goto out_acl;
368 }
369
370 *dpacl = _nfsv4_to_posix_one(dacl, flags);
371 if (IS_ERR(*dpacl)) {
372 error = PTR_ERR(*dpacl);
373 *dpacl = NULL;
374 }
375out_acl:
376 if (error) {
377 posix_acl_release(*pacl);
378 *pacl = NULL;
379 }
380 nfs4_acl_free(dacl);
381out:
382 return error;
383}
384
385/* 395/*
386 * While processing the NFSv4 ACE, this maintains bitmasks representing 396 * While processing the NFSv4 ACE, this maintains bitmasks representing
387 * which permission bits have been allowed and which denied to a given 397 * which permission bits have been allowed and which denied to a given
@@ -406,6 +416,7 @@ struct posix_ace_state_array {
406 * calculated so far: */ 416 * calculated so far: */
407 417
408struct posix_acl_state { 418struct posix_acl_state {
419 int empty;
409 struct posix_ace_state owner; 420 struct posix_ace_state owner;
410 struct posix_ace_state group; 421 struct posix_ace_state group;
411 struct posix_ace_state other; 422 struct posix_ace_state other;
@@ -421,6 +432,7 @@ init_state(struct posix_acl_state *state, int cnt)
421 int alloc; 432 int alloc;
422 433
423 memset(state, 0, sizeof(struct posix_acl_state)); 434 memset(state, 0, sizeof(struct posix_acl_state));
435 state->empty = 1;
424 /* 436 /*
425 * In the worst case, each individual acl could be for a distinct 437 * In the worst case, each individual acl could be for a distinct
426 * named user or group, but we don't no which, so we allocate 438 * named user or group, but we don't no which, so we allocate
@@ -488,6 +500,20 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
488 int nace; 500 int nace;
489 int i, error = 0; 501 int i, error = 0;
490 502
503 /*
504 * ACLs with no ACEs are treated differently in the inheritable
505 * and effective cases: when there are no inheritable ACEs, we
506 * set a zero-length default posix acl:
507 */
508 if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {
509 pacl = posix_acl_alloc(0, GFP_KERNEL);
510 return pacl ? pacl : ERR_PTR(-ENOMEM);
511 }
512 /*
513 * When there are no effective ACEs, the following will end
514 * up setting a 3-element effective posix ACL with all
515 * permissions zero.
516 */
491 nace = 4 + state->users->n + state->groups->n; 517 nace = 4 + state->users->n + state->groups->n;
492 pacl = posix_acl_alloc(nace, GFP_KERNEL); 518 pacl = posix_acl_alloc(nace, GFP_KERNEL);
493 if (!pacl) 519 if (!pacl)
@@ -603,6 +629,8 @@ static void process_one_v4_ace(struct posix_acl_state *state,
603 u32 mask = ace->access_mask; 629 u32 mask = ace->access_mask;
604 int i; 630 int i;
605 631
632 state->empty = 0;
633
606 switch (ace2type(ace)) { 634 switch (ace2type(ace)) {
607 case ACL_USER_OBJ: 635 case ACL_USER_OBJ:
608 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { 636 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
@@ -666,75 +694,62 @@ static void process_one_v4_ace(struct posix_acl_state *state,
666 } 694 }
667} 695}
668 696
669static struct posix_acl * 697int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
670_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags) 698 struct posix_acl **dpacl, unsigned int flags)
671{ 699{
672 struct posix_acl_state state; 700 struct posix_acl_state effective_acl_state, default_acl_state;
673 struct posix_acl *pacl;
674 struct nfs4_ace *ace; 701 struct nfs4_ace *ace;
675 int ret; 702 int ret;
676 703
677 ret = init_state(&state, n4acl->naces); 704 ret = init_state(&effective_acl_state, acl->naces);
678 if (ret) 705 if (ret)
679 return ERR_PTR(ret); 706 return ret;
680 707 ret = init_state(&default_acl_state, acl->naces);
681 list_for_each_entry(ace, &n4acl->ace_head, l_ace) 708 if (ret)
682 process_one_v4_ace(&state, ace); 709 goto out_estate;
683 710 ret = -EINVAL;
684 pacl = posix_state_to_acl(&state, flags); 711 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
685
686 free_state(&state);
687
688 if (!IS_ERR(pacl))
689 sort_pacl(pacl);
690 return pacl;
691}
692
693static int
694nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
695{
696 struct list_head *h, *n;
697 struct nfs4_ace *ace;
698 int error = 0;
699
700 list_for_each_safe(h, n, &acl->ace_head) {
701 ace = list_entry(h, struct nfs4_ace, l_ace);
702
703 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && 712 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
704 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) 713 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
705 return -EINVAL; 714 goto out_dstate;
706
707 if (ace->flag & ~NFS4_SUPPORTED_FLAGS) 715 if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
708 return -EINVAL; 716 goto out_dstate;
709 717 if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
710 switch (ace->flag & NFS4_INHERITANCE_FLAGS) { 718 process_one_v4_ace(&effective_acl_state, ace);
711 case 0:
712 /* Leave this ace in the effective acl: */
713 continue; 719 continue;
714 case NFS4_INHERITANCE_FLAGS:
715 /* Add this ace to the default acl and remove it
716 * from the effective acl: */
717 error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
718 ace->access_mask, ace->whotype, ace->who);
719 if (error)
720 return error;
721 list_del(h);
722 kfree(ace);
723 acl->naces--;
724 break;
725 case NFS4_INHERITANCE_FLAGS & ~NFS4_ACE_INHERIT_ONLY_ACE:
726 /* Add this ace to the default, but leave it in
727 * the effective acl as well: */
728 error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
729 ace->access_mask, ace->whotype, ace->who);
730 if (error)
731 return error;
732 break;
733 default:
734 return -EINVAL;
735 } 720 }
721 if (!(flags & NFS4_ACL_DIR))
722 goto out_dstate;
723 /*
724 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
725 * is set, we're effectively turning on the other. That's OK,
726 * according to rfc 3530.
727 */
728 process_one_v4_ace(&default_acl_state, ace);
729
730 if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
731 process_one_v4_ace(&effective_acl_state, ace);
736 } 732 }
737 return 0; 733 *pacl = posix_state_to_acl(&effective_acl_state, flags);
734 if (IS_ERR(*pacl)) {
735 ret = PTR_ERR(*pacl);
736 goto out_dstate;
737 }
738 *dpacl = posix_state_to_acl(&default_acl_state,
739 flags | NFS4_ACL_TYPE_DEFAULT);
740 if (IS_ERR(*dpacl)) {
741 ret = PTR_ERR(*dpacl);
742 posix_acl_release(*pacl);
743 goto out_dstate;
744 }
745 sort_pacl(*pacl);
746 sort_pacl(*dpacl);
747 ret = 0;
748out_dstate:
749 free_state(&default_acl_state);
750out_estate:
751 free_state(&effective_acl_state);
752 return ret;
738} 753}
739 754
740static short 755static short
@@ -759,48 +774,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
759EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); 774EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
760 775
761struct nfs4_acl * 776struct nfs4_acl *
762nfs4_acl_new(void) 777nfs4_acl_new(int n)
763{ 778{
764 struct nfs4_acl *acl; 779 struct nfs4_acl *acl;
765 780
766 if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL) 781 acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
782 if (acl == NULL)
767 return NULL; 783 return NULL;
768
769 acl->naces = 0; 784 acl->naces = 0;
770 INIT_LIST_HEAD(&acl->ace_head);
771
772 return acl; 785 return acl;
773} 786}
774 787
775void 788void
776nfs4_acl_free(struct nfs4_acl *acl)
777{
778 struct list_head *h;
779 struct nfs4_ace *ace;
780
781 if (!acl)
782 return;
783
784 while (!list_empty(&acl->ace_head)) {
785 h = acl->ace_head.next;
786 list_del(h);
787 ace = list_entry(h, struct nfs4_ace, l_ace);
788 kfree(ace);
789 }
790
791 kfree(acl);
792
793 return;
794}
795
796int
797nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, 789nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
798 int whotype, uid_t who) 790 int whotype, uid_t who)
799{ 791{
800 struct nfs4_ace *ace; 792 struct nfs4_ace *ace = acl->aces + acl->naces;
801
802 if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
803 return -ENOMEM;
804 793
805 ace->type = type; 794 ace->type = type;
806 ace->flag = flag; 795 ace->flag = flag;
@@ -808,10 +797,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
808 ace->whotype = whotype; 797 ace->whotype = whotype;
809 ace->who = who; 798 ace->who = who;
810 799
811 list_add_tail(&ace->l_ace, &acl->ace_head);
812 acl->naces++; 800 acl->naces++;
813
814 return 0;
815} 801}
816 802
817static struct { 803static struct {
@@ -865,7 +851,6 @@ nfs4_acl_write_who(int who, char *p)
865} 851}
866 852
867EXPORT_SYMBOL(nfs4_acl_new); 853EXPORT_SYMBOL(nfs4_acl_new);
868EXPORT_SYMBOL(nfs4_acl_free);
869EXPORT_SYMBOL(nfs4_acl_add_ace); 854EXPORT_SYMBOL(nfs4_acl_add_ace);
870EXPORT_SYMBOL(nfs4_acl_get_whotype); 855EXPORT_SYMBOL(nfs4_acl_get_whotype);
871EXPORT_SYMBOL(nfs4_acl_write_who); 856EXPORT_SYMBOL(nfs4_acl_write_who);