aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss
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/auth_gss
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/auth_gss')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c45
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c18
2 files changed, 42 insertions, 21 deletions
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;