Hi Sasha, Currently, the only user of this flag is the .ima_blacklist keyring. Unless the .ima_blacklist keyring was backported, there is no reason to backport this patch. Mimi On Wed, 2016-02-10 at 09:59 -0500, Sasha Levin wrote: > From: Mimi Zohar <zohar@xxxxxxxxxxxxxxxxxx> > > This patch has been added to the 3.18 stable tree. If you have any > objections, please let us know. > > =============== > > [ Upstream commit d3600bcf9d64d88dc1d189a754dcfab960ce751f ] > > Userspace should not be allowed to remove keys from certain keyrings > (eg. blacklist), though the keys themselves can expire. > > This patch defines a new key flag named KEY_FLAG_KEEP to prevent > userspace from being able to unlink, revoke, invalidate or timed > out a key on a keyring. When this flag is set on the keyring, all > keys subsequently added are flagged. > > In addition, when this flag is set, the keyring itself can not be > cleared. > > Signed-off-by: Mimi Zohar <zohar@xxxxxxxxxxxxxxxxxx> > Cc: David Howells <dhowells@xxxxxxxxxx> > Signed-off-by: Sasha Levin <sasha.levin@xxxxxxxxxx> > --- > include/linux/key.h | 1 + > security/keys/key.c | 6 +++++- > security/keys/keyctl.c | 56 +++++++++++++++++++++++++++++++++++++++++--------- > 3 files changed, 52 insertions(+), 11 deletions(-) > > diff --git a/include/linux/key.h b/include/linux/key.h > index e1d4715..2318331 100644 > --- a/include/linux/key.h > +++ b/include/linux/key.h > @@ -172,6 +172,7 @@ struct key { > #define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ > #define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ > #define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */ > +#define KEY_FLAG_KEEP 12 /* set if key should not be removed */ > > /* the key type and key description string > * - the desc is used to match a key against search criteria > diff --git a/security/keys/key.c b/security/keys/key.c > index e17ba6a..0b7aa0c 100644 > --- a/security/keys/key.c > +++ b/security/keys/key.c > @@ -431,8 +431,12 @@ static int __key_instantiate_and_link(struct key *key, > awaken = 1; > > /* and link it into the destination keyring */ > - if (keyring) > + if (keyring) { > + if (test_bit(KEY_FLAG_KEEP, &keyring->flags)) > + set_bit(KEY_FLAG_KEEP, &key->flags); > + > __key_link(key, _edit); > + } > > /* disable the authorisation key */ > if (authkey) > diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c > index fee27fe..700c204 100644 > --- a/security/keys/keyctl.c > +++ b/security/keys/keyctl.c > @@ -364,11 +364,14 @@ error: > * and any links to the key will be automatically garbage collected after a > * certain amount of time (/proc/sys/kernel/keys/gc_delay). > * > + * Keys with KEY_FLAG_KEEP set should not be revoked. > + * > * If successful, 0 is returned. > */ > long keyctl_revoke_key(key_serial_t id) > { > key_ref_t key_ref; > + struct key *key; > long ret; > > key_ref = lookup_user_key(id, 0, KEY_NEED_WRITE); > @@ -383,8 +386,13 @@ long keyctl_revoke_key(key_serial_t id) > } > } > > - key_revoke(key_ref_to_ptr(key_ref)); > - ret = 0; > + key = key_ref_to_ptr(key_ref); > + if (test_bit(KEY_FLAG_KEEP, &key->flags)) > + return -EPERM; > + else { > + key_revoke(key); > + ret = 0; > + } > > key_ref_put(key_ref); > error: > @@ -398,11 +406,14 @@ error: > * The key and any links to the key will be automatically garbage collected > * immediately. > * > + * Keys with KEY_FLAG_KEEP set should not be invalidated. > + * > * If successful, 0 is returned. > */ > long keyctl_invalidate_key(key_serial_t id) > { > key_ref_t key_ref; > + struct key *key; > long ret; > > kenter("%d", id); > @@ -426,8 +437,13 @@ long keyctl_invalidate_key(key_serial_t id) > } > > invalidate: > - key_invalidate(key_ref_to_ptr(key_ref)); > - ret = 0; > + key = key_ref_to_ptr(key_ref); > + if (test_bit(KEY_FLAG_KEEP, &key->flags)) > + ret = -EPERM; > + else { > + key_invalidate(key); > + ret = 0; > + } > error_put: > key_ref_put(key_ref); > error: > @@ -439,12 +455,13 @@ error: > * Clear the specified keyring, creating an empty process keyring if one of the > * special keyring IDs is used. > * > - * The keyring must grant the caller Write permission for this to work. If > - * successful, 0 will be returned. > + * The keyring must grant the caller Write permission and not have > + * KEY_FLAG_KEEP set for this to work. If successful, 0 will be returned. > */ > long keyctl_keyring_clear(key_serial_t ringid) > { > key_ref_t keyring_ref; > + struct key *keyring; > long ret; > > keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE); > @@ -466,7 +483,11 @@ long keyctl_keyring_clear(key_serial_t ringid) > } > > clear: > - ret = keyring_clear(key_ref_to_ptr(keyring_ref)); > + keyring = key_ref_to_ptr(keyring_ref); > + if (test_bit(KEY_FLAG_KEEP, &keyring->flags)) > + ret = -EPERM; > + else > + ret = keyring_clear(keyring); > error_put: > key_ref_put(keyring_ref); > error: > @@ -517,11 +538,14 @@ error: > * itself need not grant the caller anything. If the last link to a key is > * removed then that key will be scheduled for destruction. > * > + * Keys or keyrings with KEY_FLAG_KEEP set should not be unlinked. > + * > * If successful, 0 will be returned. > */ > long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) > { > key_ref_t keyring_ref, key_ref; > + struct key *keyring, *key; > long ret; > > keyring_ref = lookup_user_key(ringid, 0, KEY_NEED_WRITE); > @@ -536,7 +560,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) > goto error2; > } > > - ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); > + keyring = key_ref_to_ptr(keyring_ref); > + key = key_ref_to_ptr(key_ref); > + if (test_bit(KEY_FLAG_KEEP, &keyring->flags) && > + test_bit(KEY_FLAG_KEEP, &key->flags)) > + ret = -EPERM; > + else > + ret = key_unlink(keyring, key); > > key_ref_put(key_ref); > error2: > @@ -1319,6 +1349,8 @@ error: > * the current time. The key and any links to the key will be automatically > * garbage collected after the timeout expires. > * > + * Keys with KEY_FLAG_KEEP set should not be timed out. > + * > * If successful, 0 is returned. > */ > long keyctl_set_timeout(key_serial_t id, unsigned timeout) > @@ -1350,10 +1382,14 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) > > okay: > key = key_ref_to_ptr(key_ref); > - key_set_timeout(key, timeout); > + if (test_bit(KEY_FLAG_KEEP, &key->flags)) > + ret = -EPERM; > + else { > + key_set_timeout(key, timeout); > + ret = 0; > + } > key_put(key); > > - ret = 0; > error: > return ret; > } -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html