diff options
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r-- | fs/nfsd/nfs4acl.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 0a69cce33efe..832673b14587 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -416,6 +416,7 @@ struct posix_ace_state_array { | |||
416 | * calculated so far: */ | 416 | * calculated so far: */ |
417 | 417 | ||
418 | struct posix_acl_state { | 418 | struct posix_acl_state { |
419 | int empty; | ||
419 | struct posix_ace_state owner; | 420 | struct posix_ace_state owner; |
420 | struct posix_ace_state group; | 421 | struct posix_ace_state group; |
421 | struct posix_ace_state other; | 422 | struct posix_ace_state other; |
@@ -431,6 +432,7 @@ init_state(struct posix_acl_state *state, int cnt) | |||
431 | int alloc; | 432 | int alloc; |
432 | 433 | ||
433 | memset(state, 0, sizeof(struct posix_acl_state)); | 434 | memset(state, 0, sizeof(struct posix_acl_state)); |
435 | state->empty = 1; | ||
434 | /* | 436 | /* |
435 | * 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 |
436 | * 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 |
@@ -498,6 +500,20 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) | |||
498 | int nace; | 500 | int nace; |
499 | int i, error = 0; | 501 | int i, error = 0; |
500 | 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 | */ | ||
501 | nace = 4 + state->users->n + state->groups->n; | 517 | nace = 4 + state->users->n + state->groups->n; |
502 | pacl = posix_acl_alloc(nace, GFP_KERNEL); | 518 | pacl = posix_acl_alloc(nace, GFP_KERNEL); |
503 | if (!pacl) | 519 | if (!pacl) |
@@ -613,6 +629,8 @@ static void process_one_v4_ace(struct posix_acl_state *state, | |||
613 | u32 mask = ace->access_mask; | 629 | u32 mask = ace->access_mask; |
614 | int i; | 630 | int i; |
615 | 631 | ||
632 | state->empty = 0; | ||
633 | |||
616 | switch (ace2type(ace)) { | 634 | switch (ace2type(ace)) { |
617 | case ACL_USER_OBJ: | 635 | case ACL_USER_OBJ: |
618 | if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { | 636 | if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { |
@@ -717,7 +735,8 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, | |||
717 | ret = PTR_ERR(*pacl); | 735 | ret = PTR_ERR(*pacl); |
718 | goto out_dstate; | 736 | goto out_dstate; |
719 | } | 737 | } |
720 | *dpacl = posix_state_to_acl(&default_acl_state, flags); | 738 | *dpacl = posix_state_to_acl(&default_acl_state, |
739 | flags | NFS4_ACL_TYPE_DEFAULT); | ||
721 | if (IS_ERR(*dpacl)) { | 740 | if (IS_ERR(*dpacl)) { |
722 | ret = PTR_ERR(*dpacl); | 741 | ret = PTR_ERR(*dpacl); |
723 | posix_acl_release(*pacl); | 742 | posix_acl_release(*pacl); |