diff options
Diffstat (limited to 'security/keys/keyctl.c')
| -rw-r--r-- | security/keys/keyctl.c | 50 | 
1 files changed, 30 insertions, 20 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 6cfc6478863..305ecb76519 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -569,8 +569,8 @@ okay:  	ret = snprintf(tmpbuf, PAGE_SIZE - 1,  		       "%s;%d;%d;%08x;%s",  		       key->type->name, -		       key->uid, -		       key->gid, +		       from_kuid_munged(current_user_ns(), key->uid), +		       from_kgid_munged(current_user_ns(), key->gid),  		       key->perm,  		       key->description ?: ""); @@ -766,15 +766,25 @@ error:   *   * If successful, 0 will be returned.   */ -long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) +long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)  {  	struct key_user *newowner, *zapowner = NULL;  	struct key *key;  	key_ref_t key_ref;  	long ret; +	kuid_t uid; +	kgid_t gid; + +	uid = make_kuid(current_user_ns(), user); +	gid = make_kgid(current_user_ns(), group); +	ret = -EINVAL; +	if ((user != (uid_t) -1) && !uid_valid(uid)) +		goto error; +	if ((group != (gid_t) -1) && !gid_valid(gid)) +		goto error;  	ret = 0; -	if (uid == (uid_t) -1 && gid == (gid_t) -1) +	if (user == (uid_t) -1 && group == (gid_t) -1)  		goto error;  	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, @@ -792,27 +802,27 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)  	if (!capable(CAP_SYS_ADMIN)) {  		/* only the sysadmin can chown a key to some other UID */ -		if (uid != (uid_t) -1 && key->uid != uid) +		if (user != (uid_t) -1 && !uid_eq(key->uid, uid))  			goto error_put;  		/* only the sysadmin can set the key's GID to a group other  		 * than one of those that the current process subscribes to */ -		if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid)) +		if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid))  			goto error_put;  	}  	/* change the UID */ -	if (uid != (uid_t) -1 && uid != key->uid) { +	if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) {  		ret = -ENOMEM; -		newowner = key_user_lookup(uid, current_user_ns()); +		newowner = key_user_lookup(uid);  		if (!newowner)  			goto error_put;  		/* transfer the quota burden to the new user */  		if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { -			unsigned maxkeys = (uid == 0) ? +			unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ?  				key_quota_root_maxkeys : key_quota_maxkeys; -			unsigned maxbytes = (uid == 0) ? +			unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?  				key_quota_root_maxbytes : key_quota_maxbytes;  			spin_lock(&newowner->lock); @@ -846,7 +856,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)  	}  	/* change the GID */ -	if (gid != (gid_t) -1) +	if (group != (gid_t) -1)  		key->gid = gid;  	ret = 0; @@ -897,7 +907,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)  	down_write(&key->sem);  	/* if we're not the sysadmin, we can only change a key that we own */ -	if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) { +	if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) {  		key->perm = perm;  		ret = 0;  	} @@ -1506,18 +1516,18 @@ long keyctl_session_to_parent(void)  	/* the parent must have the same effective ownership and mustn't be  	 * SUID/SGID */ -	if (pcred->uid	!= mycred->euid	|| -	    pcred->euid	!= mycred->euid	|| -	    pcred->suid	!= mycred->euid	|| -	    pcred->gid	!= mycred->egid	|| -	    pcred->egid	!= mycred->egid	|| -	    pcred->sgid	!= mycred->egid) +	if (!uid_eq(pcred->uid,	 mycred->euid) || +	    !uid_eq(pcred->euid, mycred->euid) || +	    !uid_eq(pcred->suid, mycred->euid) || +	    !gid_eq(pcred->gid,	 mycred->egid) || +	    !gid_eq(pcred->egid, mycred->egid) || +	    !gid_eq(pcred->sgid, mycred->egid))  		goto unlock;  	/* the keyrings must have the same UID */  	if ((pcred->tgcred->session_keyring && -	     pcred->tgcred->session_keyring->uid != mycred->euid) || -	    mycred->tgcred->session_keyring->uid != mycred->euid) +	     !uid_eq(pcred->tgcred->session_keyring->uid, mycred->euid)) || +	    !uid_eq(mycred->tgcred->session_keyring->uid, mycred->euid))  		goto unlock;  	/* cancel an already pending keyring replacement */  |