All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
To: Eric Biggers <ebiggers@kernel.org>,
	"Theodore Y. Ts'o" <tytso@mit.edu>,
	Jaegeuk Kim <jaegeuk@kernel.org>,
	linux-fscrypt@vger.kernel.org, kernel-team@meta.com
Cc: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
Subject: [PATCH v1 5/7] fscrypt: reclaim pooled prepared keys under pressure
Date: Tue, 18 Apr 2023 22:42:14 -0400	[thread overview]
Message-ID: <4513ae7360866fee4bbc2f800f77d0b74a9fa3ec.1681871298.git.sweettea-kernel@dorminy.me> (raw)
In-Reply-To: <cover.1681871298.git.sweettea-kernel@dorminy.me>

While it is to be hoped that the pools of prepared keys are sized
appropriately, there is no way to guarantee that they will never have
pressure short of expanding the pool for every user -- and that defeats
the goal of not allocating a prepared key for every user. So, a
mechanism to 'steal' a prepared key from its current owner must be
added, to support another info using the prepared key.

This adds that stealing mechanism. Currently, on pressure, the head of
the active prepared key list is stolen; this selection mechanism is
likely suboptimal, and is improved in a later change.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 fs/crypto/keysetup.c | 47 +++++++++++++++++++++++++++++++-------------
 1 file changed, 33 insertions(+), 14 deletions(-)

diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index aed60280ad32..c12a26c81611 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -260,8 +260,8 @@ static void __fscrypt_return_key_to_pool(struct fscrypt_key_pool *pool,
 	/* Pairs with the acquire in get_pooled_key_owner() */
 	smp_store_release(&key->owner, NULL);
 	list_move(&key->pool_link, &pool->free_keys);
-	mutex_unlock(&pool->mutex);
 	mutex_unlock(&key->mutex);
+	mutex_unlock(&pool->mutex);
 }
 
 static void fscrypt_return_key_to_pool(struct fscrypt_info *ci)
@@ -269,17 +269,20 @@ static void fscrypt_return_key_to_pool(struct fscrypt_info *ci)
 	struct fscrypt_pooled_prepared_key *pooled_key;
 	const u8 mode_num = ci->ci_mode - fscrypt_modes;
 	struct fscrypt_master_key *mk = ci->ci_master_key;
+	struct fscrypt_key_pool *pool = &mk->mk_key_pools[mode_num];
 
 	mutex_lock(&pool->mutex);
 	/* Try to lock the key. If we don't, it's already been stolen. */
-	if (fscrypt_lock_pooled_key(ci) != 0)
+	if (fscrypt_lock_pooled_key(ci) != 0) {
+		mutex_unlock(&pool->mutex);
 		return;
+	}
 
 	pooled_key = container_of(ci->ci_enc_key,
 				  struct fscrypt_pooled_prepared_key,
 				  prep_key);
 
