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

Commit b206f281 authored by David Howells's avatar David Howells
Browse files

keys: Namespace keyring names



Keyring names are held in a single global list that any process can pick
from by means of keyctl_join_session_keyring (provided the keyring grants
Search permission).  This isn't very container friendly, however.

Make the following changes:

 (1) Make default session, process and thread keyring names begin with a
     '.' instead of '_'.

 (2) Keyrings whose names begin with a '.' aren't added to the list.  Such
     keyrings are system specials.

 (3) Replace the global list with per-user_namespace lists.  A keyring adds
     its name to the list for the user_namespace that it is currently in.

 (4) When a user_namespace is deleted, it just removes itself from the
     keyring name list.

The global keyring_name_lock is retained for accessing the name lists.
This allows (4) to work.

This can be tested by:

	# keyctl newring foo @s
	995906392
	# unshare -U
	$ keyctl show
	...
	 995906392 --alswrv  65534 65534   \_ keyring: foo
	...
	$ keyctl session foo
	Joined session keyring: 935622349

As can be seen, a new session keyring was created.

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

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Eric W. Biederman <ebiederm@xmission.com>
parent dcf49dbc
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ extern void key_set_timeout(struct key *, unsigned);

extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
				 key_perm_t perm);
extern void key_free_user_ns(struct user_namespace *);

/*
 * The permissions required on a key that we're looking up.
@@ -434,6 +435,7 @@ extern void key_init(void);
#define key_fsuid_changed(c)		do { } while(0)
#define key_fsgid_changed(c)		do { } while(0)
#define key_init()			do { } while(0)
#define key_free_user_ns(ns)		do { } while(0)

#endif /* CONFIG_KEYS */
#endif /* __KERNEL__ */
+5 −0
Original line number Diff line number Diff line
@@ -64,6 +64,11 @@ struct user_namespace {
	struct ns_common	ns;
	unsigned long		flags;

#ifdef CONFIG_KEYS
	/* List of joinable keyrings in this namespace */
	struct list_head	keyring_name_list;
#endif

	/* Register of per-UID persistent keyrings for this namespace */
#ifdef CONFIG_PERSISTENT_KEYRINGS
	struct key		*persistent_keyring_register;
+1 −0
Original line number Diff line number Diff line
@@ -128,5 +128,6 @@ struct keyctl_pkey_params {
#define KEYCTL_CAPS0_INVALIDATE		0x20 /* KEYCTL_INVALIDATE supported */
#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 */

#endif /*  _LINUX_KEYCTL_H */
+3 −0
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ struct user_namespace init_user_ns = {
	.ns.ops = &userns_operations,
#endif
	.flags = USERNS_INIT_FLAGS,
#ifdef CONFIG_KEYS
	.keyring_name_list = LIST_HEAD_INIT(init_user_ns.keyring_name_list),
#endif
#ifdef CONFIG_PERSISTENT_KEYRINGS
	.persistent_keyring_register_sem =
	__RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
+4 −3
Original line number Diff line number Diff line
@@ -133,6 +133,9 @@ int create_user_ns(struct cred *new)
	ns->flags = parent_ns->flags;
	mutex_unlock(&userns_state_mutex);

#ifdef CONFIG_KEYS
	INIT_LIST_HEAD(&ns->keyring_name_list);
#endif
#ifdef CONFIG_PERSISTENT_KEYRINGS
	init_rwsem(&ns->persistent_keyring_register_sem);
#endif
@@ -196,9 +199,7 @@ static void free_user_ns(struct work_struct *work)
			kfree(ns->projid_map.reverse);
		}
		retire_userns_sysctls(ns);
#ifdef CONFIG_PERSISTENT_KEYRINGS
		key_put(ns->persistent_keyring_register);
#endif
		key_free_user_ns(ns);
		ns_free_inum(&ns->ns);
		kmem_cache_free(user_ns_cachep, ns);
		dec_user_namespaces(ucounts);
Loading