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

Commit 0f44e4d9 authored by David Howells's avatar David Howells
Browse files

keys: Move the user and user-session keyrings to the user_namespace



Move the user and user-session keyrings to the user_namespace struct rather
than pinning them from the user_struct struct.  This prevents these
keyrings from propagating across user-namespaces boundaries with regard to
the KEY_SPEC_* flags, thereby making them more useful in a containerised
environment.

The issue is that a single user_struct may be represent UIDs in several
different namespaces.

The way the patch does this is by attaching a 'register keyring' in each
user_namespace and then sticking the user and user-session keyrings into
that.  It can then be searched to retrieve them.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Jann Horn <jannh@google.com>
parent b206f281
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -7,8 +7,6 @@
#include <linux/refcount.h>
#include <linux/ratelimit.h>

struct key;

/*
 * Some day this will be a full-fledged user tracking system..
 */
@@ -30,18 +28,6 @@ struct user_struct {
	unsigned long unix_inflight;	/* How many files in flight in unix sockets */
	atomic_long_t pipe_bufs;  /* how many pages are allocated in pipe buffers */

#ifdef CONFIG_KEYS
	/*
	 * These pointers can only change from NULL to a non-NULL value once.
	 * Writes are protected by key_user_keyring_mutex.
	 * Unlocked readers should use READ_ONCE() unless they know that
	 * install_user_keyrings() has been called successfully (which sets
	 * these members to non-NULL values, preventing further modifications).
	 */
	struct key *uid_keyring;	/* UID specific keyring */
	struct key *session_keyring;	/* UID's default session keyring */
#endif

	/* Hash table maintenance information */
	struct hlist_node uidhash_node;
	kuid_t uid;
+7 −2
Original line number Diff line number Diff line
@@ -65,14 +65,19 @@ struct user_namespace {
	unsigned long		flags;

#ifdef CONFIG_KEYS
	/* List of joinable keyrings in this namespace */
	/* List of joinable keyrings in this namespace.  Modification access of
	 * these pointers is controlled by keyring_sem.  Once
	 * user_keyring_register is set, it won't be changed, so it can be
	 * accessed directly with READ_ONCE().
	 */
	struct list_head	keyring_name_list;
	struct key		*user_keyring_register;
	struct rw_semaphore	keyring_sem;
#endif

	/* Register of per-UID persistent keyrings for this namespace */
#ifdef CONFIG_PERSISTENT_KEYRINGS
	struct key		*persistent_keyring_register;
	struct rw_semaphore	persistent_keyring_register_sem;
#endif
	struct work_struct	work;
#ifdef CONFIG_SYSCTL
+1 −6
Original line number Diff line number Diff line
@@ -64,10 +64,7 @@ struct user_namespace init_user_ns = {
	.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),
	.keyring_sem = __RWSEM_INITIALIZER(init_user_ns.keyring_sem),
#endif
};
EXPORT_SYMBOL_GPL(init_user_ns);
@@ -143,8 +140,6 @@ static void free_user(struct user_struct *up, unsigned long flags)
{
	uid_hash_remove(up);
	spin_unlock_irqrestore(&uidhash_lock, flags);
	key_put(up->uid_keyring);
	key_put(up->session_keyring);
	kmem_cache_free(uid_cachep, up);
}

+1 −3
Original line number Diff line number Diff line
@@ -135,9 +135,7 @@ int create_user_ns(struct cred *new)

#ifdef CONFIG_KEYS
	INIT_LIST_HEAD(&ns->keyring_name_list);
#endif
#ifdef CONFIG_PERSISTENT_KEYRINGS
	init_rwsem(&ns->persistent_keyring_register_sem);
	init_rwsem(&ns->keyring_sem);
#endif
	ret = -ENOMEM;
	if (!setup_userns_sysctls(ns))
+2 −1
Original line number Diff line number Diff line
@@ -148,7 +148,8 @@ extern key_ref_t search_process_keyrings_rcu(struct keyring_search_context *ctx)

extern struct key *find_keyring_by_name(const char *name, bool uid_keyring);

extern int install_user_keyrings(void);
extern int look_up_user_keyrings(struct key **, struct key **);
extern struct key *get_user_session_keyring_rcu(const struct cred *);
extern int install_thread_keyring_to_cred(struct cred *);
extern int install_process_keyring_to_cred(struct cred *);
extern int install_session_keyring_to_cred(struct cred *, struct key *);
Loading