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/svcauth_unix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/sunrpc/svcauth_unix.c') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4d0129203733..c8cb5dc8d871 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/svcauth_unix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/sunrpc/svcauth_unix.c') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index c8cb5dc8d871..caae662f9fa3 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/svcauth_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/sunrpc/svcauth_unix.c') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index caae662f9fa3..92166b57ec7a 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 9e469e30d712b54cd3ff4a82d4dd5510522b8f16 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" 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/svcauth_unix.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'net/sunrpc/svcauth_unix.c') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 92166b57ec7a..faf17195a9fd 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 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/svcauth_unix.c') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index faf17195a9fd..bdea0a1b6d1d 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/svcauth_unix.c') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index bdea0a1b6d1d..a1852e19ed0c 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