The patch titled keys: let keyctl_chown() change a key's owner has been added to the -mm tree. Its filename is keys-let-keyctl_chown-change-a-keys-owner.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: keys: let keyctl_chown() change a key's owner From: Fredrik Tolf <fredrik@xxxxxxxxxxxxx> 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@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- security/keys/keyctl.c | 56 +++++++++++++++++++++++++++++++++------ 1 files changed, 48 insertions(+), 8 deletions(-) diff -puN security/keys/keyctl.c~keys-let-keyctl_chown-change-a-keys-owner security/keys/keyctl.c --- 25/security/keys/keyctl.c~keys-let-keyctl_chown-change-a-keys-owner Tue Jun 20 17:00:26 2006 +++ 25-akpm/security/keys/keyctl.c Tue Jun 20 17:00:26 2006 @@ -673,6 +673,7 @@ long keyctl_read_key(key_serial_t keyid, */ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) { + struct key_user *newowner, *zapowner = NULL; struct key *key; key_ref_t key_ref; long ret; @@ -696,19 +697,50 @@ long keyctl_chown_key(key_serial_t id, u if (!capable(CAP_SYS_ADMIN)) { /* only the sysadmin can chown a key to some other 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 * than one of those that the current process subscribes to */ 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) { - /* don't support UID changing yet */ - ret = -EOPNOTSUPP; - goto no_access; + ret = -ENOMEM; + 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)) { + 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 */ @@ -717,12 +749,20 @@ long keyctl_chown_key(key_serial_t id, u ret = 0; - no_access: +error_put: up_write(&key->sem); key_put(key); - error: + if (zapowner) + key_user_put(zapowner); +error: return ret; +quota_overrun: + spin_unlock(&newowner->lock); + zapowner = newowner; + ret = -EDQUOT; + goto error_put; + } /* end keyctl_chown_key() */ /*****************************************************************************/ _ Patches currently in -mm which might be from fredrik@xxxxxxxxxxxxx are keys-let-keyctl_chown-change-a-keys-owner.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html