summaryrefslogtreecommitdiff
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 3663e5168583..0da8fa282d56 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -175,6 +175,9 @@ static void hash_key_type_and_desc(struct keyring_index_key *index_key)
type = (unsigned long)index_key->type;
acc = mult_64x32_and_fold(type, desc_len + 13);
acc = mult_64x32_and_fold(acc, 9207);
+ piece = (unsigned long)index_key->domain_tag;
+ acc = mult_64x32_and_fold(acc, piece);
+ acc = mult_64x32_and_fold(acc, 9207);
for (;;) {
n = desc_len;
@@ -208,16 +211,36 @@ static void hash_key_type_and_desc(struct keyring_index_key *index_key)
/*
* Finalise an index key to include a part of the description actually in the
- * index key and to add in the hash too.
+ * index key, to set the domain tag and to calculate the hash.
*/
void key_set_index_key(struct keyring_index_key *index_key)
{
+ static struct key_tag default_domain_tag = { .usage = REFCOUNT_INIT(1), };
size_t n = min_t(size_t, index_key->desc_len, sizeof(index_key->desc));
+
memcpy(index_key->desc, index_key->description, n);
+ index_key->domain_tag = &default_domain_tag;
hash_key_type_and_desc(index_key);
}
+/**
+ * key_put_tag - Release a ref on a tag.
+ * @tag: The tag to release.
+ *
+ * This releases a reference the given tag and returns true if that ref was the
+ * last one.
+ */
+bool key_put_tag(struct key_tag *tag)
+{
+ if (refcount_dec_and_test(&tag->usage)) {
+ kfree_rcu(tag, rcu);
+ return true;
+ }
+
+ return false;
+}
+
/*
* Build the next index key chunk.
*
@@ -238,8 +261,10 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
return index_key->x;
case 2:
return (unsigned long)index_key->type;
+ case 3:
+ return (unsigned long)index_key->domain_tag;
default:
- level -= 3;
+ level -= 4;
if (desc_len <= sizeof(index_key->desc))
return 0;
@@ -268,6 +293,7 @@ static bool keyring_compare_object(const void *object, const void *data)
const struct key *key = keyring_ptr_to_key(object);
return key->index_key.type == index_key->type &&
+ key->index_key.domain_tag == index_key->domain_tag &&
key->index_key.desc_len == index_key->desc_len &&
memcmp(key->index_key.description, index_key->description,
index_key->desc_len) == 0;
@@ -309,6 +335,12 @@ static int keyring_diff_objects(const void *object, const void *data)
goto differ;
level += sizeof(unsigned long);
+ seg_a = (unsigned long)a->domain_tag;
+ seg_b = (unsigned long)b->domain_tag;
+ if ((seg_a ^ seg_b) != 0)
+ goto differ;
+ level += sizeof(unsigned long);
+
i = sizeof(a->desc);
if (a->desc_len <= i)
goto same;