-	__fscrypt_return_key_to_pool(&mk->mk_key_pools[mode_num], pooled_key);
+	__fscrypt_return_key_to_pool(pool, pooled_key);
 }
 
 static int fscrypt_allocate_new_pooled_key(struct fscrypt_key_pool *pool,
@@ -302,13 +305,33 @@ static int fscrypt_allocate_new_pooled_key(struct fscrypt_key_pool *pool,
 	pooled_key->prep_key.type = FSCRYPT_KEY_POOLED;
 	mutex_init(&pooled_key->mutex);
 	INIT_LIST_HEAD(&pooled_key->pool_link);
+	mutex_lock(&pool->mutex);
 	mutex_lock(&pooled_key->mutex);
 	__fscrypt_return_key_to_pool(pool, pooled_key);
 	return 0;
 }
 
+static struct fscrypt_pooled_prepared_key *
+fscrypt_select_victim_key(struct fscrypt_key_pool *pool)
+{
+	return list_first_entry(&pool->active_keys,
+				struct fscrypt_pooled_prepared_key, pool_link);
+}
+
+static void fscrypt_steal_an_active_key(struct fscrypt_key_pool *pool)
+{
+	struct fscrypt_pooled_prepared_key *key;
+
+	key = fscrypt_select_victim_key(pool);
+	mutex_lock(&key->mutex);
+	/* Pairs with the acquire in get_pooled_key_owner() */
+	smp_store_release(&key->owner, NULL);
+	list_move(&key->pool_link, &pool->free_keys);
+	mutex_unlock(&key->mutex);
+}
+
 /*
- * Gets a key out of the free list, and locks it for use.
+ * Gets a key out of the free list, possibly stealing it along the way.
  */
 static int fscrypt_get_key_from_pool(struct fscrypt_key_pool *pool,
 				     struct fscrypt_info *ci)
@@ -316,10 +339,14 @@ static int fscrypt_get_key_from_pool(struct fscrypt_key_pool *pool,
 	struct fscrypt_pooled_prepared_key *key;
 
 	mutex_lock(&pool->mutex);
-	if (WARN_ON_ONCE(list_empty(&pool->free_keys))) {
+	if (list_empty(&pool->free_keys) && list_empty(&pool->active_keys)) {
 		mutex_unlock(&pool->mutex);
-		return -EBUSY;
+		return -EINVAL;
 	}
+
+	if (list_empty(&pool->free_keys))
+		fscrypt_steal_an_active_key(pool);
+
 	key = list_first_entry(&pool->free_keys,
 			       struct fscrypt_pooled_prepared_key, pool_link);
 
@@ -959,16 +986,8 @@ fscrypt_setup_encryption_info(struct inode *inode,
 		res = fscrypt_setup_file_key(crypt_info, mk);
 		if (res)
 			goto out;
-	} else {
-		const u8 mode_num = mode - fscrypt_modes;
-		struct fscrypt_key_pool *pool = &mk->mk_key_pools[mode_num];
-
-		res = fscrypt_allocate_new_pooled_key(pool, mode);
-		if (res)
-			return res;
 	}
 
-
 	/*
 	 * Derive a secret dirhash key for directories that need it. It
 	 * should be impossible to set flags such that a v1 policy sets
-- 
2.40.0


  parent reply	other threads:[~2023-04-19  2:42 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-19  2:42 [PATCH v1 0/7] fscrypt: add pooled prepared keys facility Sweet Tea Dorminy
2023-04-19  2:42 ` [PATCH v1 1/7] fscrypt: add new pooled prepared keys Sweet Tea Dorminy
2023-04-19  2:42 ` [PATCH v1 2/7] fscrypt: set up pooled keys upon first use Sweet Tea Dorminy
2023-04-19  2:42 ` [PATCH v1 3/7] fscrypt: add pooling of pooled prepared keys Sweet Tea Dorminy
2023-04-19  2:42 ` [PATCH v1 4/7] fscrypt: add pooled prepared key locking around use Sweet Tea Dorminy
2023-04-19  2:42 ` Sweet Tea Dorminy [this message]
2023-04-19  2:42 ` [PATCH v1 6/7] fscrypt: add facility to shrink a pool of keys Sweet Tea Dorminy
2023-04-19  2:42 ` [PATCH v1 7/7] fscrypt: add lru mechanism to choose pooled key Sweet Tea Dorminy
2023-05-02  3:47 ` [PATCH v1 0/7] fscrypt: add pooled prepared keys facility Eric Biggers
2023-05-05 12:15   ` Sweet Tea Dorminy
2023-05-05 22:40     ` Eric Biggers
2023-05-06  0:35       ` Sweet Tea Dorminy
2023-05-15  6:40         ` Eric Biggers
2023-05-16 18:34           ` Sweet Tea Dorminy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4513ae7360866fee4bbc2f800f77d0b74a9fa3ec.1681871298.git.sweettea-kernel@dorminy.me \
    --to=sweettea-kernel@dorminy.me \
    --cc=ebiggers@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=kernel-team@meta.com \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.