diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 19:00:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 19:00:49 -0500 |
commit | 94f2f14234178f118545a0be60a6371ddeb229b7 (patch) | |
tree | 313af6e9e255e9060fc24c836cd71ce712502b17 /net/sunrpc/auth_gss | |
parent | 8d168f71551ec2a6528d01d0389b7a73c091e3e7 (diff) | |
parent | 139321c65c0584cd65c4c87a5eb3fdb4fdbd0e19 (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.c | 45 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 18 |
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 | ||
256 | struct gss_upcall_msg { | 256 | struct 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 | ||
304 | static struct gss_upcall_msg * | 304 | static 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 | ||
395 | static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) | 395 | static 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 | ||
401 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | 404 | static 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 | ||
445 | static struct gss_upcall_msg * | 448 | static struct gss_upcall_msg * |
446 | gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | 449 | gss_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); |
549 | out: | 552 | out: |
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)); | ||
565 | retry: | 570 | retry: |
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); |
604 | out: | 609 | out: |
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; |