mirror of
https://github.com/torvalds/linux
synced 2024-09-06 09:51:23 +00:00
Hi
2nd trial of the earlier PR with more appropriate tag: 1. Do no overwrite the key expiration once it is set. 2. Early to quota updates for keys to key_put(), instead of updating them in key_gc_unused_keys(). [1] Earlier PR: https://lore.kernel.org/linux-integrity/20240326143838.15076-1-jarkko@kernel.org/ BR, Jarkko -----BEGIN PGP SIGNATURE----- iJYEABYKAD4WIQRE6pSOnaBC00OEHEIaerohdGur0gUCZjzYqSAcamFya2tvLnNh a2tpbmVuQGxpbnV4LmludGVsLmNvbQAKCRAaerohdGur0nQJAQDN4r2K/QgryPyS fSfVPeeIPkBIOat2sTq8IOQLKlCybwD8Duo6gJuZWmQmdbn2m2Pn/Dg3xUy4ljba IwHRro/kcwY= =3V25 -----END PGP SIGNATURE----- Merge tag 'keys-next-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd Pull keys updates from Jarkko Sakkinen: - do not overwrite the key expiration once it is set - move key quota updates earlier into key_put(), instead of updating them in key_gc_unused_keys() * tag 'keys-next-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: keys: Fix overwrite of key expiration on instantiation keys: update key quotas in key_put()
This commit is contained in:
commit
25c73642cc
|
@ -155,14 +155,6 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
|
||||||
|
|
||||||
security_key_free(key);
|
security_key_free(key);
|
||||||
|
|
||||||
/* deal with the user's key tracking and quota */
|
|
||||||
if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
|
|
||||||
spin_lock(&key->user->lock);
|
|
||||||
key->user->qnkeys--;
|
|
||||||
key->user->qnbytes -= key->quotalen;
|
|
||||||
spin_unlock(&key->user->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic_dec(&key->user->nkeys);
|
atomic_dec(&key->user->nkeys);
|
||||||
if (state != KEY_IS_UNINSTANTIATED)
|
if (state != KEY_IS_UNINSTANTIATED)
|
||||||
atomic_dec(&key->user->nikeys);
|
atomic_dec(&key->user->nikeys);
|
||||||
|
|
|
@ -230,6 +230,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
struct key *key;
|
struct key *key;
|
||||||
size_t desclen, quotalen;
|
size_t desclen, quotalen;
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned long irqflags;
|
||||||
|
|
||||||
key = ERR_PTR(-EINVAL);
|
key = ERR_PTR(-EINVAL);
|
||||||
if (!desc || !*desc)
|
if (!desc || !*desc)
|
||||||
|
@ -259,7 +260,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
|
unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
|
||||||
key_quota_root_maxbytes : key_quota_maxbytes;
|
key_quota_root_maxbytes : key_quota_maxbytes;
|
||||||
|
|
||||||
spin_lock(&user->lock);
|
spin_lock_irqsave(&user->lock, irqflags);
|
||||||
if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
|
if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
|
||||||
if (user->qnkeys + 1 > maxkeys ||
|
if (user->qnkeys + 1 > maxkeys ||
|
||||||
user->qnbytes + quotalen > maxbytes ||
|
user->qnbytes + quotalen > maxbytes ||
|
||||||
|
@ -269,7 +270,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
|
|
||||||
user->qnkeys++;
|
user->qnkeys++;
|
||||||
user->qnbytes += quotalen;
|
user->qnbytes += quotalen;
|
||||||
spin_unlock(&user->lock);
|
spin_unlock_irqrestore(&user->lock, irqflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate and initialise the key and its description */
|
/* allocate and initialise the key and its description */
|
||||||
|
@ -327,10 +328,10 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
kfree(key->description);
|
kfree(key->description);
|
||||||
kmem_cache_free(key_jar, key);
|
kmem_cache_free(key_jar, key);
|
||||||
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
|
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
|
||||||
spin_lock(&user->lock);
|
spin_lock_irqsave(&user->lock, irqflags);
|
||||||
user->qnkeys--;
|
user->qnkeys--;
|
||||||
user->qnbytes -= quotalen;
|
user->qnbytes -= quotalen;
|
||||||
spin_unlock(&user->lock);
|
spin_unlock_irqrestore(&user->lock, irqflags);
|
||||||
}
|
}
|
||||||
key_user_put(user);
|
key_user_put(user);
|
||||||
key = ERR_PTR(ret);
|
key = ERR_PTR(ret);
|
||||||
|
@ -340,10 +341,10 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
kmem_cache_free(key_jar, key);
|
kmem_cache_free(key_jar, key);
|
||||||
no_memory_2:
|
no_memory_2:
|
||||||
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
|
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
|
||||||
spin_lock(&user->lock);
|
spin_lock_irqsave(&user->lock, irqflags);
|
||||||
user->qnkeys--;
|
user->qnkeys--;
|
||||||
user->qnbytes -= quotalen;
|
user->qnbytes -= quotalen;
|
||||||
spin_unlock(&user->lock);
|
spin_unlock_irqrestore(&user->lock, irqflags);
|
||||||
}
|
}
|
||||||
key_user_put(user);
|
key_user_put(user);
|
||||||
no_memory_1:
|
no_memory_1:
|
||||||
|
@ -351,7 +352,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
no_quota:
|
no_quota:
|
||||||
spin_unlock(&user->lock);
|
spin_unlock_irqrestore(&user->lock, irqflags);
|
||||||
key_user_put(user);
|
key_user_put(user);
|
||||||
key = ERR_PTR(-EDQUOT);
|
key = ERR_PTR(-EDQUOT);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -380,8 +381,9 @@ int key_payload_reserve(struct key *key, size_t datalen)
|
||||||
if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
|
if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
|
||||||
unsigned maxbytes = uid_eq(key->user->uid, GLOBAL_ROOT_UID) ?
|
unsigned maxbytes = uid_eq(key->user->uid, GLOBAL_ROOT_UID) ?
|
||||||
key_quota_root_maxbytes : key_quota_maxbytes;
|
key_quota_root_maxbytes : key_quota_maxbytes;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock(&key->user->lock);
|
spin_lock_irqsave(&key->user->lock, flags);
|
||||||
|
|
||||||
if (delta > 0 &&
|
if (delta > 0 &&
|
||||||
(key->user->qnbytes + delta > maxbytes ||
|
(key->user->qnbytes + delta > maxbytes ||
|
||||||
|
@ -392,7 +394,7 @@ int key_payload_reserve(struct key *key, size_t datalen)
|
||||||
key->user->qnbytes += delta;
|
key->user->qnbytes += delta;
|
||||||
key->quotalen += delta;
|
key->quotalen += delta;
|
||||||
}
|
}
|
||||||
spin_unlock(&key->user->lock);
|
spin_unlock_irqrestore(&key->user->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change the recorded data length if that didn't generate an error */
|
/* change the recorded data length if that didn't generate an error */
|
||||||
|
@ -463,6 +465,7 @@ static int __key_instantiate_and_link(struct key *key,
|
||||||
if (authkey)
|
if (authkey)
|
||||||
key_invalidate(authkey);
|
key_invalidate(authkey);
|
||||||
|
|
||||||
|
if (prep->expiry != TIME64_MAX)
|
||||||
key_set_expiry(key, prep->expiry);
|
key_set_expiry(key, prep->expiry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -645,9 +648,19 @@ void key_put(struct key *key)
|
||||||
if (key) {
|
if (key) {
|
||||||
key_check(key);
|
key_check(key);
|
||||||
|
|
||||||
if (refcount_dec_and_test(&key->usage))
|
if (refcount_dec_and_test(&key->usage)) {
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/* deal with the user's key tracking and quota */
|
||||||
|
if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
|
||||||
|
spin_lock_irqsave(&key->user->lock, flags);
|
||||||
|
key->user->qnkeys--;
|
||||||
|
key->user->qnbytes -= key->quotalen;
|
||||||
|
spin_unlock_irqrestore(&key->user->lock, flags);
|
||||||
|
}
|
||||||
schedule_work(&key_gc_work);
|
schedule_work(&key_gc_work);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(key_put);
|
EXPORT_SYMBOL(key_put);
|
||||||
|
|
||||||
|
|
|
@ -954,6 +954,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
|
||||||
long ret;
|
long ret;
|
||||||
kuid_t uid;
|
kuid_t uid;
|
||||||
kgid_t gid;
|
kgid_t gid;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
uid = make_kuid(current_user_ns(), user);
|
uid = make_kuid(current_user_ns(), user);
|
||||||
gid = make_kgid(current_user_ns(), group);
|
gid = make_kgid(current_user_ns(), group);
|
||||||
|
@ -1010,7 +1011,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
|
||||||
unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
|
unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
|
||||||
key_quota_root_maxbytes : key_quota_maxbytes;
|
key_quota_root_maxbytes : key_quota_maxbytes;
|
||||||
|
|
||||||
spin_lock(&newowner->lock);
|
spin_lock_irqsave(&newowner->lock, flags);
|
||||||
if (newowner->qnkeys + 1 > maxkeys ||
|
if (newowner->qnkeys + 1 > maxkeys ||
|
||||||
newowner->qnbytes + key->quotalen > maxbytes ||
|
newowner->qnbytes + key->quotalen > maxbytes ||
|
||||||
newowner->qnbytes + key->quotalen <
|
newowner->qnbytes + key->quotalen <
|
||||||
|
@ -1019,12 +1020,12 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
|
||||||
|
|
||||||
newowner->qnkeys++;
|
newowner->qnkeys++;
|
||||||
newowner->qnbytes += key->quotalen;
|
newowner->qnbytes += key->quotalen;
|
||||||
spin_unlock(&newowner->lock);
|
spin_unlock_irqrestore(&newowner->lock, flags);
|
||||||
|
|
||||||
spin_lock(&key->user->lock);
|
spin_lock_irqsave(&key->user->lock, flags);
|
||||||
key->user->qnkeys--;
|
key->user->qnkeys--;
|
||||||
key->user->qnbytes -= key->quotalen;
|
key->user->qnbytes -= key->quotalen;
|
||||||
spin_unlock(&key->user->lock);
|
spin_unlock_irqrestore(&key->user->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_dec(&key->user->nkeys);
|
atomic_dec(&key->user->nkeys);
|
||||||
|
@ -1056,7 +1057,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
quota_overrun:
|
quota_overrun:
|
||||||
spin_unlock(&newowner->lock);
|
spin_unlock_irqrestore(&newowner->lock, flags);
|
||||||
zapowner = newowner;
|
zapowner = newowner;
|
||||||
ret = -EDQUOT;
|
ret = -EDQUOT;
|
||||||
goto error_put;
|
goto error_put;
|
||||||
|
|
Loading…
Reference in a new issue