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

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

KEYS: Add per-user_namespace registers for persistent per-UID kerberos caches



Add support for per-user_namespace registers of persistent per-UID kerberos
caches held within the kernel.

This allows the kerberos cache to be retained beyond the life of all a user's
processes so that the user's cron jobs can work.

The kerberos cache is envisioned as a keyring/key tree looking something like:

	struct user_namespace
	  \___ .krb_cache keyring		- The register
		\___ _krb.0 keyring		- Root's Kerberos cache
		\___ _krb.5000 keyring		- User 5000's Kerberos cache
		\___ _krb.5001 keyring		- User 5001's Kerberos cache
			\___ tkt785 big_key	- A ccache blob
			\___ tkt12345 big_key	- Another ccache blob

Or possibly:

	struct user_namespace
	  \___ .krb_cache keyring		- The register
		\___ _krb.0 keyring		- Root's Kerberos cache
		\___ _krb.5000 keyring		- User 5000's Kerberos cache
		\___ _krb.5001 keyring		- User 5001's Kerberos cache
			\___ tkt785 keyring	- A ccache
				\___ krbtgt/REDHAT.COM@REDHAT.COM big_key
				\___ http/REDHAT.COM@REDHAT.COM user
				\___ afs/REDHAT.COM@REDHAT.COM user
				\___ nfs/REDHAT.COM@REDHAT.COM user
				\___ krbtgt/KERNEL.ORG@KERNEL.ORG big_key
				\___ http/KERNEL.ORG@KERNEL.ORG big_key

What goes into a particular Kerberos cache is entirely up to userspace.  Kernel
support is limited to giving you the Kerberos cache keyring that you want.

The user asks for their Kerberos cache by:

	krb_cache = keyctl_get_krbcache(uid, dest_keyring);

The uid is -1 or the user's own UID for the user's own cache or the uid of some
other user's cache (requires CAP_SETUID).  This permits rpc.gssd or whatever to
mess with the cache.

The cache returned is a keyring named "_krb.<uid>" that the possessor can read,
search, clear, invalidate, unlink from and add links to.  Active LSMs get a
chance to rule on whether the caller is permitted to make a link.

Each uid's cache keyring is created when it first accessed and is given a
timeout that is extended each time this function is called so that the keyring
goes away after a while.  The timeout is configurable by sysctl but defaults to
three days.

Each user_namespace struct gets a lazily-created keyring that serves as the
register.  The cache keyrings are added to it.  This means that standard key
search and garbage collection facilities are available.

The user_namespace struct's register goes away when it does and anything left
in it is then automatically gc'd.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Tested-by: default avatarSimo Sorce <simo@redhat.com>
cc: Serge E. Hallyn <serge.hallyn@ubuntu.com>
cc: Eric W. Biederman <ebiederm@xmission.com>
parent ab3c3587
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -27,6 +27,12 @@ struct user_namespace {
	kuid_t			owner;
	kgid_t			group;
	unsigned int		proc_inum;

	/* 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
};

extern struct user_namespace init_user_ns;
+1 −0
Original line number Diff line number Diff line
@@ -56,5 +56,6 @@
#define KEYCTL_REJECT			19	/* reject a partially constructed key */
#define KEYCTL_INSTANTIATE_IOV		20	/* instantiate a partially constructed key */
#define KEYCTL_INVALIDATE		21	/* invalidate a key */
#define KEYCTL_GET_PERSISTENT		22	/* get a user's persistent keyring */

#endif /*  _LINUX_KEYCTL_H */
+4 −0
Original line number Diff line number Diff line
@@ -51,6 +51,10 @@ struct user_namespace init_user_ns = {
	.owner = GLOBAL_ROOT_UID,
	.group = GLOBAL_ROOT_GID,
	.proc_inum = PROC_USER_INIT_INO,
#ifdef CONFIG_KEYS_KERBEROS_CACHE
	.krb_cache_register_sem =
	__RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem),
#endif
};
EXPORT_SYMBOL_GPL(init_user_ns);

+6 −0
Original line number Diff line number Diff line
@@ -101,6 +101,9 @@ int create_user_ns(struct cred *new)

	set_cred_user_ns(new, ns);

#ifdef CONFIG_PERSISTENT_KEYRINGS
	init_rwsem(&ns->persistent_keyring_register_sem);
#endif
	return 0;
}

@@ -130,6 +133,9 @@ void free_user_ns(struct user_namespace *ns)

	do {
		parent = ns->parent;
#ifdef CONFIG_PERSISTENT_KEYRINGS
		key_put(ns->persistent_keyring_register);
#endif
		proc_free_inum(ns->proc_inum);
		kmem_cache_free(user_ns_cachep, ns);
		ns = parent;
+17 −0
Original line number Diff line number Diff line
@@ -20,6 +20,23 @@ config KEYS

	  If you are unsure as to whether this is required, answer N.

config PERSISTENT_KEYRINGS
	bool "Enable register of persistent per-UID keyrings"
	depends on KEYS
	help
	  This option provides a register of persistent per-UID keyrings,
	  primarily aimed at Kerberos key storage.  The keyrings are persistent
	  in the sense that they stay around after all processes of that UID
	  have exited, not that they survive the machine being rebooted.

	  A particular keyring may be accessed by either the user whose keyring
	  it is or by a process with administrative privileges.  The active
	  LSMs gets to rule on which admin-level processes get to access the
	  cache.

	  Keyrings are created and added into the register upon demand and get
	  removed if they expire (a default timeout is set upon creation).

config BIG_KEYS
	tristate "Large payload keys"
	depends on KEYS
Loading