1238 lines · 37.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Filesystem-level keyring for fscrypt * * Copyright 2019 Google LLC */ /* * This file implements management of fscrypt master keys in the * filesystem-level keyring, including the ioctls: * * - FS_IOC_ADD_ENCRYPTION_KEY * - FS_IOC_REMOVE_ENCRYPTION_KEY * - FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS * - FS_IOC_GET_ENCRYPTION_KEY_STATUS * * See the "User API" section of Documentation/filesystems/fscrypt.rst for more * information about these ioctls. */ #include <crypto/skcipher.h>#include <linux/export.h>#include <linux/key-type.h>#include <linux/once.h>#include <linux/random.h>#include <linux/seq_file.h>#include <linux/unaligned.h> #include "fscrypt_private.h" /* The master encryption keys for a filesystem (->s_master_keys) */struct fscrypt_keyring {	/*	 * Lock that protects ->key_hashtable.  It does *not* protect the	 * fscrypt_master_key structs themselves.	 */	spinlock_t lock; 	/* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */	struct hlist_head key_hashtable[128];}; static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret){	memzero_explicit(secret, sizeof(*secret));} static void move_master_key_secret(struct fscrypt_master_key_secret *dst,				   struct fscrypt_master_key_secret *src){	memcpy(dst, src, sizeof(*dst));	memzero_explicit(src, sizeof(*src));} static void fscrypt_free_master_key(struct rcu_head *head){	struct fscrypt_master_key *mk =		container_of(head, struct fscrypt_master_key, mk_rcu_head);	/*	 * The master key secret and any embedded subkeys should have already	 * been wiped when the last active reference to the fscrypt_master_key	 * struct was dropped; doing it here would be unnecessarily late.	 * Nevertheless, use kfree_sensitive() in case anything was missed.	 */	kfree_sensitive(mk);} static void clear_mk_users(struct fscrypt_master_key *mk); void fscrypt_put_master_key(struct fscrypt_master_key *mk){	if (!refcount_dec_and_test(&mk->mk_struct_refs))		return;	/*	 * No structural references left, so clear ->mk_users, and also free the	 * fscrypt_master_key struct itself after an RCU grace period ensures	 * that concurrent keyring lookups can no longer find it.	 */	WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 0);	clear_mk_users(mk);	call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);} void fscrypt_put_master_key_activeref(struct super_block *sb,				      struct fscrypt_master_key *mk){	struct fscrypt_mode_key *node, *tmp; 	if (!refcount_dec_and_test(&mk->mk_active_refs))		return;	/*	 * No active references left, so complete the full removal of this	 * fscrypt_master_key struct by removing it from the keyring and	 * destroying any non-file-scoped subkeys.	 */ 	if (WARN_ON_ONCE(!sb->s_master_keys))		return;	spin_lock(&sb->s_master_keys->lock);	hlist_del_rcu(&mk->mk_node);	spin_unlock(&sb->s_master_keys->lock); 	/*	 * ->mk_active_refs == 0 implies that ->mk_present is false and	 * ->mk_decrypted_inodes is empty.	 */	WARN_ON_ONCE(mk->mk_present);	WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes)); 	/*	 * Destroy any non-file-scoped subkeys.  Since ->mk_active_refs == 0,	 * they're no longer referenced by any inodes.  Nor can key setup run	 * and use them again.  So they're no longer needed.  (This implies no	 * concurrent readers, so we don't need list_del_rcu() for example.)	 */	list_for_each_entry_safe(node, tmp, &mk->mk_mode_keys, link) {		fscrypt_destroy_prepared_key(sb, &node->key);		list_del(&node->link);		kfree(node);	}	memzero_explicit(&mk->mk_ino_hash_key,			 sizeof(mk->mk_ino_hash_key));	mk->mk_ino_hash_key_initialized = false; 	/* Drop the structural ref associated with the active refs. */	fscrypt_put_master_key(mk);} /* * This transitions the key state from present to incompletely removed, and then * potentially to absent (depending on whether inodes remain). */static void fscrypt_initiate_key_removal(struct super_block *sb,					 struct fscrypt_master_key *mk){	WRITE_ONCE(mk->mk_present, false);	wipe_master_key_secret(&mk->mk_secret);	fscrypt_put_master_key_activeref(sb, mk);} static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec){	if (spec->__reserved)		return false;	return master_key_spec_len(spec) != 0;} static int fscrypt_user_key_instantiate(struct key *key,					struct key_preparsed_payload *prep){	/*	 * We just charge FSCRYPT_MAX_RAW_KEY_SIZE bytes to the user's key quota	 * for each key, regardless of the exact key size.  The amount of memory	 * actually used is greater than the size of the raw key anyway.	 */	return key_payload_reserve(key, FSCRYPT_MAX_RAW_KEY_SIZE);} static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m){	seq_puts(m, key->description);} /* * Type of fscrypt_master_key_user::quota_key.  This contains no secret; it * exists solely to charge a user's key quota. * * Note that the name of this key type really should be something like * ".fscrypt-user" instead of simply ".fscrypt".  But the shorter name is chosen * mainly for simplicity of presentation in /proc/keys when read by a non-root * user.  And it is expected to be rare that a key is actually added by multiple * users, since users should keep their encryption keys confidential. */static struct key_type key_type_fscrypt_user = {	.name			= ".fscrypt",	.instantiate		= fscrypt_user_key_instantiate,	.describe		= fscrypt_user_key_describe,}; #define FSCRYPT_MK_USER_DESCRIPTION_SIZE	\	(2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1) /* Create ->s_master_keys if needed.  Synchronized by fscrypt_add_key_mutex. */static int allocate_filesystem_keyring(struct super_block *sb){	struct fscrypt_keyring *keyring; 	if (sb->s_master_keys)		return 0; 	keyring = kzalloc_obj(*keyring);	if (!keyring)		return -ENOMEM;	spin_lock_init(&keyring->lock);	/*	 * Pairs with the smp_load_acquire() in fscrypt_find_master_key().	 * I.e., here we publish ->s_master_keys with a RELEASE barrier so that	 * concurrent tasks can ACQUIRE it.	 */	smp_store_release(&sb->s_master_keys, keyring);	return 0;} /* * Release all encryption keys that have been added to the filesystem, along * with the keyring that contains them. * * This is called at unmount time, after all potentially-encrypted inodes have * been evicted.  The filesystem's underlying block device(s) are still * available at this time; this is important because after user file accesses * have been allowed, this function may need to evict keys from the keyslots of * an inline crypto engine, which requires the block device(s). */void fscrypt_destroy_keyring(struct super_block *sb){	struct fscrypt_keyring *keyring = sb->s_master_keys;	size_t i; 	if (!keyring)		return; 	for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) {		struct hlist_head *bucket = &keyring->key_hashtable[i];		struct fscrypt_master_key *mk;		struct hlist_node *tmp; 		hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {			/*			 * Since all potentially-encrypted inodes were already			 * evicted, every key remaining in the keyring should			 * have an empty inode list, and should only still be in			 * the keyring due to the single active ref associated			 * with ->mk_present.  There should be no structural			 * refs beyond the one associated with the active ref.			 */			WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 1);			WARN_ON_ONCE(refcount_read(&mk->mk_struct_refs) != 1);			WARN_ON_ONCE(!mk->mk_present);			fscrypt_initiate_key_removal(sb, mk);		}	}	kfree_sensitive(keyring);	sb->s_master_keys = NULL;} static struct hlist_head *fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,		       const struct fscrypt_key_specifier *mk_spec){	/*	 * Since key specifiers should be "random" values, it is sufficient to	 * use a trivial hash function that just takes the first several bits of	 * the key specifier.	 */	unsigned long i = get_unaligned((unsigned long *)&mk_spec->u); 	return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)];} /* * Find the specified master key struct in ->s_master_keys and take a structural * ref to it.  The structural ref guarantees that the key struct continues to * exist, but it does *not* guarantee that ->s_master_keys continues to contain * the key struct.  The structural ref needs to be dropped by * fscrypt_put_master_key().  Returns NULL if the key struct is not found. */struct fscrypt_master_key *fscrypt_find_master_key(struct super_block *sb,			const struct fscrypt_key_specifier *mk_spec){	struct fscrypt_keyring *keyring;	struct hlist_head *bucket;	struct fscrypt_master_key *mk; 	/*	 * Pairs with the smp_store_release() in allocate_filesystem_keyring().	 * I.e., another task can publish ->s_master_keys concurrently,	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here	 * to safely ACQUIRE the memory the other task published.	 */	keyring = smp_load_acquire(&sb->s_master_keys);	if (keyring == NULL)		return NULL; /* No keyring yet, so no keys yet. */ 	bucket = fscrypt_mk_hash_bucket(keyring, mk_spec);	rcu_read_lock();	switch (mk_spec->type) {	case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:		hlist_for_each_entry_rcu(mk, bucket, mk_node) {			if (mk->mk_spec.type ==				FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&			    memcmp(mk->mk_spec.u.descriptor,				   mk_spec->u.descriptor,				   FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 &&			    refcount_inc_not_zero(&mk->mk_struct_refs))				goto out;		}		break;	case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:		hlist_for_each_entry_rcu(mk, bucket, mk_node) {			if (mk->mk_spec.type ==				FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&			    memcmp(mk->mk_spec.u.identifier,				   mk_spec->u.identifier,				   FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 &&			    refcount_inc_not_zero(&mk->mk_struct_refs))				goto out;		}		break;	}	mk = NULL;out:	rcu_read_unlock();	return mk;} /* Find the current user's claim in ->mk_users.  ->mk_sem must be held. */static struct fscrypt_master_key_user *find_master_key_user(struct fscrypt_master_key *mk){	struct fscrypt_master_key_user *mk_user;	kuid_t uid = current_fsuid(); 	list_for_each_entry(mk_user, &mk->mk_users, link) {		if (uid_eq(mk_user->uid, uid))			return mk_user;	}	return NULL;} /* * Give the current user a claim in ->mk_users.  This charges the user's quota * and marks the master key as added by the current user, so that it cannot be * removed by another user with the key.  Either ->mk_sem must be held for * write, or the master key must be still undergoing initialization. */static int add_master_key_user(struct fscrypt_master_key *mk){	kuid_t uid = current_fsuid();	char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];	struct key *quota_key;	struct fscrypt_master_key_user *mk_user;	int err; 	snprintf(description, sizeof(description), "%*phN.uid.%u",		 FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier,		 __kuid_val(uid));	quota_key = key_alloc(&key_type_fscrypt_user, description, uid,			      current_gid(), current_cred(),			      KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);	if (IS_ERR(quota_key))		return PTR_ERR(quota_key); 	err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL);	if (err) {		key_put(quota_key);		return err;	} 	mk_user = kzalloc_obj(*mk_user);	if (!mk_user) {		key_put(quota_key);		return -ENOMEM;	}	mk_user->uid = uid;	mk_user->quota_key = quota_key;	list_add(&mk_user->link, &mk->mk_users);	return 0;} static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user){	list_del(&mk_user->link);	key_put(mk_user->quota_key);	kfree(mk_user);} /* * Remove the current user's claim from ->mk_users. * ->mk_sem must be held for write. * * Returns 0 if removed or -ENOKEY if not found. */static int remove_master_key_user(struct fscrypt_master_key *mk){	struct fscrypt_master_key_user *mk_user; 	mk_user = find_master_key_user(mk);	if (!mk_user)		return -ENOKEY;	unlink_and_free_mk_user(mk_user);	return 0;} /* * Clear ->mk_users.  Either ->mk_sem must be held for write, or 'mk' must have * no structural references left. */static void clear_mk_users(struct fscrypt_master_key *mk){	struct fscrypt_master_key_user *mk_user, *tmp; 	list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link)		unlink_and_free_mk_user(mk_user);} /* * Allocate a new fscrypt_master_key, transfer the given secret over to it, and * insert it into sb->s_master_keys. */static int add_new_master_key(struct super_block *sb,			      struct fscrypt_master_key_secret *secret,			      const struct fscrypt_key_specifier *mk_spec){	struct fscrypt_keyring *keyring = sb->s_master_keys;	struct fscrypt_master_key *mk;	int err; 	mk = kzalloc_obj(*mk);	if (!mk)		return -ENOMEM; 	init_rwsem(&mk->mk_sem);	refcount_set(&mk->mk_struct_refs, 1);	mk->mk_spec = *mk_spec; 	INIT_LIST_HEAD(&mk->mk_users); 	INIT_LIST_HEAD(&mk->mk_decrypted_inodes);	spin_lock_init(&mk->mk_decrypted_inodes_lock); 	INIT_LIST_HEAD(&mk->mk_mode_keys); 	if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {		err = add_master_key_user(mk);		if (err)			goto out_put;	} 	move_master_key_secret(&mk->mk_secret, secret);	mk->mk_present = true;	refcount_set(&mk->mk_active_refs, 1); /* ->mk_present is true */ 	spin_lock(&keyring->lock);	hlist_add_head_rcu(&mk->mk_node,			   fscrypt_mk_hash_bucket(keyring, mk_spec));	spin_unlock(&keyring->lock);	return 0; out_put:	fscrypt_put_master_key(mk);	return err;} #define KEY_DEAD	1 static int add_existing_master_key(struct fscrypt_master_key *mk,				   struct fscrypt_master_key_secret *secret){	int err; 	/*	 * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current	 * user is already in ->mk_users, then there's nothing to do.	 * Otherwise, add the user to ->mk_users.	 */	if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {		if (find_master_key_user(mk) != NULL)			return 0;		err = add_master_key_user(mk);		if (err)			return err;	} 	/* If the key is incompletely removed, make it present again. */	if (!mk->mk_present) {		if (!refcount_inc_not_zero(&mk->mk_active_refs)) {			/*			 * Raced with the last active ref being dropped, so the			 * key has become, or is about to become, "absent".			 * Therefore, we need to allocate a new key struct.			 */			return KEY_DEAD;		}		move_master_key_secret(&mk->mk_secret, secret);		WRITE_ONCE(mk->mk_present, true);	} 	return 0;} static int do_add_master_key(struct super_block *sb,			     struct fscrypt_master_key_secret *secret,			     const struct fscrypt_key_specifier *mk_spec){	static DEFINE_MUTEX(fscrypt_add_key_mutex);	struct fscrypt_master_key *mk;	int err; 	guard(mutex)(&fscrypt_add_key_mutex); /* serialize find + link */

Lines 1–500 of 1238.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t