Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b6e4de0 authored by David Howells's avatar David Howells
Browse files

keys: Include target namespace in match criteria



Currently a key has a standard matching criteria of { type, description }
and this is used to only allow keys with unique criteria in a keyring.
This means, however, that you cannot have keys with the same type and
description but a different target namespace in the same keyring.

This is a potential problem for a containerised environment where, say, a
container is made up of some parts of its mount space involving netfs
superblocks from two different network namespaces.

This is also a problem for shared system management keyrings such as the
DNS records keyring or the NFS idmapper keyring that might contain keys
from different network namespaces.

Fix this by including a namespace component in a key's matching criteria.
Keyring types are marked to indicate which, if any, namespace is relevant
to keys of that type, and that namespace is set when the key is created
from the current task's namespace set.

The capability bit KEYCTL_CAPS1_NS_KEY_TAG is set if the kernel is
employing this feature.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 0f44e4d9
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -82,9 +82,16 @@ struct cred;

struct key_type;
struct key_owner;
struct key_tag;
struct keyring_list;
struct keyring_name;

struct key_tag {
	struct rcu_head		rcu;
	refcount_t		usage;
	bool			removed;	/* T when subject removed */
};

struct keyring_index_key {
	/* [!] If this structure is altered, the union in struct key must change too! */
	unsigned long		hash;			/* Hash value */
@@ -101,6 +108,7 @@ struct keyring_index_key {
		unsigned long x;
	};
	struct key_type		*type;
	struct key_tag		*domain_tag;	/* Domain of operation */
	const char		*description;
};

@@ -218,6 +226,7 @@ struct key {
			unsigned long	hash;
			unsigned long	len_desc;
			struct key_type	*type;		/* type of key */
			struct key_tag	*domain_tag;	/* Domain of operation */
			char		*description;
		};
	};
@@ -268,6 +277,7 @@ extern struct key *key_alloc(struct key_type *type,
extern void key_revoke(struct key *key);
extern void key_invalidate(struct key *key);
extern void key_put(struct key *key);
extern bool key_put_tag(struct key_tag *tag);

static inline struct key *__key_get(struct key *key)
{
+1 −0
Original line number Diff line number Diff line
@@ -129,5 +129,6 @@ struct keyctl_pkey_params {
#define KEYCTL_CAPS0_RESTRICT_KEYRING	0x40 /* KEYCTL_RESTRICT_KEYRING supported */
#define KEYCTL_CAPS0_MOVE		0x80 /* KEYCTL_MOVE supported */
#define KEYCTL_CAPS1_NS_KEYRING_NAME	0x01 /* Keyring names are per-user_namespace */
#define KEYCTL_CAPS1_NS_KEY_TAG		0x02 /* Key indexing can include a namespace tag */

#endif /*  _LINUX_KEYCTL_H */
+1 −1
Original line number Diff line number Diff line
@@ -154,7 +154,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
			atomic_dec(&key->user->nikeys);

		key_user_put(key->user);

		key_put_tag(key->domain_tag);
		kfree(key->description);

		memzero_explicit(key, sizeof(*key));
+1 −0
Original line number Diff line number Diff line
@@ -317,6 +317,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
		goto security_error;

	/* publish the key by giving it a serial number */
	refcount_inc(&key->domain_tag->usage);
	atomic_inc(&user->nkeys);
	key_alloc_serial(key);

+2 −1
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ static const unsigned char keyrings_capabilities[2] = {
	       KEYCTL_CAPS0_RESTRICT_KEYRING |
	       KEYCTL_CAPS0_MOVE
	       ),
	[1] = (KEYCTL_CAPS1_NS_KEYRING_NAME),
	[1] = (KEYCTL_CAPS1_NS_KEYRING_NAME |
	       KEYCTL_CAPS1_NS_KEY_TAG),
};

static int key_get_type_from_user(char *type,
Loading