aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4acl.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2013-02-02 08:18:08 -0500
committerEric W. Biederman <ebiederm@xmission.com>2013-02-13 09:16:06 -0500
commitab8e4aee0a3f73d1b12e6d63b42075f0586ad4fd (patch)
treedc58ca18da44877a8274e423079a9aee65dce7fa /fs/nfsd/nfs4acl.c
parent7c19723e997a3990951c0db0500009fb90c0c5b9 (diff)
nfsd: Handle kuids and kgids in the nfs4acl to posix_acl conversion
In struct nfs4_ace remove the member who and replace it with an anonymous union holding who_uid and who_gid. Allowing typesafe storage uids and gids. Add a helper pace_gt for sorting posix_acl_entries. In struct posix_user_ace_state to replace uid with a union of kuid_t uid and kgid_t gid. Remove all initializations of the deprecated posic_acl_entry e_id field. Which is not present when user namespaces are enabled. Split find_uid into two functions find_uid and find_gid that work in a typesafe manner. In nfs4xdr update nfsd4_encode_fattr to deal with the changes in struct nfs4_ace. Rewrite nfsd4_encode_name to take a kuid_t and a kgid_t instead of a generic id and flag if it is a group or a uid. Replace the group flag with a test for a valid gid. Modify nfsd4_encode_user to take a kuid_t and call the modifed nfsd4_encode_name. Modify nfsd4_encode_group to take a kgid_t and call the modified nfsd4_encode_name. Modify nfsd4_encode_aclname to take an ace instead of taking the fields of an ace broken out. This allows it to detect if the ace is for a user or a group and to pass the appropriate value while still being typesafe. Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r--fs/nfsd/nfs4acl.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 9c51aff02ae2..8a50b3c18093 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -264,7 +264,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
264 ace->flag = eflag; 264 ace->flag = eflag;
265 ace->access_mask = deny_mask_from_posix(deny, flags); 265 ace->access_mask = deny_mask_from_posix(deny, flags);
266 ace->whotype = NFS4_ACL_WHO_NAMED; 266 ace->whotype = NFS4_ACL_WHO_NAMED;
267 ace->who = pa->e_id; 267 ace->who_uid = pa->e_uid;
268 ace++; 268 ace++;
269 acl->naces++; 269 acl->naces++;
270 } 270 }
@@ -273,7 +273,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
273 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask, 273 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
274 flags); 274 flags);
275 ace->whotype = NFS4_ACL_WHO_NAMED; 275 ace->whotype = NFS4_ACL_WHO_NAMED;
276 ace->who = pa->e_id; 276 ace->who_uid = pa->e_uid;
277 ace++; 277 ace++;
278 acl->naces++; 278 acl->naces++;
279 pa++; 279 pa++;
@@ -300,7 +300,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
300 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask, 300 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
301 flags); 301 flags);
302 ace->whotype = NFS4_ACL_WHO_NAMED; 302 ace->whotype = NFS4_ACL_WHO_NAMED;
303 ace->who = pa->e_id; 303 ace->who_gid = pa->e_gid;
304 ace++; 304 ace++;
305 acl->naces++; 305 acl->naces++;
306 pa++; 306 pa++;
@@ -329,7 +329,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
329 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; 329 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
330 ace->access_mask = deny_mask_from_posix(deny, flags); 330 ace->access_mask = deny_mask_from_posix(deny, flags);
331 ace->whotype = NFS4_ACL_WHO_NAMED; 331 ace->whotype = NFS4_ACL_WHO_NAMED;
332 ace->who = pa->e_id; 332 ace->who_gid = pa->e_gid;
333 ace++; 333 ace++;
334 acl->naces++; 334 acl->naces++;
335 } 335 }
@@ -345,6 +345,18 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
345 acl->naces++; 345 acl->naces++;
346} 346}
347 347
348static bool
349pace_gt(struct posix_acl_entry *pace1, struct posix_acl_entry *pace2)
350{
351 if (pace1->e_tag != pace2->e_tag)
352 return pace1->e_tag > pace2->e_tag;
353 if (pace1->e_tag == ACL_USER)
354 return uid_gt(pace1->e_uid, pace2->e_uid);
355 if (pace1->e_tag == ACL_GROUP)
356 return gid_gt(pace1->e_gid, pace2->e_gid);
357 return false;
358}
359
348static void 360static void
349sort_pacl_range(struct posix_acl *pacl, int start, int end) { 361sort_pacl_range(struct posix_acl *pacl, int start, int end) {
350 int sorted = 0, i; 362 int sorted = 0, i;
@@ -355,8 +367,8 @@ sort_pacl_range(struct posix_acl *pacl, int start, int end) {
355 while (!sorted) { 367 while (!sorted) {
356 sorted = 1; 368 sorted = 1;
357 for (i = start; i < end; i++) { 369 for (i = start; i < end; i++) {
358 if (pacl->a_entries[i].e_id 370 if (pace_gt(&pacl->a_entries[i],
359 > pacl->a_entries[i+1].e_id) { 371 &pacl->a_entries[i+1])) {
360 sorted = 0; 372 sorted = 0;
361 tmp = pacl->a_entries[i]; 373 tmp = pacl->a_entries[i];
362 pacl->a_entries[i] = pacl->a_entries[i+1]; 374 pacl->a_entries[i] = pacl->a_entries[i+1];
@@ -398,7 +410,10 @@ struct posix_ace_state {
398}; 410};
399 411
400struct posix_user_ace_state { 412struct posix_user_ace_state {
401 uid_t uid; 413 union {
414 kuid_t uid;
415 kgid_t gid;
416 };
402 struct posix_ace_state perms; 417 struct posix_ace_state perms;
403}; 418};
404 419
@@ -521,7 +536,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
521 if (error) 536 if (error)
522 goto out_err; 537 goto out_err;
523 low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags); 538 low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
524 pace->e_id = ACL_UNDEFINED_ID;
525 539
526 for (i=0; i < state->users->n; i++) { 540 for (i=0; i < state->users->n; i++) {
527 pace++; 541 pace++;
@@ -531,7 +545,7 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
531 goto out_err; 545 goto out_err;
532 low_mode_from_nfs4(state->users->aces[i].perms.allow, 546 low_mode_from_nfs4(state->users->aces[i].perms.allow,
533 &pace->e_perm, flags); 547 &pace->e_perm, flags);
534 pace->e_id = state->users->aces[i].uid; 548 pace->e_uid = state->users->aces[i].uid;
535 add_to_mask(state, &state->users->aces[i].perms); 549 add_to_mask(state, &state->users->aces[i].perms);
536 } 550 }
537 551
@@ -541,7 +555,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
541 if (error) 555 if (error)
542 goto out_err; 556 goto out_err;
543 low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags); 557 low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
544 pace->e_id = ACL_UNDEFINED_ID;
545 add_to_mask(state, &state->group); 558 add_to_mask(state, &state->group);
546 559
547 for (i=0; i < state->groups->n; i++) { 560 for (i=0; i < state->groups->n; i++) {
@@ -552,14 +565,13 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
552 goto out_err; 565 goto out_err;
553 low_mode_from_nfs4(state->groups->aces[i].perms.allow, 566 low_mode_from_nfs4(state->groups->aces[i].perms.allow,
554 &pace->e_perm, flags); 567 &pace->e_perm, flags);
555 pace->e_id = state->groups->aces[i].uid; 568 pace->e_gid = state->groups->aces[i].gid;
556 add_to_mask(state, &state->groups->aces[i].perms); 569 add_to_mask(state, &state->groups->aces[i].perms);
557 } 570 }
558 571
559 pace++; 572 pace++;
560 pace->e_tag = ACL_MASK; 573 pace->e_tag = ACL_MASK;
561 low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags); 574 low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
562 pace->e_id = ACL_UNDEFINED_ID;
563 575
564 pace++; 576 pace++;
565 pace->e_tag = ACL_OTHER; 577 pace->e_tag = ACL_OTHER;
@@ -567,7 +579,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
567 if (error) 579 if (error)
568 goto out_err; 580 goto out_err;
569 low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags); 581 low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
570 pace->e_id = ACL_UNDEFINED_ID;
571 582
572 return pacl; 583 return pacl;
573out_err: 584out_err:
@@ -587,12 +598,13 @@ static inline void deny_bits(struct posix_ace_state *astate, u32 mask)
587 astate->deny |= mask & ~astate->allow; 598 astate->deny |= mask & ~astate->allow;
588} 599}
589 600
590static int find_uid(struct posix_acl_state *state, struct posix_ace_state_array *a, uid_t uid) 601static int find_uid(struct posix_acl_state *state, kuid_t uid)
591{ 602{
603 struct posix_ace_state_array *a = state->users;
592 int i; 604 int i;
593 605
594 for (i = 0; i < a->n; i++) 606 for (i = 0; i < a->n; i++)
595 if (a->aces[i].uid == uid) 607 if (uid_eq(a->aces[i].uid, uid))
596 return i; 608 return i;
597 /* Not found: */ 609 /* Not found: */
598 a->n++; 610 a->n++;
@@ -603,6 +615,23 @@ static int find_uid(struct posix_acl_state *state, struct posix_ace_state_array
603 return i; 615 return i;
604} 616}
605 617
618static int find_gid(struct posix_acl_state *state, kgid_t gid)
619{
620 struct posix_ace_state_array *a = state->groups;
621 int i;
622
623 for (i = 0; i < a->n; i++)
624 if (gid_eq(a->aces[i].gid, gid))
625 return i;
626 /* Not found: */
627 a->n++;
628 a->aces[i].gid = gid;
629 a->aces[i].perms.allow = state->everyone.allow;
630 a->aces[i].perms.deny = state->everyone.deny;
631
632 return i;
633}
634
606static void deny_bits_array(struct posix_ace_state_array *a, u32 mask) 635static void deny_bits_array(struct posix_ace_state_array *a, u32 mask)
607{ 636{
608 int i; 637 int i;
@@ -636,7 +665,7 @@ static void process_one_v4_ace(struct posix_acl_state *state,
636 } 665 }
637 break; 666 break;
638 case ACL_USER: 667 case ACL_USER:
639 i = find_uid(state, state->users, ace->who); 668 i = find_uid(state, ace->who_uid);
640 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { 669 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
641 allow_bits(&state->users->aces[i].perms, mask); 670 allow_bits(&state->users->aces[i].perms, mask);
642 } else { 671 } else {
@@ -658,7 +687,7 @@ static void process_one_v4_ace(struct posix_acl_state *state,
658 } 687 }
659 break; 688 break;
660 case ACL_GROUP: 689 case ACL_GROUP:
661 i = find_uid(state, state->groups, ace->who); 690 i = find_gid(state, ace->who_gid);
662 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { 691 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
663 allow_bits(&state->groups->aces[i].perms, mask); 692 allow_bits(&state->groups->aces[i].perms, mask);
664 } else { 693 } else {