aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcauth_unix.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-25 19:00:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-25 19:00:49 -0500
commit94f2f14234178f118545a0be60a6371ddeb229b7 (patch)
tree313af6e9e255e9060fc24c836cd71ce712502b17 /net/sunrpc/svcauth_unix.c
parent8d168f71551ec2a6528d01d0389b7a73c091e3e7 (diff)
parent139321c65c0584cd65c4c87a5eb3fdb4fdbd0e19 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull user namespace and namespace infrastructure changes from Eric W Biederman: "This set of changes starts with a few small enhnacements to the user namespace. reboot support, allowing more arbitrary mappings, and support for mounting devpts, ramfs, tmpfs, and mqueuefs as just the user namespace root. I do my best to document that if you care about limiting your unprivileged users that when you have the user namespace support enabled you will need to enable memory control groups. There is a minor bug fix to prevent overflowing the stack if someone creates way too many user namespaces. The bulk of the changes are a continuation of the kuid/kgid push down work through the filesystems. These changes make using uids and gids typesafe which ensures that these filesystems are safe to use when multiple user namespaces are in use. The filesystems converted for 3.9 are ceph, 9p, afs, ocfs2, gfs2, ncpfs, nfs, nfsd, and cifs. The changes for these filesystems were a little more involved so I split the changes into smaller hopefully obviously correct changes. XFS is the only filesystem that remains. I was hoping I could get that in this release so that user namespace support would be enabled with an allyesconfig or an allmodconfig but it looks like the xfs changes need another couple of days before it they are ready." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (93 commits) cifs: Enable building with user namespaces enabled. cifs: Convert struct cifs_ses to use a kuid_t and a kgid_t cifs: Convert struct cifs_sb_info to use kuids and kgids cifs: Modify struct smb_vol to use kuids and kgids cifs: Convert struct cifsFileInfo to use a kuid cifs: Convert struct cifs_fattr to use kuid and kgids cifs: Convert struct tcon_link to use a kuid. cifs: Modify struct cifs_unix_set_info_args to hold a kuid_t and a kgid_t cifs: Convert from a kuid before printing current_fsuid cifs: Use kuids and kgids SID to uid/gid mapping cifs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring_alloc cifs: Use BUILD_BUG_ON to validate uids and gids are the same size cifs: Override unmappable incoming uids and gids nfsd: Enable building with user namespaces enabled. nfsd: Properly compare and initialize kuids and kgids nfsd: Store ex_anon_uid and ex_anon_gid as kuids and kgids nfsd: Modify nfsd4_cb_sec to use kuids and kgids nfsd: Handle kuids and kgids in the nfs4acl to posix_acl conversion nfsd: Convert nfsxdr to use kuids and kgids nfsd: Convert nfs3xdr to use kuids and kgids ...
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r--net/sunrpc/svcauth_unix.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 4d0129203733..a1852e19ed0c 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -415,10 +415,15 @@ svcauth_unix_info_release(struct svc_xprt *xpt)
415 415
416struct unix_gid { 416struct unix_gid {
417 struct cache_head h; 417 struct cache_head h;
418 uid_t uid; 418 kuid_t uid;
419 struct group_info *gi; 419 struct group_info *gi;
420}; 420};
421 421
422static int unix_gid_hash(kuid_t uid)
423{
424 return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
425}
426
422static void unix_gid_put(struct kref *kref) 427static void unix_gid_put(struct kref *kref)
423{ 428{
424 struct cache_head *item = container_of(kref, struct cache_head, ref); 429 struct cache_head *item = container_of(kref, struct cache_head, ref);
@@ -433,7 +438,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
433{ 438{
434 struct unix_gid *orig = container_of(corig, struct unix_gid, h); 439 struct unix_gid *orig = container_of(corig, struct unix_gid, h);
435 struct unix_gid *new = container_of(cnew, struct unix_gid, h); 440 struct unix_gid *new = container_of(cnew, struct unix_gid, h);
436 return orig->uid == new->uid; 441 return uid_eq(orig->uid, new->uid);
437} 442}
438static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) 443static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
439{ 444{
@@ -465,7 +470,7 @@ static void unix_gid_request(struct cache_detail *cd,
465 char tuid[20]; 470 char tuid[20];
466 struct unix_gid *ug = container_of(h, struct unix_gid, h); 471 struct unix_gid *ug = container_of(h, struct unix_gid, h);
467 472
468 snprintf(tuid, 20, "%u", ug->uid); 473 snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
469 qword_add(bpp, blen, tuid); 474 qword_add(bpp, blen, tuid);
470 (*bpp)[-1] = '\n'; 475 (*bpp)[-1] = '\n';
471} 476}
@@ -475,13 +480,14 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
475 return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); 480 return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request);
476} 481}
477 482
478static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); 483static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid);
479 484
480static int unix_gid_parse(struct cache_detail *cd, 485static int unix_gid_parse(struct cache_detail *cd,
481 char *mesg, int mlen) 486 char *mesg, int mlen)
482{ 487{
483 /* uid expiry Ngid gid0 gid1 ... gidN-1 */ 488 /* uid expiry Ngid gid0 gid1 ... gidN-1 */
484 int uid; 489 int id;
490 kuid_t uid;
485 int gids; 491 int gids;
486 int rv; 492 int rv;
487 int i; 493 int i;
@@ -493,9 +499,12 @@ static int unix_gid_parse(struct cache_detail *cd,
493 return -EINVAL; 499 return -EINVAL;
494 mesg[mlen-1] = 0; 500 mesg[mlen-1] = 0;
495 501
496 rv = get_int(&mesg, &uid); 502 rv = get_int(&mesg, &id);
497 if (rv) 503 if (rv)
498 return -EINVAL; 504 return -EINVAL;
505 uid = make_kuid(&init_user_ns, id);
506 if (!uid_valid(uid))
507 return -EINVAL;
499 ug.uid = uid; 508 ug.uid = uid;
500 509
501 expiry = get_expiry(&mesg); 510 expiry = get_expiry(&mesg);
@@ -530,7 +539,7 @@ static int unix_gid_parse(struct cache_detail *cd,
530 ug.h.expiry_time = expiry; 539 ug.h.expiry_time = expiry;
531 ch = sunrpc_cache_update(cd, 540 ch = sunrpc_cache_update(cd,
532 &ug.h, &ugp->h, 541 &ug.h, &ugp->h,
533 hash_long(uid, GID_HASHBITS)); 542 unix_gid_hash(uid));
534 if (!ch) 543 if (!ch)
535 err = -ENOMEM; 544 err = -ENOMEM;
536 else { 545 else {
@@ -549,7 +558,7 @@ static int unix_gid_show(struct seq_file *m,
549 struct cache_detail *cd, 558 struct cache_detail *cd,
550 struct cache_head *h) 559 struct cache_head *h)
551{ 560{
552 struct user_namespace *user_ns = current_user_ns(); 561 struct user_namespace *user_ns = &init_user_ns;
553 struct unix_gid *ug; 562 struct unix_gid *ug;
554 int i; 563 int i;
555 int glen; 564 int glen;
@@ -565,7 +574,7 @@ static int unix_gid_show(struct seq_file *m,
565 else 574 else
566 glen = 0; 575 glen = 0;
567 576
568 seq_printf(m, "%u %d:", ug->uid, glen); 577 seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
569 for (i = 0; i < glen; i++) 578 for (i = 0; i < glen; i++)
570 seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); 579 seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i)));
571 seq_printf(m, "\n"); 580 seq_printf(m, "\n");
@@ -615,20 +624,20 @@ void unix_gid_cache_destroy(struct net *net)
615 cache_destroy_net(cd, net); 624 cache_destroy_net(cd, net);
616} 625}
617 626
618static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) 627static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)
619{ 628{
620 struct unix_gid ug; 629 struct unix_gid ug;
621 struct cache_head *ch; 630 struct cache_head *ch;
622 631
623 ug.uid = uid; 632 ug.uid = uid;
624 ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); 633 ch = sunrpc_cache_lookup(cd, &ug.h, unix_gid_hash(uid));
625 if (ch) 634 if (ch)
626 return container_of(ch, struct unix_gid, h); 635 return container_of(ch, struct unix_gid, h);
627 else 636 else
628 return NULL; 637 return NULL;
629} 638}
630 639
631static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) 640static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
632{ 641{
633 struct unix_gid *ug; 642 struct unix_gid *ug;
634 struct group_info *gi; 643 struct group_info *gi;
@@ -750,8 +759,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
750 } 759 }
751 760
752 /* Signal that mapping to nobody uid/gid is required */ 761 /* Signal that mapping to nobody uid/gid is required */
753 cred->cr_uid = (uid_t) -1; 762 cred->cr_uid = INVALID_UID;
754 cred->cr_gid = (gid_t) -1; 763 cred->cr_gid = INVALID_GID;
755 cred->cr_group_info = groups_alloc(0); 764 cred->cr_group_info = groups_alloc(0);
756 if (cred->cr_group_info == NULL) 765 if (cred->cr_group_info == NULL)
757 return SVC_CLOSE; /* kmalloc failure - client must retry */ 766 return SVC_CLOSE; /* kmalloc failure - client must retry */
@@ -812,8 +821,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
812 argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ 821 argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */
813 argv->iov_len -= slen*4; 822 argv->iov_len -= slen*4;
814 823
815 cred->cr_uid = svc_getnl(argv); /* uid */ 824 cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
816 cred->cr_gid = svc_getnl(argv); /* gid */ 825 cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
826 if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid))
827 goto badcred;
817 slen = svc_getnl(argv); /* gids length */ 828 slen = svc_getnl(argv); /* gids length */
818 if (slen > 16 || (len -= (slen + 2)*4) < 0) 829 if (slen > 16 || (len -= (slen + 2)*4) < 0)
819 goto badcred; 830 goto badcred;