diff options
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
| -rw-r--r-- | net/sunrpc/svcauth_unix.c | 43 | 
1 files changed, 27 insertions, 16 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4d012920373..a1852e19ed0 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)  struct unix_gid {  	struct cache_head	h; -	uid_t			uid; +	kuid_t			uid;  	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); @@ -433,7 +438,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)  { @@ -465,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';  } @@ -475,13 +480,14 @@ 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)  {  	/* uid expiry Ngid gid0 gid1 ... gidN-1 */ -	int uid; +	int id; +	kuid_t uid;  	int gids;  	int rv;  	int i; @@ -493,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); @@ -530,7 +539,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 { @@ -549,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; @@ -565,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"); @@ -615,20 +624,20 @@ 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;  	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  		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; @@ -750,8 +759,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 */ @@ -812,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;  |