mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-04 04:06:26 +00:00
[PATCH] keys: let keyctl_chown() change a key's owner
Let keyctl_chown() change a key's owner, including attempting to transfer the quota burden to the new user. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
31204ed925
commit
5801649d8b
@ -673,6 +673,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
|
|||||||
*/
|
*/
|
||||||
long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
|
long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
|
struct key_user *newowner, *zapowner = NULL;
|
||||||
struct key *key;
|
struct key *key;
|
||||||
key_ref_t key_ref;
|
key_ref_t key_ref;
|
||||||
long ret;
|
long ret;
|
||||||
@ -696,19 +697,50 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
|
|||||||
if (!capable(CAP_SYS_ADMIN)) {
|
if (!capable(CAP_SYS_ADMIN)) {
|
||||||
/* only the sysadmin can chown a key to some other UID */
|
/* only the sysadmin can chown a key to some other UID */
|
||||||
if (uid != (uid_t) -1 && key->uid != uid)
|
if (uid != (uid_t) -1 && key->uid != uid)
|
||||||
goto no_access;
|
goto error_put;
|
||||||
|
|
||||||
/* only the sysadmin can set the key's GID to a group other
|
/* only the sysadmin can set the key's GID to a group other
|
||||||
* than one of those that the current process subscribes to */
|
* than one of those that the current process subscribes to */
|
||||||
if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
|
if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
|
||||||
goto no_access;
|
goto error_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change the UID (have to update the quotas) */
|
/* change the UID */
|
||||||
if (uid != (uid_t) -1 && uid != key->uid) {
|
if (uid != (uid_t) -1 && uid != key->uid) {
|
||||||
/* don't support UID changing yet */
|
ret = -ENOMEM;
|
||||||
ret = -EOPNOTSUPP;
|
newowner = key_user_lookup(uid);
|
||||||
goto no_access;
|
if (!newowner)
|
||||||
|
goto error_put;
|
||||||
|
|
||||||
|
/* transfer the quota burden to the new user */
|
||||||
|
if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
|
||||||
|
spin_lock(&newowner->lock);
|
||||||
|
if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
|
||||||
|
newowner->qnbytes + key->quotalen >=
|
||||||
|
KEYQUOTA_MAX_BYTES)
|
||||||
|
goto quota_overrun;
|
||||||
|
|
||||||
|
newowner->qnkeys++;
|
||||||
|
newowner->qnbytes += key->quotalen;
|
||||||
|
spin_unlock(&newowner->lock);
|
||||||
|
|
||||||
|
spin_lock(&key->user->lock);
|
||||||
|
key->user->qnkeys--;
|
||||||
|
key->user->qnbytes -= key->quotalen;
|
||||||
|
spin_unlock(&key->user->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_dec(&key->user->nkeys);
|
||||||
|
atomic_inc(&newowner->nkeys);
|
||||||
|
|
||||||
|
if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
|
||||||
|
atomic_dec(&key->user->nikeys);
|
||||||
|
atomic_inc(&newowner->nikeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
zapowner = key->user;
|
||||||
|
key->user = newowner;
|
||||||
|
key->uid = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change the GID */
|
/* change the GID */
|
||||||
@ -717,12 +749,20 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
no_access:
|
error_put:
|
||||||
up_write(&key->sem);
|
up_write(&key->sem);
|
||||||
key_put(key);
|
key_put(key);
|
||||||
error:
|
if (zapowner)
|
||||||
|
key_user_put(zapowner);
|
||||||
|
error:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
quota_overrun:
|
||||||
|
spin_unlock(&newowner->lock);
|
||||||
|
zapowner = newowner;
|
||||||
|
ret = -EDQUOT;
|
||||||
|
goto error_put;
|
||||||
|
|
||||||
} /* end keyctl_chown_key() */
|
} /* end keyctl_chown_key() */
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user