From bf37f794372d5b8fda66702e1f3e70d4f07b6533 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 15:55:38 -0800 Subject: sunrpc: Use userns friendly constants. Instead of (uid_t)0 use GLOBAL_ROOT_UID. Instead of (gid_t)0 use GLOBAL_ROOT_GID. Instead of (uid_t)-1 use INVALID_UID Instead of (gid_t)-1 use INVALID_GID. Instead of NOGROUP use INVALID_GID. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth.c | 4 ++-- net/sunrpc/auth_generic.c | 4 ++-- net/sunrpc/auth_unix.c | 6 +++--- net/sunrpc/svcauth_unix.c | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index b5c067bccc4..4cd0ecfe983 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -519,8 +519,8 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) { struct rpc_auth *auth = task->tk_client->cl_auth; struct auth_cred acred = { - .uid = 0, - .gid = 0, + .uid = GLOBAL_ROOT_UID, + .gid = GLOBAL_ROOT_GID, }; dprintk("RPC: %5u looking up %s cred\n", diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 6ed6f201b02..9d2e0b04559 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -18,8 +18,8 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif -#define RPC_MACHINE_CRED_USERID ((uid_t)0) -#define RPC_MACHINE_CRED_GROUPID ((gid_t)0) +#define RPC_MACHINE_CRED_USERID GLOBAL_ROOT_UID +#define RPC_MACHINE_CRED_GROUPID GLOBAL_ROOT_GID struct generic_cred { struct rpc_cred gc_base; diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 52c5abdee21..2f8627082fa 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -85,7 +85,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) cred->uc_gids[i] = gid; } if (i < NFS_NGROUPS) - cred->uc_gids[i] = NOGROUP; + cred->uc_gids[i] = INVALID_GID; return &cred->uc_base; } @@ -137,7 +137,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) return 0; } if (groups < NFS_NGROUPS && - cred->uc_gids[groups] != NOGROUP) + cred->uc_gids[groups] != INVALID_GID) return 0; return 1; } @@ -166,7 +166,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) *p++ = htonl((u32) cred->uc_uid); *p++ = htonl((u32) cred->uc_gid); hold = p++; - for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++) + for (i = 0; i < 16 && cred->uc_gids[i] != INVALID_GID; i++) *p++ = htonl((u32) cred->uc_gids[i]); *hold = htonl(p - hold - 1); /* gid array length */ *base = htonl((p - base - 1) << 2); /* cred length */ diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4d012920373..c8cb5dc8d87 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -750,8 +750,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) } /* Signal that mapping to nobody uid/gid is required */ - cred->cr_uid = (uid_t) -1; - cred->cr_gid = (gid_t) -1; + cred->cr_uid = INVALID_UID; + cred->cr_gid = INVALID_GID; cred->cr_group_info = groups_alloc(0); if (cred->cr_group_info == NULL) return SVC_CLOSE; /* kmalloc failure - client must retry */ -- cgit v1.2.3 From 7eaf040b720bc8c0ce5cd49151ca194ca2d56842 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 16:31:17 -0800 Subject: sunrpc: Use kuid_t and kgid_t where appropriate Convert variables that store uids and gids to be of type kuid_t and kgid_t instead of type uid_t and gid_t. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_gss/auth_gss.c | 8 ++++---- net/sunrpc/auth_unix.c | 4 ++-- net/sunrpc/svcauth_unix.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6e5c824b040..4daab81ca33 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -256,7 +256,7 @@ err: struct gss_upcall_msg { atomic_t count; - uid_t uid; + kuid_t uid; struct rpc_pipe_msg msg; struct list_head list; struct gss_auth *auth; @@ -303,7 +303,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) } static struct gss_upcall_msg * -__gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) +__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid) { struct gss_upcall_msg *pos; list_for_each_entry(pos, &pipe->in_downcall, list) { @@ -445,7 +445,7 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg, static struct gss_upcall_msg * gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, - uid_t uid, const char *service_name) + kuid_t uid, const char *service_name) { struct gss_upcall_msg *gss_msg; int vers; @@ -475,7 +475,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_upcall_msg *gss_new, *gss_msg; - uid_t uid = cred->cr_uid; + kuid_t uid = cred->cr_uid; gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal); if (IS_ERR(gss_new)) diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 2f8627082fa..372d9156f6e 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -18,8 +18,8 @@ struct unx_cred { struct rpc_cred uc_base; - gid_t uc_gid; - gid_t uc_gids[NFS_NGROUPS]; + kgid_t uc_gid; + kgid_t uc_gids[NFS_NGROUPS]; }; #define uc_uid uc_base.cr_uid diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index c8cb5dc8d87..caae662f9fa 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -415,7 +415,7 @@ svcauth_unix_info_release(struct svc_xprt *xpt) struct unix_gid { struct cache_head h; - uid_t uid; + kuid_t uid; struct group_info *gi; }; @@ -475,7 +475,7 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); } -static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); +static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid); static int unix_gid_parse(struct cache_detail *cd, char *mesg, int mlen) @@ -615,7 +615,7 @@ void unix_gid_cache_destroy(struct net *net) cache_destroy_net(cd, net); } -static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) +static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid) { struct unix_gid ug; struct cache_head *ch; @@ -628,7 +628,7 @@ static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) return NULL; } -static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) +static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp) { struct unix_gid *ug; struct group_info *gi; -- cgit v1.2.3 From 0b4d51b02a2e941beec6f02a6c7a32c5a28c5b43 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 16:39:32 -0800 Subject: sunrpc: Use uid_eq and gid_eq where appropriate When comparing uids use uid_eq instead of ==. When comparing gids use gid_eq instead of ==. And unfortunate cost of type safety. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_generic.c | 8 ++++---- net/sunrpc/auth_gss/auth_gss.c | 4 ++-- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/svcauth_unix.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 9d2e0b04559..bff3e4730f6 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -129,8 +129,8 @@ machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flag { if (!gcred->acred.machine_cred || gcred->acred.principal != acred->principal || - gcred->acred.uid != acred->uid || - gcred->acred.gid != acred->gid) + !uid_eq(gcred->acred.uid, acred->uid) || + !gid_eq(gcred->acred.gid, acred->gid)) return 0; return 1; } @@ -147,8 +147,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) if (acred->machine_cred) return machine_cred_match(acred, gcred, flags); - if (gcred->acred.uid != acred->uid || - gcred->acred.gid != acred->gid || + if (!uid_eq(gcred->acred.uid, acred->uid) || + !gid_eq(gcred->acred.gid, acred->gid) || gcred->acred.machine_cred != 0) goto out_nomatch; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 4daab81ca33..1b8b3e4fad4 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -307,7 +307,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid) { struct gss_upcall_msg *pos; list_for_each_entry(pos, &pipe->in_downcall, list) { - if (pos->uid != uid) + if (!uid_eq(pos->uid, uid)) continue; atomic_inc(&pos->count); dprintk("RPC: %s found msg %p\n", __func__, pos); @@ -1115,7 +1115,7 @@ out: } if (gss_cred->gc_principal != NULL) return 0; - return rc->cr_uid == acred->uid; + return uid_eq(rc->cr_uid, acred->uid); } /* diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 372d9156f6e..8365a9cade9 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -123,7 +123,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) unsigned int i; - if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid) + if (!uid_eq(cred->uc_uid, acred->uid) || !gid_eq(cred->uc_gid, acred->gid)) return 0; if (acred->group_info != NULL) diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index caae662f9fa..92166b57ec7 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -433,7 +433,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) { struct unix_gid *orig = container_of(corig, struct unix_gid, h); struct unix_gid *new = container_of(cnew, struct unix_gid, h); - return orig->uid == new->uid; + return uid_eq(orig->uid, new->uid); } static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) { -- cgit v1.2.3 From 9132adb0212c7ddf37d1c2a26c12f8fe7706827d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 16:46:42 -0800 Subject: sunrpc: Simplify auth_unix now that everything is a kgid_t In unx_create_cred directly assign gids from acred->group_info to cred->uc_gids. In unx_match directly compare uc_gids with group_info. Now that both group_info and unx_cred gids are stored as kgids this is valid and the extra layer of translation can be removed. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_unix.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 8365a9cade9..9f3885745fb 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -79,11 +79,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) groups = NFS_NGROUPS; cred->uc_gid = acred->gid; - for (i = 0; i < groups; i++) { - gid_t gid; - gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i)); - cred->uc_gids[i] = gid; - } + for (i = 0; i < groups; i++) + cred->uc_gids[i] = GROUP_AT(acred->group_info, i); if (i < NFS_NGROUPS) cred->uc_gids[i] = INVALID_GID; @@ -130,12 +127,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) groups = acred->group_info->ngroups; if (groups > NFS_NGROUPS) groups = NFS_NGROUPS; - for (i = 0; i < groups ; i++) { - gid_t gid; - gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i)); - if (cred->uc_gids[i] != gid) + for (i = 0; i < groups ; i++) + if (!gid_eq(cred->uc_gids[i], GROUP_AT(acred->group_info, i))) return 0; - } if (groups < NFS_NGROUPS && cred->uc_gids[groups] != INVALID_GID) return 0; -- cgit v1.2.3 From cdba321e291f0fbf5abda4d88340292b858e3d4d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 17:10:52 -0800 Subject: sunrpc: Convert kuids and kgids to uids and gids for printing When printing kuids and kgids for debugging purpropses convert them to ordinary integers so their values can be fed to the oridnary print functions. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_generic.c | 4 +++- net/sunrpc/auth_gss/auth_gss.c | 13 ++++++++----- net/sunrpc/auth_unix.c | 3 ++- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index bff3e4730f6..b6badafc649 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -96,7 +96,9 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", gcred->acred.machine_cred ? "machine" : "generic", - gcred, acred->uid, acred->gid); + gcred, + from_kuid(&init_user_ns, acred->uid), + from_kgid(&init_user_ns, acred->gid)); return &gcred->gc_base; } diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1b8b3e4fad4..afbbcfb1078 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -517,7 +517,7 @@ gss_refresh_upcall(struct rpc_task *task) int err = 0; dprintk("RPC: %5u %s for uid %u\n", - task->tk_pid, __func__, cred->cr_uid); + task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid)); gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); if (PTR_ERR(gss_msg) == -EAGAIN) { /* XXX: warning on the first, under the assumption we @@ -549,7 +549,8 @@ gss_refresh_upcall(struct rpc_task *task) gss_release_msg(gss_msg); out: dprintk("RPC: %5u %s for uid %u result %d\n", - task->tk_pid, __func__, cred->cr_uid, err); + task->tk_pid, __func__, + from_kuid(&init_user_ns, cred->cr_uid), err); return err; } @@ -562,7 +563,8 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) DEFINE_WAIT(wait); int err = 0; - dprintk("RPC: %s for uid %u\n", __func__, cred->cr_uid); + dprintk("RPC: %s for uid %u\n", + __func__, from_kuid(&init_user_ns, cred->cr_uid)); retry: gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); if (PTR_ERR(gss_msg) == -EAGAIN) { @@ -604,7 +606,7 @@ out_intr: gss_release_msg(gss_msg); out: dprintk("RPC: %s for uid %u result %d\n", - __func__, cred->cr_uid, err); + __func__, from_kuid(&init_user_ns, cred->cr_uid), err); return err; } @@ -1059,7 +1061,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) int err = -ENOMEM; dprintk("RPC: %s for uid %d, flavor %d\n", - __func__, acred->uid, auth->au_flavor); + __func__, from_kuid(&init_user_ns, acred->uid), + auth->au_flavor); if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) goto out_err; diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 9f3885745fb..55b6ca6fbbd 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -65,7 +65,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) unsigned int i; dprintk("RPC: allocating UNIX cred for uid %d gid %d\n", - acred->uid, acred->gid); + from_kuid(&init_user_ns, acred->uid), + from_kgid(&init_user_ns, acred->gid)); if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS))) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From e572fc739822ad779493b8a72bd27f2101fc3373 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 17:18:04 -0800 Subject: sunrpc: Use gid_valid to test for gid != INVALID_GID In auth unix there are a couple of places INVALID_GID is used a sentinel to mark the end of uc_gids array. Use gid_valid as a type safe way to verify we have not hit the end of valid data in the array. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_unix.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 55b6ca6fbbd..c434fde2079 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -131,8 +131,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) for (i = 0; i < groups ; i++) if (!gid_eq(cred->uc_gids[i], GROUP_AT(acred->group_info, i))) return 0; - if (groups < NFS_NGROUPS && - cred->uc_gids[groups] != INVALID_GID) + if (groups < NFS_NGROUPS && gid_valid(cred->uc_gids[groups])) return 0; return 1; } @@ -161,7 +160,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) *p++ = htonl((u32) cred->uc_uid); *p++ = htonl((u32) cred->uc_gid); hold = p++; - for (i = 0; i < 16 && cred->uc_gids[i] != INVALID_GID; i++) + for (i = 0; i < 16 && gid_valid(cred->uc_gids[i]); i++) *p++ = htonl((u32) cred->uc_gids[i]); *hold = htonl(p - hold - 1); /* gid array length */ *base = htonl((p - base - 1) << 2); /* cred length */ -- cgit v1.2.3 From 90602c7b192fdd3e6b7c7623479f4bc86ed7ee34 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 2 Feb 2013 00:25:43 -0800 Subject: sunrpc: Update gss uid to security context mapping. - Use from_kuid when generating the on the wire uid values. - Use make_kuid when reading on the wire values. In gss_encode_v0_msg, since the uid in gss_upcall_msg is now a kuid_t generate the necessary uid_t value on the stack copy it into gss_msg->databuf where it can safely live until the message is no longer needed. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_gss/auth_gss.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index afbbcfb1078..a3600671989 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -395,8 +395,11 @@ gss_upcall_callback(struct rpc_task *task) static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) { - gss_msg->msg.data = &gss_msg->uid; - gss_msg->msg.len = sizeof(gss_msg->uid); + uid_t uid = from_kuid(&init_user_ns, gss_msg->uid); + memcpy(gss_msg->databuf, &uid, sizeof(uid)); + gss_msg->msg.data = gss_msg->databuf; + gss_msg->msg.len = sizeof(uid); + BUG_ON(sizeof(uid) > UPCALL_BUF_LEN); } static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, @@ -409,7 +412,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ", mech->gm_name, - gss_msg->uid); + from_kuid(&init_user_ns, gss_msg->uid)); p += gss_msg->msg.len; if (clnt->cl_principal) { len = sprintf(p, "target=%s ", clnt->cl_principal); @@ -620,7 +623,8 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) struct gss_upcall_msg *gss_msg; struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe; struct gss_cl_ctx *ctx; - uid_t uid; + uid_t id; + kuid_t uid; ssize_t err = -EFBIG; if (mlen > MSG_BUF_MAXSIZE) @@ -635,12 +639,18 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) goto err; end = (const void *)((char *)buf + mlen); - p = simple_get_bytes(buf, end, &uid, sizeof(uid)); + p = simple_get_bytes(buf, end, &id, sizeof(id)); if (IS_ERR(p)) { err = PTR_ERR(p); goto err; } + uid = make_kuid(&init_user_ns, id); + if (!uid_valid(uid)) { + err = -EINVAL; + goto err; + } + err = -ENOMEM; ctx = gss_alloc_context(); if (ctx == NULL) -- cgit v1.2.3 From 683428fae8c73d7d7da0fa2e0b6beb4d8df4e808 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 2 Feb 2013 01:40:53 -0800 Subject: sunrpc: Update svcgss xdr handle to rpsec_contect cache For each received uid call make_kuid and validate the result. For each received gid call make_kgid and validate the result. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_gss/svcauth_gss.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 73e95738660..ecd1d58bf61 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, { /* contexthandle expiry [ uid gid N mechname ...mechdata... ] */ char *buf = mesg; + int id; int len, rv; struct rsc rsci, *rscp = NULL; time_t expiry; @@ -444,7 +445,7 @@ static int rsc_parse(struct cache_detail *cd, goto out; /* uid, or NEGATIVE */ - rv = get_int(&mesg, &rsci.cred.cr_uid); + rv = get_int(&mesg, &id); if (rv == -EINVAL) goto out; if (rv == -ENOENT) @@ -452,8 +453,16 @@ static int rsc_parse(struct cache_detail *cd, else { int N, i; + /* uid */ + rsci.cred.cr_uid = make_kuid(&init_user_ns, id); + if (!uid_valid(rsci.cred.cr_uid)) + goto out; + /* gid */ - if (get_int(&mesg, &rsci.cred.cr_gid)) + if (get_int(&mesg, &id)) + goto out; + rsci.cred.cr_gid = make_kgid(&init_user_ns, id); + if (!gid_valid(rsci.cred.cr_gid)) goto out; /* number of additional gid's */ @@ -467,11 +476,10 @@ static int rsc_parse(struct cache_detail *cd, /* gid's */ status = -EINVAL; for (i=0; i Date: Sat, 2 Feb 2013 01:57:30 -0800 Subject: sunrpc: Hash uids by first computing their value in the initial userns In svcauth_unix introduce a helper unix_gid_hash as otherwise the expresion to generate the hash value is just too long. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth.c | 2 +- net/sunrpc/svcauth_unix.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 4cd0ecfe983..392adc41e2e 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, *entry, *new; unsigned int nr; - nr = hash_long(acred->uid, cache->hashbits); + nr = hash_long(from_kuid(&init_user_ns, acred->uid), cache->hashbits); rcu_read_lock(); hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 92166b57ec7..faf17195a9f 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -419,6 +419,11 @@ struct unix_gid { struct group_info *gi; }; +static int unix_gid_hash(kuid_t uid) +{ + return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS); +} + static void unix_gid_put(struct kref *kref) { struct cache_head *item = container_of(kref, struct cache_head, ref); @@ -530,7 +535,7 @@ static int unix_gid_parse(struct cache_detail *cd, ug.h.expiry_time = expiry; ch = sunrpc_cache_update(cd, &ug.h, &ugp->h, - hash_long(uid, GID_HASHBITS)); + unix_gid_hash(uid)); if (!ch) err = -ENOMEM; else { @@ -621,7 +626,7 @@ static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid) struct cache_head *ch; ug.uid = uid; - ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); + ch = sunrpc_cache_lookup(cd, &ug.h, unix_gid_hash(uid)); if (ch) return container_of(ch, struct unix_gid, h); else -- cgit v1.2.3 From a570abbb966ee7de6c4357a58be11a558fa7099b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 2 Feb 2013 02:45:08 -0800 Subject: sunrpc: Properly encode kuids and kgids in RPC_AUTH_UNIX credentials When writing kuids onto the wire first map them into the initial user namespace. When writing kgids onto the wire first map them into the initial user namespace. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/auth_unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index c434fde2079..dc37021fc3e 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -157,11 +157,11 @@ unx_marshal(struct rpc_task *task, __be32 *p) */ p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); - *p++ = htonl((u32) cred->uc_uid); - *p++ = htonl((u32) cred->uc_gid); + *p++ = htonl((u32) from_kuid(&init_user_ns, cred->uc_uid)); + *p++ = htonl((u32) from_kgid(&init_user_ns, cred->uc_gid)); hold = p++; for (i = 0; i < 16 && gid_valid(cred->uc_gids[i]); i++) - *p++ = htonl((u32) cred->uc_gids[i]); + *p++ = htonl((u32) from_kgid(&init_user_ns, cred->uc_gids[i])); *hold = htonl(p - hold - 1); /* gid array length */ *base = htonl((p - base - 1) << 2); /* cred length */ -- cgit v1.2.3 From 25da9263710ec94c964259c79fa9a3a635cd3a50 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 2 Feb 2013 02:49:44 -0800 Subject: sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls. When a new rpc connection is established with an in-kernel server, the traffic passes through svc_process_common, and svc_set_client and down into svcauth_unix_set_client if it is of type RPC_AUTH_NULL or RPC_AUTH_UNIX. svcauth_unix_set_client then looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use. The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace. When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further. When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/svcauth_unix.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index faf17195a9f..bdea0a1b6d1 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -470,7 +470,7 @@ static void unix_gid_request(struct cache_detail *cd, char tuid[20]; struct unix_gid *ug = container_of(h, struct unix_gid, h); - snprintf(tuid, 20, "%u", ug->uid); + snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid)); qword_add(bpp, blen, tuid); (*bpp)[-1] = '\n'; } @@ -486,7 +486,8 @@ static int unix_gid_parse(struct cache_detail *cd, char *mesg, int mlen) { /* uid expiry Ngid gid0 gid1 ... gidN-1 */ - int uid; + int id; + kuid_t uid; int gids; int rv; int i; @@ -498,9 +499,12 @@ static int unix_gid_parse(struct cache_detail *cd, return -EINVAL; mesg[mlen-1] = 0; - rv = get_int(&mesg, &uid); + rv = get_int(&mesg, &id); if (rv) return -EINVAL; + uid = make_kuid(&init_user_ns, id); + if (!uid_valid(uid)) + return -EINVAL; ug.uid = uid; expiry = get_expiry(&mesg); @@ -554,7 +558,7 @@ static int unix_gid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) { - struct user_namespace *user_ns = current_user_ns(); + struct user_namespace *user_ns = &init_user_ns; struct unix_gid *ug; int i; int glen; @@ -570,7 +574,7 @@ static int unix_gid_show(struct seq_file *m, else glen = 0; - seq_printf(m, "%u %d:", ug->uid, glen); + seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen); for (i = 0; i < glen; i++) seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); seq_printf(m, "\n"); -- cgit v1.2.3 From f025adf191924e3a75ce80e130afcd2485b53bb8 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 2 Feb 2013 03:03:04 -0800 Subject: sunrpc: Properly decode kuids and kgids in RPC_AUTH_UNIX credentials When reading kuids from the wire map them into the initial user namespace, and validate the mapping succeded. When reading kgids from the wire map them into the initial user namespace, and validate the mapping succeded. Cc: "J. Bruce Fields" Cc: Trond Myklebust Signed-off-by: "Eric W. Biederman" --- net/sunrpc/svcauth_unix.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index bdea0a1b6d1..a1852e19ed0 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -821,8 +821,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ argv->iov_len -= slen*4; - cred->cr_uid = svc_getnl(argv); /* uid */ - cred->cr_gid = svc_getnl(argv); /* gid */ + cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ + cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ + if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid)) + goto badcred; slen = svc_getnl(argv); /* gids length */ if (slen > 16 || (len -= (slen + 2)*4) < 0) goto badcred; -- cgit v1.2.3