| From b990760c580646ae8d32494750f08ed91a5eec90 Mon Sep 17 00:00:00 2001 |
| From: Yang Xu <xuyang2018.jy@cn.fujitsu.com> |
| Date: Fri, 28 Feb 2020 12:41:51 +0800 |
| Subject: [PATCH] KEYS: reaching the keys quotas correctly |
| |
| commit 2e356101e72ab1361821b3af024d64877d9a798d upstream. |
| |
| Currently, when we add a new user key, the calltrace as below: |
| |
| add_key() |
| key_create_or_update() |
| key_alloc() |
| __key_instantiate_and_link |
| generic_key_instantiate |
| key_payload_reserve |
| ...... |
| |
| Since commit a08bf91ce28e ("KEYS: allow reaching the keys quotas exactly"), |
| we can reach max bytes/keys in key_alloc, but we forget to remove this |
| limit when we reserver space for payload in key_payload_reserve. So we |
| can only reach max keys but not max bytes when having delta between plen |
| and type->def_datalen. Remove this limit when instantiating the key, so we |
| can keep consistent with key_alloc. |
| |
| Also, fix the similar problem in keyctl_chown_key(). |
| |
| Fixes: 0b77f5bfb45c ("keys: make the keyring quotas controllable through /proc/sys") |
| Fixes: a08bf91ce28e ("KEYS: allow reaching the keys quotas exactly") |
| Cc: stable@vger.kernel.org # 5.0.x |
| Cc: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> |
| Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Reviewed-by: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/security/keys/key.c b/security/keys/key.c |
| index 9a6108aefae9..32df6a06abc3 100644 |
| --- a/security/keys/key.c |
| +++ b/security/keys/key.c |
| @@ -379,7 +379,7 @@ int key_payload_reserve(struct key *key, size_t datalen) |
| spin_lock(&key->user->lock); |
| |
| if (delta > 0 && |
| - (key->user->qnbytes + delta >= maxbytes || |
| + (key->user->qnbytes + delta > maxbytes || |
| key->user->qnbytes + delta < key->user->qnbytes)) { |
| ret = -EDQUOT; |
| } |
| diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c |
| index 5aa605ef8d9d..126eb7c6bda1 100644 |
| --- a/security/keys/keyctl.c |
| +++ b/security/keys/keyctl.c |
| @@ -877,8 +877,8 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) |
| key_quota_root_maxbytes : key_quota_maxbytes; |
| |
| spin_lock(&newowner->lock); |
| - if (newowner->qnkeys + 1 >= maxkeys || |
| - newowner->qnbytes + key->quotalen >= maxbytes || |
| + if (newowner->qnkeys + 1 > maxkeys || |
| + newowner->qnbytes + key->quotalen > maxbytes || |
| newowner->qnbytes + key->quotalen < |
| newowner->qnbytes) |
| goto quota_overrun; |
| -- |
| 2.7.4 |
| |