aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
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
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')
-rw-r--r--net/sunrpc/auth.c6
-rw-r--r--net/sunrpc/auth_generic.c16
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c45
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c18
-rw-r--r--net/sunrpc/auth_unix.c36
-rw-r--r--net/sunrpc/svcauth_unix.c43
6 files changed, 96 insertions, 68 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index b5c067bccc45..392adc41e2e5 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -412,7 +412,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
412 *entry, *new; 412 *entry, *new;
413 unsigned int nr; 413 unsigned int nr;
414 414
415 nr = hash_long(acred->uid, cache->hashbits); 415 nr = hash_long(from_kuid(&init_user_ns, acred->uid), cache->hashbits);
416 416
417 rcu_read_lock(); 417 rcu_read_lock();
418 hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { 418 hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
@@ -519,8 +519,8 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
519{ 519{
520 struct rpc_auth *auth = task->tk_client->cl_auth; 520 struct rpc_auth *auth = task->tk_client->cl_auth;
521 struct auth_cred acred = { 521 struct auth_cred acred = {
522 .uid = 0, 522 .uid = GLOBAL_ROOT_UID,
523 .gid = 0, 523 .gid = GLOBAL_ROOT_GID,
524 }; 524 };
525 525
526 dprintk("RPC: %5u looking up %s cred\n", 526 dprintk("RPC: %5u looking up %s cred\n",
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 6ed6f201b022..b6badafc6494 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -18,8 +18,8 @@
18# define RPCDBG_FACILITY RPCDBG_AUTH 18# define RPCDBG_FACILITY RPCDBG_AUTH
19#endif 19#endif
20 20
21#define RPC_MACHINE_CRED_USERID ((uid_t)0) 21#define RPC_MACHINE_CRED_USERID GLOBAL_ROOT_UID
22#define RPC_MACHINE_CRED_GROUPID ((gid_t)0) 22#define RPC_MACHINE_CRED_GROUPID GLOBAL_ROOT_GID
23 23
24struct generic_cred { 24struct generic_cred {
25 struct rpc_cred gc_base; 25 struct rpc_cred gc_base;
@@ -96,7 +96,9 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
96 96
97 dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", 97 dprintk("RPC: allocated %s cred %p for uid %d gid %d\n",
98 gcred->acred.machine_cred ? "machine" : "generic", 98 gcred->acred.machine_cred ? "machine" : "generic",
99 gcred, acred->uid, acred->gid); 99 gcred,
100 from_kuid(&init_user_ns, acred->uid),
101 from_kgid(&init_user_ns, acred->gid));
100 return &gcred->gc_base; 102 return &gcred->gc_base;
101} 103}
102 104
@@ -129,8 +131,8 @@ machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flag
129{ 131{
130 if (!gcred->acred.machine_cred || 132 if (!gcred->acred.machine_cred ||
131 gcred->acred.principal != acred->principal || 133 gcred->acred.principal != acred->principal ||
132 gcred->acred.uid != acred->uid || 134 !uid_eq(gcred->acred.uid, acred->uid) ||
133 gcred->acred.gid != acred->gid) 135 !gid_eq(gcred->acred.gid, acred->gid))
134 return 0; 136 return 0;
135 return 1; 137 return 1;
136} 138}
@@ -147,8 +149,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
147 if (acred->machine_cred) 149 if (acred->machine_cred)
148 return machine_cred_match(acred, gcred, flags); 150 return machine_cred_match(acred, gcred, flags);
149 151
150 if (gcred->acred.uid != acred->uid || 152 if (!uid_eq(gcred->acred.uid, acred->uid) ||
151 gcred->acred.gid != acred->gid || 153 !gid_eq(gcred->acred.gid, acred->gid) ||
152 gcred->acred.machine_cred != 0) 154 gcred->acred.machine_cred != 0)
153 goto out_nomatch; 155 goto out_nomatch;
154 156
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 911ef008b701..6ea29f4ed6c0 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -255,7 +255,7 @@ err:
255 255
256struct gss_upcall_msg { 256struct gss_upcall_msg {
257 atomic_t count; 257 atomic_t count;
258 uid_t uid; 258 kuid_t uid;
259 struct rpc_pipe_msg msg; 259 struct rpc_pipe_msg msg;
260 struct list_head list; 260 struct list_head list;
261 struct gss_auth *auth; 261 struct gss_auth *auth;
@@ -302,11 +302,11 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
302} 302}
303 303
304static struct gss_upcall_msg * 304static struct gss_upcall_msg *
305__gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) 305__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid)
306{ 306{
307 struct gss_upcall_msg *pos; 307 struct gss_upcall_msg *pos;
308 list_for_each_entry(pos, &pipe->in_downcall, list) { 308 list_for_each_entry(pos, &pipe->in_downcall, list) {
309 if (pos->uid != uid) 309 if (!uid_eq(pos->uid, uid))
310 continue; 310 continue;
311 atomic_inc(&pos->count); 311 atomic_inc(&pos->count);
312 dprintk("RPC: %s found msg %p\n", __func__, pos); 312 dprintk("RPC: %s found msg %p\n", __func__, pos);
@@ -394,8 +394,11 @@ gss_upcall_callback(struct rpc_task *task)
394 394
395static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) 395static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
396{ 396{
397 gss_msg->msg.data = &gss_msg->uid; 397 uid_t uid = from_kuid(&init_user_ns, gss_msg->uid);
398 gss_msg->msg.len = sizeof(gss_msg->uid); 398 memcpy(gss_msg->databuf, &uid, sizeof(uid));
399 gss_msg->msg.data = gss_msg->databuf;
400 gss_msg->msg.len = sizeof(uid);
401 BUG_ON(sizeof(uid) > UPCALL_BUF_LEN);
399} 402}
400 403
401static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, 404static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
@@ -408,7 +411,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
408 411
409 gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ", 412 gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ",
410 mech->gm_name, 413 mech->gm_name,
411 gss_msg->uid); 414 from_kuid(&init_user_ns, gss_msg->uid));
412 p += gss_msg->msg.len; 415 p += gss_msg->msg.len;
413 if (clnt->cl_principal) { 416 if (clnt->cl_principal) {
414 len = sprintf(p, "target=%s ", clnt->cl_principal); 417 len = sprintf(p, "target=%s ", clnt->cl_principal);
@@ -444,7 +447,7 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg,
444 447
445static struct gss_upcall_msg * 448static struct gss_upcall_msg *
446gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, 449gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt,
447 uid_t uid, const char *service_name) 450 kuid_t uid, const char *service_name)
448{ 451{
449 struct gss_upcall_msg *gss_msg; 452 struct gss_upcall_msg *gss_msg;
450 int vers; 453 int vers;
@@ -474,7 +477,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
474 struct gss_cred *gss_cred = container_of(cred, 477 struct gss_cred *gss_cred = container_of(cred,
475 struct gss_cred, gc_base); 478 struct gss_cred, gc_base);
476 struct gss_upcall_msg *gss_new, *gss_msg; 479 struct gss_upcall_msg *gss_new, *gss_msg;
477 uid_t uid = cred->cr_uid; 480 kuid_t uid = cred->cr_uid;
478 481
479 gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal); 482 gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal);
480 if (IS_ERR(gss_new)) 483 if (IS_ERR(gss_new))
@@ -516,7 +519,7 @@ gss_refresh_upcall(struct rpc_task *task)
516 int err = 0; 519 int err = 0;
517 520
518 dprintk("RPC: %5u %s for uid %u\n", 521 dprintk("RPC: %5u %s for uid %u\n",
519 task->tk_pid, __func__, cred->cr_uid); 522 task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid));
520 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); 523 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
521 if (PTR_ERR(gss_msg) == -EAGAIN) { 524 if (PTR_ERR(gss_msg) == -EAGAIN) {
522 /* XXX: warning on the first, under the assumption we 525 /* XXX: warning on the first, under the assumption we
@@ -548,7 +551,8 @@ gss_refresh_upcall(struct rpc_task *task)
548 gss_release_msg(gss_msg); 551 gss_release_msg(gss_msg);
549out: 552out:
550 dprintk("RPC: %5u %s for uid %u result %d\n", 553 dprintk("RPC: %5u %s for uid %u result %d\n",
551 task->tk_pid, __func__, cred->cr_uid, err); 554 task->tk_pid, __func__,
555 from_kuid(&init_user_ns, cred->cr_uid), err);
552 return err; 556 return err;
553} 557}
554 558
@@ -561,7 +565,8 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
561 DEFINE_WAIT(wait); 565 DEFINE_WAIT(wait);
562 int err = 0; 566 int err = 0;
563 567
564 dprintk("RPC: %s for uid %u\n", __func__, cred->cr_uid); 568 dprintk("RPC: %s for uid %u\n",
569 __func__, from_kuid(&init_user_ns, cred->cr_uid));
565retry: 570retry:
566 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 571 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
567 if (PTR_ERR(gss_msg) == -EAGAIN) { 572 if (PTR_ERR(gss_msg) == -EAGAIN) {
@@ -603,7 +608,7 @@ out_intr:
603 gss_release_msg(gss_msg); 608 gss_release_msg(gss_msg);
604out: 609out:
605 dprintk("RPC: %s for uid %u result %d\n", 610 dprintk("RPC: %s for uid %u result %d\n",
606 __func__, cred->cr_uid, err); 611 __func__, from_kuid(&init_user_ns, cred->cr_uid), err);
607 return err; 612 return err;
608} 613}
609 614
@@ -617,7 +622,8 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
617 struct gss_upcall_msg *gss_msg; 622 struct gss_upcall_msg *gss_msg;
618 struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe; 623 struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe;
619 struct gss_cl_ctx *ctx; 624 struct gss_cl_ctx *ctx;
620 uid_t uid; 625 uid_t id;
626 kuid_t uid;
621 ssize_t err = -EFBIG; 627 ssize_t err = -EFBIG;
622 628
623 if (mlen > MSG_BUF_MAXSIZE) 629 if (mlen > MSG_BUF_MAXSIZE)
@@ -632,12 +638,18 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
632 goto err; 638 goto err;
633 639
634 end = (const void *)((char *)buf + mlen); 640 end = (const void *)((char *)buf + mlen);
635 p = simple_get_bytes(buf, end, &uid, sizeof(uid)); 641 p = simple_get_bytes(buf, end, &id, sizeof(id));
636 if (IS_ERR(p)) { 642 if (IS_ERR(p)) {
637 err = PTR_ERR(p); 643 err = PTR_ERR(p);
638 goto err; 644 goto err;
639 } 645 }
640 646
647 uid = make_kuid(&init_user_ns, id);
648 if (!uid_valid(uid)) {
649 err = -EINVAL;
650 goto err;
651 }
652
641 err = -ENOMEM; 653 err = -ENOMEM;
642 ctx = gss_alloc_context(); 654 ctx = gss_alloc_context();
643 if (ctx == NULL) 655 if (ctx == NULL)
@@ -1058,7 +1070,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
1058 int err = -ENOMEM; 1070 int err = -ENOMEM;
1059 1071
1060 dprintk("RPC: %s for uid %d, flavor %d\n", 1072 dprintk("RPC: %s for uid %d, flavor %d\n",
1061 __func__, acred->uid, auth->au_flavor); 1073 __func__, from_kuid(&init_user_ns, acred->uid),
1074 auth->au_flavor);
1062 1075
1063 if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) 1076 if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS)))
1064 goto out_err; 1077 goto out_err;
@@ -1114,7 +1127,7 @@ out:
1114 } 1127 }
1115 if (gss_cred->gc_principal != NULL) 1128 if (gss_cred->gc_principal != NULL)
1116 return 0; 1129 return 0;
1117 return rc->cr_uid == acred->uid; 1130 return uid_eq(rc->cr_uid, acred->uid);
1118} 1131}
1119 1132
1120/* 1133/*
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 73e957386600..ecd1d58bf611 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -418,6 +418,7 @@ static int rsc_parse(struct cache_detail *cd,
418{ 418{
419 /* contexthandle expiry [ uid gid N <n gids> mechname ...mechdata... ] */ 419 /* contexthandle expiry [ uid gid N <n gids> mechname ...mechdata... ] */
420 char *buf = mesg; 420 char *buf = mesg;
421 int id;
421 int len, rv; 422 int len, rv;
422 struct rsc rsci, *rscp = NULL; 423 struct rsc rsci, *rscp = NULL;
423 time_t expiry; 424 time_t expiry;
@@ -444,7 +445,7 @@ static int rsc_parse(struct cache_detail *cd,
444 goto out; 445 goto out;
445 446
446 /* uid, or NEGATIVE */ 447 /* uid, or NEGATIVE */
447 rv = get_int(&mesg, &rsci.cred.cr_uid); 448 rv = get_int(&mesg, &id);
448 if (rv == -EINVAL) 449 if (rv == -EINVAL)
449 goto out; 450 goto out;
450 if (rv == -ENOENT) 451 if (rv == -ENOENT)
@@ -452,8 +453,16 @@ static int rsc_parse(struct cache_detail *cd,
452 else { 453 else {
453 int N, i; 454 int N, i;
454 455
456 /* uid */
457 rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
458 if (!uid_valid(rsci.cred.cr_uid))
459 goto out;
460
455 /* gid */ 461 /* gid */
456 if (get_int(&mesg, &rsci.cred.cr_gid)) 462 if (get_int(&mesg, &id))
463 goto out;
464 rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
465 if (!gid_valid(rsci.cred.cr_gid))
457 goto out; 466 goto out;
458 467
459 /* number of additional gid's */ 468 /* number of additional gid's */
@@ -467,11 +476,10 @@ static int rsc_parse(struct cache_detail *cd,
467 /* gid's */ 476 /* gid's */
468 status = -EINVAL; 477 status = -EINVAL;
469 for (i=0; i<N; i++) { 478 for (i=0; i<N; i++) {
470 gid_t gid;
471 kgid_t kgid; 479 kgid_t kgid;
472 if (get_int(&mesg, &gid)) 480 if (get_int(&mesg, &id))
473 goto out; 481 goto out;
474 kgid = make_kgid(&init_user_ns, gid); 482 kgid = make_kgid(&init_user_ns, id);
475 if (!gid_valid(kgid)) 483 if (!gid_valid(kgid))
476 goto out; 484 goto out;
477 GROUP_AT(rsci.cred.cr_group_info, i) = kgid; 485 GROUP_AT(rsci.cred.cr_group_info, i) = kgid;
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 52c5abdee211..dc37021fc3e5 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -18,8 +18,8 @@
18 18
19struct unx_cred { 19struct unx_cred {
20 struct rpc_cred uc_base; 20 struct rpc_cred uc_base;
21 gid_t uc_gid; 21 kgid_t uc_gid;
22 gid_t uc_gids[NFS_NGROUPS]; 22 kgid_t uc_gids[NFS_NGROUPS];
23}; 23};
24#define uc_uid uc_base.cr_uid 24#define uc_uid uc_base.cr_uid
25 25
@@ -65,7 +65,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
65 unsigned int i; 65 unsigned int i;
66 66
67 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n", 67 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
68 acred->uid, acred->gid); 68 from_kuid(&init_user_ns, acred->uid),
69 from_kgid(&init_user_ns, acred->gid));
69 70
70 if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS))) 71 if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS)))
71 return ERR_PTR(-ENOMEM); 72 return ERR_PTR(-ENOMEM);
@@ -79,13 +80,10 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
79 groups = NFS_NGROUPS; 80 groups = NFS_NGROUPS;
80 81
81 cred->uc_gid = acred->gid; 82 cred->uc_gid = acred->gid;
82 for (i = 0; i < groups; i++) { 83 for (i = 0; i < groups; i++)
83 gid_t gid; 84 cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
84 gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i));
85 cred->uc_gids[i] = gid;
86 }
87 if (i < NFS_NGROUPS) 85 if (i < NFS_NGROUPS)
88 cred->uc_gids[i] = NOGROUP; 86 cred->uc_gids[i] = INVALID_GID;
89 87
90 return &cred->uc_base; 88 return &cred->uc_base;
91} 89}
@@ -123,21 +121,17 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
123 unsigned int i; 121 unsigned int i;
124 122
125 123
126 if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid) 124 if (!uid_eq(cred->uc_uid, acred->uid) || !gid_eq(cred->uc_gid, acred->gid))
127 return 0; 125 return 0;
128 126
129 if (acred->group_info != NULL) 127 if (acred->group_info != NULL)
130 groups = acred->group_info->ngroups; 128 groups = acred->group_info->ngroups;
131 if (groups > NFS_NGROUPS) 129 if (groups > NFS_NGROUPS)
132 groups = NFS_NGROUPS; 130 groups = NFS_NGROUPS;
133 for (i = 0; i < groups ; i++) { 131 for (i = 0; i < groups ; i++)
134 gid_t gid; 132 if (!gid_eq(cred->uc_gids[i], GROUP_AT(acred->group_info, i)))
135 gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i));
136 if (cred->uc_gids[i] != gid)
137 return 0; 133 return 0;
138 } 134 if (groups < NFS_NGROUPS && gid_valid(cred->uc_gids[groups]))
139 if (groups < NFS_NGROUPS &&
140 cred->uc_gids[groups] != NOGROUP)
141 return 0; 135 return 0;
142 return 1; 136 return 1;
143} 137}
@@ -163,11 +157,11 @@ unx_marshal(struct rpc_task *task, __be32 *p)
163 */ 157 */
164 p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); 158 p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
165 159
166 *p++ = htonl((u32) cred->uc_uid); 160 *p++ = htonl((u32) from_kuid(&init_user_ns, cred->uc_uid));
167 *p++ = htonl((u32) cred->uc_gid); 161 *p++ = htonl((u32) from_kgid(&init_user_ns, cred->uc_gid));
168 hold = p++; 162 hold = p++;
169 for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++) 163 for (i = 0; i < 16 && gid_valid(cred->uc_gids[i]); i++)
170 *p++ = htonl((u32) cred->uc_gids[i]); 164 *p++ = htonl((u32) from_kgid(&init_user_ns, cred->uc_gids[i]));
171 *hold = htonl(p - hold - 1); /* gid array length */ 165 *hold = htonl(p - hold - 1); /* gid array length */
172 *base = htonl((p - base - 1) << 2); /* cred length */ 166 *base = htonl((p - base - 1) << 2); /* cred length */
173 167
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;