linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] eCryptfs key locking patches
@ 2011-03-21 15:00 Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 1/5] eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat Roberto Sassu
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Roberto Sassu @ 2011-03-21 15:00 UTC (permalink / raw)
  To: tyhicks
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel, Roberto Sassu

[-- Attachment #1: Type: text/plain, Size: 1428 bytes --]

This patch set modifies the eCryptfs code in order to lock requested keys
while authentication tokens are used to encrypt or decrypt files.

Changelog:
  - removed patch "eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix"
	(already applied to the eCryptfs git repository at git.kernel.org);
  - added new patch "eCryptfs: removed num_global_auth_toks from 
	ecryptfs_mount_crypt_stat";
  - patch 3/5: avoid invalidating a global authentication token only if
	key_validate() returns the error -EKEYEXPIRED;
  - patch 3/5: added new function
	process_find_global_auth_tok_for_sig_err() to handle errors
	returned by ecryptfs_find_global_auth_tok_for_sig();
  - patch 3/5: return an error in the function
	ecryptfs_generate_key_packet_set() if at least one global
	authentication token cannot be retrieved.

Roberto Sassu


Roberto Sassu (5):
  eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat
  eCryptfs: modified size of keysig in the ecryptfs_key_sig structure
  eCryptfs: verify authentication tokens before their use
  eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before
    mutex_lock
  eCryptfs: write lock requested keys

 fs/ecryptfs/crypto.c          |    1 -
 fs/ecryptfs/ecryptfs_kernel.h |    4 +-
 fs/ecryptfs/keystore.c        |  280 ++++++++++++++++++++++++++---------------
 fs/ecryptfs/main.c            |    8 +-
 4 files changed, 185 insertions(+), 108 deletions(-)

-- 
1.7.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2061 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/5] eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat
  2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
@ 2011-03-21 15:00 ` Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 2/5] eCryptfs: modified size of keysig in the ecryptfs_key_sig structure Roberto Sassu
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Roberto Sassu @ 2011-03-21 15:00 UTC (permalink / raw)
  To: tyhicks
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel, Roberto Sassu

[-- Attachment #1: Type: text/plain, Size: 2042 bytes --]

This patch removes the 'num_global_auth_toks' field of the
ecryptfs_mount_crypt_stat structure, used to count the number of items in
the 'global_auth_tok_list' list. This variable is not needed because there
are no checks based upon it.

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
---
 fs/ecryptfs/crypto.c          |    1 -
 fs/ecryptfs/ecryptfs_kernel.h |    1 -
 fs/ecryptfs/keystore.c        |    1 -
 3 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index bfd8b68..38178ff 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -266,7 +266,6 @@ void ecryptfs_destroy_mount_crypt_stat(
 				 &mount_crypt_stat->global_auth_tok_list,
 				 mount_crypt_stat_list) {
 		list_del(&auth_tok->mount_crypt_stat_list);
-		mount_crypt_stat->num_global_auth_toks--;
 		if (auth_tok->global_auth_tok_key
 		    && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID))
 			key_put(auth_tok->global_auth_tok_key);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index e007534..6ea1faa 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -380,7 +380,6 @@ struct ecryptfs_mount_crypt_stat {
 	u32 flags;
 	struct list_head global_auth_tok_list;
 	struct mutex global_auth_tok_list_mutex;
-	size_t num_global_auth_toks;
 	size_t global_default_cipher_key_size;
 	size_t global_default_fn_cipher_key_bytes;
 	unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 4feb78c..523e51d 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -2454,7 +2454,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
 	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
 	list_add(&new_auth_tok->mount_crypt_stat_list,
 		 &mount_crypt_stat->global_auth_tok_list);
-	mount_crypt_stat->num_global_auth_toks++;
 	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
 out:
 	return rc;
-- 
1.7.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2061 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/5] eCryptfs: modified size of keysig in the ecryptfs_key_sig structure
  2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 1/5] eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat Roberto Sassu
@ 2011-03-21 15:00 ` Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 3/5] eCryptfs: verify authentication tokens before their use Roberto Sassu
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Roberto Sassu @ 2011-03-21 15:00 UTC (permalink / raw)
  To: tyhicks
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel, Roberto Sassu

[-- Attachment #1: Type: text/plain, Size: 1423 bytes --]

The size of the 'keysig' array is incremented of one byte in order to make
room for the NULL character. The 'keysig' variable is used, in the function
ecryptfs_generate_key_packet_set(), to find an authentication token with
the given signature and is printed a debug message if it cannot be
retrieved.

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
---
 fs/ecryptfs/ecryptfs_kernel.h |    2 +-
 fs/ecryptfs/keystore.c        |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 6ea1faa..f39956a 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -233,7 +233,7 @@ ecryptfs_get_key_payload_data(struct key *key)
 
 struct ecryptfs_key_sig {
 	struct list_head crypt_stat_list;
-	char keysig[ECRYPTFS_SIG_SIZE_HEX];
+	char keysig[ECRYPTFS_SIG_SIZE_HEX + 1];
 };
 
 struct ecryptfs_filename {
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 523e51d..bd139df 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -2425,6 +2425,7 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)
 		return -ENOMEM;
 	}
 	memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX);
+	new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
 	/* Caller must hold keysig_list_mutex */
 	list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list);
 
-- 
1.7.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2061 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/5] eCryptfs: verify authentication tokens before their use
  2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 1/5] eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 2/5] eCryptfs: modified size of keysig in the ecryptfs_key_sig structure Roberto Sassu
@ 2011-03-21 15:00 ` Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 4/5] eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before mutex_lock Roberto Sassu
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Roberto Sassu @ 2011-03-21 15:00 UTC (permalink / raw)
  To: tyhicks
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel, Roberto Sassu

[-- Attachment #1: Type: text/plain, Size: 10563 bytes --]

Authentication tokens content may change if another requestor calls the
update() method of the corresponding key. The new function
ecryptfs_verify_auth_tok_from_key() retrieves the authentication token from
the provided key and verifies if it is still valid before being used to
encrypt or decrypt an eCryptfs file.

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
---
 fs/ecryptfs/ecryptfs_kernel.h |    1 -
 fs/ecryptfs/keystore.c        |  220 ++++++++++++++++++++++++++---------------
 fs/ecryptfs/main.c            |    4 +-
 3 files changed, 144 insertions(+), 81 deletions(-)

diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index f39956a..43ab593 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -333,7 +333,6 @@ struct ecryptfs_global_auth_tok {
 	u32 flags;
 	struct list_head mount_crypt_stat_list;
 	struct key *global_auth_tok_key;
-	struct ecryptfs_auth_tok *global_auth_tok;
 	unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
 };
 
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index bd139df..ff92b3c 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -65,6 +65,26 @@ static int process_request_key_err(long err_code)
 	return rc;
 }
 
+static int process_find_global_auth_tok_for_sig_err(int err_code)
+{
+	int rc = err_code;
+
+	switch (err_code) {
+	case -ENOENT:
+		ecryptfs_printk(KERN_WARNING,
+				"Missing auth tok\n");
+		break;
+	case -EINVAL:
+		ecryptfs_printk(KERN_WARNING,
+				"Invalid auth tok\n");
+		break;
+	default:
+		rc = process_request_key_err(err_code);
+		break;
+	}
+	return rc;
+}
+
 /**
  * ecryptfs_parse_packet_length
  * @data: Pointer to memory containing length at offset
@@ -403,27 +423,122 @@ out:
 	return rc;
 }
 
+/**
+ * ecryptfs_verify_version
+ * @version: The version number to confirm
+ *
+ * Returns zero on good version; non-zero otherwise
+ */
+static int ecryptfs_verify_version(u16 version)
+{
+	int rc = 0;
+	unsigned char major;
+	unsigned char minor;
+
+	major = ((version >> 8) & 0xFF);
+	minor = (version & 0xFF);
+	if (major != ECRYPTFS_VERSION_MAJOR) {
+		ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
+				"Expected [%d]; got [%d]\n",
+				ECRYPTFS_VERSION_MAJOR, major);
+		rc = -EINVAL;
+		goto out;
+	}
+	if (minor != ECRYPTFS_VERSION_MINOR) {
+		ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
+				"Expected [%d]; got [%d]\n",
+				ECRYPTFS_VERSION_MINOR, minor);
+		rc = -EINVAL;
+		goto out;
+	}
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_verify_auth_tok_from_key
+ * @auth_tok_key: key containing the authentication token
+ * @auth_tok: authentication token
+ *
+ * Returns zero on valid auth tok; -EINVAL otherwise
+ */
+static int
+ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
+				  struct ecryptfs_auth_tok **auth_tok)
+{
+	int rc = 0;
+
+	(*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key);
+	if (ecryptfs_verify_version((*auth_tok)->version)) {
+		printk(KERN_ERR
+		       "Data structure version mismatch. "
+		       "Userspace tools must match eCryptfs "
+		       "kernel module with major version [%d] "
+		       "and minor version [%d]\n",
+		       ECRYPTFS_VERSION_MAJOR,
+		       ECRYPTFS_VERSION_MINOR);
+		rc = -EINVAL;
+		goto out;
+	}
+	if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
+	    && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
+		printk(KERN_ERR "Invalid auth_tok structure "
+		       "returned from key query\n");
+		rc = -EINVAL;
+		goto out;
+	}
+out:
+	return rc;
+}
+
 static int
 ecryptfs_find_global_auth_tok_for_sig(
-	struct ecryptfs_global_auth_tok **global_auth_tok,
+	struct key **auth_tok_key,
+	struct ecryptfs_auth_tok **auth_tok,
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
 {
 	struct ecryptfs_global_auth_tok *walker;
 	int rc = 0;
 
-	(*global_auth_tok) = NULL;
+	(*auth_tok_key) = NULL;
+	(*auth_tok) = NULL;
 	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
 	list_for_each_entry(walker,
 			    &mount_crypt_stat->global_auth_tok_list,
 			    mount_crypt_stat_list) {
-		if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
-			rc = key_validate(walker->global_auth_tok_key);
-			if (!rc)
-				(*global_auth_tok) = walker;
+		if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX))
+			continue;
+
+		if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) {
+			rc = -EINVAL;
 			goto out;
 		}
+
+		rc = key_validate(walker->global_auth_tok_key);
+		if (rc) {
+			if (rc == -EKEYEXPIRED)
+				goto out;
+			else
+				goto out_invalid_auth_tok;
+		}
+
+		rc = ecryptfs_verify_auth_tok_from_key(
+				walker->global_auth_tok_key, auth_tok);
+		if (rc)
+			goto out_invalid_auth_tok;
+
+		(*auth_tok_key) = walker->global_auth_tok_key;
+		key_get(*auth_tok_key);
+		goto out;
 	}
-	rc = -EINVAL;
+	rc = -ENOENT;
+	goto out;
+
+out_invalid_auth_tok:
+	printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig);
+	walker->flags |= ECRYPTFS_AUTH_TOK_INVALID;
+	key_put(walker->global_auth_tok_key);
+	walker->global_auth_tok_key = NULL;
 out:
 	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
 	return rc;
@@ -451,14 +566,11 @@ ecryptfs_find_auth_tok_for_sig(
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
 	char *sig)
 {
-	struct ecryptfs_global_auth_tok *global_auth_tok;
 	int rc = 0;
 
-	(*auth_tok_key) = NULL;
-	(*auth_tok) = NULL;
-	if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
-						  mount_crypt_stat, sig)) {
-
+	rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok,
+						   mount_crypt_stat, sig);
+	if (rc == -ENOENT) {
 		/* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the
 		 * mount_crypt_stat structure, we prevent to use auth toks that
 		 * are not inserted through the ecryptfs_add_global_auth_tok
@@ -470,8 +582,8 @@ ecryptfs_find_auth_tok_for_sig(
 
 		rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,
 						       sig);
-	} else
-		(*auth_tok) = global_auth_tok->global_auth_tok;
+	}
+
 	return rc;
 }
 
@@ -1520,38 +1632,6 @@ out:
 	return rc;
 }
 
-/**
- * ecryptfs_verify_version
- * @version: The version number to confirm
- *
- * Returns zero on good version; non-zero otherwise
- */
-static int ecryptfs_verify_version(u16 version)
-{
-	int rc = 0;
-	unsigned char major;
-	unsigned char minor;
-
-	major = ((version >> 8) & 0xFF);
-	minor = (version & 0xFF);
-	if (major != ECRYPTFS_VERSION_MAJOR) {
-		ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
-				"Expected [%d]; got [%d]\n",
-				ECRYPTFS_VERSION_MAJOR, major);
-		rc = -EINVAL;
-		goto out;
-	}
-	if (minor != ECRYPTFS_VERSION_MINOR) {
-		ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
-				"Expected [%d]; got [%d]\n",
-				ECRYPTFS_VERSION_MINOR, minor);
-		rc = -EINVAL;
-		goto out;
-	}
-out:
-	return rc;
-}
-
 int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
 				      struct ecryptfs_auth_tok **auth_tok,
 				      char *sig)
@@ -1566,29 +1646,12 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
 		(*auth_tok_key) = NULL;
 		goto out;
 	}
-	(*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
-	if (ecryptfs_verify_version((*auth_tok)->version)) {
-		printk(KERN_ERR
-		       "Data structure version mismatch. "
-		       "Userspace tools must match eCryptfs "
-		       "kernel module with major version [%d] "
-		       "and minor version [%d]\n",
-		       ECRYPTFS_VERSION_MAJOR,
-		       ECRYPTFS_VERSION_MINOR);
-		rc = -EINVAL;
-		goto out_release_key;
-	}
-	if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
-	    && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
-		printk(KERN_ERR "Invalid auth_tok structure "
-		       "returned from key query\n");
-		rc = -EINVAL;
-		goto out_release_key;
-	}
-out_release_key:
+
+	rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
 	if (rc) {
 		key_put(*auth_tok_key);
 		(*auth_tok_key) = NULL;
+		goto out;
 	}
 out:
 	return rc;
@@ -2325,7 +2388,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,
 				 size_t max)
 {
 	struct ecryptfs_auth_tok *auth_tok;
-	struct ecryptfs_global_auth_tok *global_auth_tok;
+	struct key *auth_tok_key = NULL;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
 		&ecryptfs_superblock_to_private(
 			ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -2344,21 +2407,17 @@ ecryptfs_generate_key_packet_set(char *dest_base,
 	list_for_each_entry(key_sig, &crypt_stat->keysig_list,
 			    crypt_stat_list) {
 		memset(key_rec, 0, sizeof(*key_rec));
-		rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
+		rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key,
+							   &auth_tok,
 							   mount_crypt_stat,
 							   key_sig->keysig);
 		if (rc) {
-			printk(KERN_ERR "Error attempting to get the global "
-			       "auth_tok; rc = [%d]\n", rc);
-			goto out_free;
-		}
-		if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) {
 			printk(KERN_WARNING
-			       "Skipping invalid auth tok with sig = [%s]\n",
-			       global_auth_tok->sig);
-			continue;
+			       "Unable to retrieve auth tok with sig = [%s]\n",
+			       key_sig->keysig);
+			rc = process_find_global_auth_tok_for_sig_err(rc);
+			goto out_free;
 		}
-		auth_tok = global_auth_tok->global_auth_tok;
 		if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
 			rc = write_tag_3_packet((dest_base + (*len)),
 						&max, auth_tok,
@@ -2396,6 +2455,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
 			rc = -EINVAL;
 			goto out_free;
 		}
+		key_put(auth_tok_key);
+		auth_tok_key = NULL;
 	}
 	if (likely(max > 0)) {
 		dest_base[(*len)] = 0x00;
@@ -2408,6 +2469,9 @@ out_free:
 out:
 	if (rc)
 		(*len) = 0;
+	if (auth_tok_key)
+		key_put(auth_tok_key);
+
 	mutex_unlock(&crypt_stat->keysig_list_mutex);
 	return rc;
 }
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 758323a..f079473 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -241,14 +241,14 @@ static int ecryptfs_init_global_auth_toks(
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
 {
 	struct ecryptfs_global_auth_tok *global_auth_tok;
+	struct ecryptfs_auth_tok *auth_tok;
 	int rc = 0;
 
 	list_for_each_entry(global_auth_tok,
 			    &mount_crypt_stat->global_auth_tok_list,
 			    mount_crypt_stat_list) {
 		rc = ecryptfs_keyring_auth_tok_for_sig(
-			&global_auth_tok->global_auth_tok_key,
-			&global_auth_tok->global_auth_tok,
+			&global_auth_tok->global_auth_tok_key, &auth_tok,
 			global_auth_tok->sig);
 		if (rc) {
 			printk(KERN_ERR "Could not find valid key in user "
-- 
1.7.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2061 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 4/5] eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before mutex_lock
  2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
                   ` (2 preceding siblings ...)
  2011-03-21 15:00 ` [PATCH v2 3/5] eCryptfs: verify authentication tokens before their use Roberto Sassu
@ 2011-03-21 15:00 ` Roberto Sassu
  2011-03-21 15:00 ` [PATCH v2 5/5] eCryptfs: write lock requested keys Roberto Sassu
  2011-03-22 21:32 ` [PATCH v2 0/5] eCryptfs key locking patches Tyler Hicks
  5 siblings, 0 replies; 7+ messages in thread
From: Roberto Sassu @ 2011-03-21 15:00 UTC (permalink / raw)
  To: tyhicks
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel, Roberto Sassu

[-- Attachment #1: Type: text/plain, Size: 3055 bytes --]

The ecryptfs_find_auth_tok_for_sig() call is moved before the
mutex_lock(s->tfm_mutex) instruction in order to avoid possible deadlocks
that may occur by holding the lock on the two semaphores 'key->sem' and
's->tfm_mutex' in reverse order.

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
---
 fs/ecryptfs/keystore.c |   38 +++++++++++++++++++-------------------
 1 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index ff92b3c..09b3afe 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -643,6 +643,16 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
 	}
 	s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 	(*packet_size) = 0;
+	rc = ecryptfs_find_auth_tok_for_sig(
+		&auth_tok_key,
+		&s->auth_tok, mount_crypt_stat,
+		mount_crypt_stat->global_default_fnek_sig);
+	if (rc) {
+		printk(KERN_ERR "%s: Error attempting to find auth tok for "
+		       "fnek sig [%s]; rc = [%d]\n", __func__,
+		       mount_crypt_stat->global_default_fnek_sig, rc);
+		goto out;
+	}
 	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(
 		&s->desc.tfm,
 		&s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name);
@@ -728,16 +738,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
 		goto out_free_unlock;
 	}
 	dest[s->i++] = s->cipher_code;
-	rc = ecryptfs_find_auth_tok_for_sig(
-		&auth_tok_key,
-		&s->auth_tok, mount_crypt_stat,
-		mount_crypt_stat->global_default_fnek_sig);
-	if (rc) {
-		printk(KERN_ERR "%s: Error attempting to find auth tok for "
-		       "fnek sig [%s]; rc = [%d]\n", __func__,
-		       mount_crypt_stat->global_default_fnek_sig, rc);
-		goto out_free_unlock;
-	}
 	/* TODO: Support other key modules than passphrase for
 	 * filename encryption */
 	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
@@ -991,6 +991,15 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
 		       __func__, s->cipher_code);
 		goto out;
 	}
+	rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
+					    &s->auth_tok, mount_crypt_stat,
+					    s->fnek_sig_hex);
+	if (rc) {
+		printk(KERN_ERR "%s: Error attempting to find auth tok for "
+		       "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex,
+		       rc);
+		goto out;
+	}
 	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm,
 							&s->tfm_mutex,
 							s->cipher_string);
@@ -1037,15 +1046,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
 	 * >= ECRYPTFS_MAX_IV_BYTES. */
 	memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES);
 	s->desc.info = s->iv;
-	rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
-					    &s->auth_tok, mount_crypt_stat,
-					    s->fnek_sig_hex);
-	if (rc) {
-		printk(KERN_ERR "%s: Error attempting to find auth tok for "
-		       "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex,
-		       rc);
-		goto out_free_unlock;
-	}
 	/* TODO: Support other key modules than passphrase for
 	 * filename encryption */
 	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
-- 
1.7.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2061 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 5/5] eCryptfs: write lock requested keys
  2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
                   ` (3 preceding siblings ...)
  2011-03-21 15:00 ` [PATCH v2 4/5] eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before mutex_lock Roberto Sassu
@ 2011-03-21 15:00 ` Roberto Sassu
  2011-03-22 21:32 ` [PATCH v2 0/5] eCryptfs key locking patches Tyler Hicks
  5 siblings, 0 replies; 7+ messages in thread
From: Roberto Sassu @ 2011-03-21 15:00 UTC (permalink / raw)
  To: tyhicks
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel, Roberto Sassu

[-- Attachment #1: Type: text/plain, Size: 3394 bytes --]

A requested key is write locked in order to prevent modifications on the
authentication token while it is being used.

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
---
 fs/ecryptfs/keystore.c |   26 ++++++++++++++++++++------
 fs/ecryptfs/main.c     |    4 +++-
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 09b3afe..455ce8f 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -522,10 +522,11 @@ ecryptfs_find_global_auth_tok_for_sig(
 				goto out_invalid_auth_tok;
 		}
 
+		down_write(&(walker->global_auth_tok_key->sem));
 		rc = ecryptfs_verify_auth_tok_from_key(
 				walker->global_auth_tok_key, auth_tok);
 		if (rc)
-			goto out_invalid_auth_tok;
+			goto out_invalid_auth_tok_unlock;
 
 		(*auth_tok_key) = walker->global_auth_tok_key;
 		key_get(*auth_tok_key);
@@ -534,6 +535,8 @@ ecryptfs_find_global_auth_tok_for_sig(
 	rc = -ENOENT;
 	goto out;
 
+out_invalid_auth_tok_unlock:
+	up_write(&(walker->global_auth_tok_key->sem));
 out_invalid_auth_tok:
 	printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig);
 	walker->flags |= ECRYPTFS_AUTH_TOK_INVALID;
@@ -877,8 +880,10 @@ out_free_unlock:
 out_unlock:
 	mutex_unlock(s->tfm_mutex);
 out:
-	if (auth_tok_key)
+	if (auth_tok_key) {
+		up_write(&(auth_tok_key->sem));
 		key_put(auth_tok_key);
+	}
 	kfree(s);
 	return rc;
 }
@@ -1114,8 +1119,10 @@ out:
 		(*filename_size) = 0;
 		(*filename) = NULL;
 	}
-	if (auth_tok_key)
+	if (auth_tok_key) {
+		up_write(&(auth_tok_key->sem));
 		key_put(auth_tok_key);
+	}
 	kfree(s);
 	return rc;
 }
@@ -1646,9 +1653,10 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
 		(*auth_tok_key) = NULL;
 		goto out;
 	}
-
+	down_write(&(*auth_tok_key)->sem);
 	rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
 	if (rc) {
+		up_write(&(*auth_tok_key)->sem);
 		key_put(*auth_tok_key);
 		(*auth_tok_key) = NULL;
 		goto out;
@@ -1873,6 +1881,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
 find_next_matching_auth_tok:
 	found_auth_tok = 0;
 	if (auth_tok_key) {
+		up_write(&(auth_tok_key->sem));
 		key_put(auth_tok_key);
 		auth_tok_key = NULL;
 	}
@@ -1959,8 +1968,10 @@ found_matching_auth_tok:
 out_wipe_list:
 	wipe_auth_tok_list(&auth_tok_list);
 out:
-	if (auth_tok_key)
+	if (auth_tok_key) {
+		up_write(&(auth_tok_key->sem));
 		key_put(auth_tok_key);
+	}
 	return rc;
 }
 
@@ -2455,6 +2466,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,
 			rc = -EINVAL;
 			goto out_free;
 		}
+		up_write(&(auth_tok_key->sem));
 		key_put(auth_tok_key);
 		auth_tok_key = NULL;
 	}
@@ -2469,8 +2481,10 @@ out_free:
 out:
 	if (rc)
 		(*len) = 0;
-	if (auth_tok_key)
+	if (auth_tok_key) {
+		up_write(&(auth_tok_key->sem));
 		key_put(auth_tok_key);
+	}
 
 	mutex_unlock(&crypt_stat->keysig_list_mutex);
 	return rc;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index f079473..ada50a3 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -256,8 +256,10 @@ static int ecryptfs_init_global_auth_toks(
 			       "option: [%s]\n", global_auth_tok->sig);
 			global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
 			goto out;
-		} else
+		} else {
 			global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
+			up_write(&(global_auth_tok->global_auth_tok_key)->sem);
+		}
 	}
 out:
 	return rc;
-- 
1.7.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2061 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 0/5] eCryptfs key locking patches
  2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
                   ` (4 preceding siblings ...)
  2011-03-21 15:00 ` [PATCH v2 5/5] eCryptfs: write lock requested keys Roberto Sassu
@ 2011-03-22 21:32 ` Tyler Hicks
  5 siblings, 0 replies; 7+ messages in thread
From: Tyler Hicks @ 2011-03-22 21:32 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: kirkland, dhowells, jmorris, linux-fsdevel, keyrings,
	linux-kernel, ecryptfs-devel

On Mon Mar 21, 2011 at 04:00:50PM +0100, Roberto Sassu <roberto.sassu@polito.it> wrote:
> This patch set modifies the eCryptfs code in order to lock requested keys
> while authentication tokens are used to encrypt or decrypt files.
> 
> Changelog:
>   - removed patch "eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix"
> 	(already applied to the eCryptfs git repository at git.kernel.org);
>   - added new patch "eCryptfs: removed num_global_auth_toks from 
> 	ecryptfs_mount_crypt_stat";
>   - patch 3/5: avoid invalidating a global authentication token only if
> 	key_validate() returns the error -EKEYEXPIRED;
>   - patch 3/5: added new function
> 	process_find_global_auth_tok_for_sig_err() to handle errors
> 	returned by ecryptfs_find_global_auth_tok_for_sig();
>   - patch 3/5: return an error in the function
> 	ecryptfs_generate_key_packet_set() if at least one global
> 	authentication token cannot be retrieved.

Thanks Roberto - This revision looks good to me. I'll keep the patch set
in my tree for another day or two, to see if anyone else has comments,
and then set up a pull request to try to get it into the rc1 release.

Tyler

> 
> Roberto Sassu
> 
> 
> Roberto Sassu (5):
>   eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat
>   eCryptfs: modified size of keysig in the ecryptfs_key_sig structure
>   eCryptfs: verify authentication tokens before their use
>   eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before
>     mutex_lock
>   eCryptfs: write lock requested keys
> 
>  fs/ecryptfs/crypto.c          |    1 -
>  fs/ecryptfs/ecryptfs_kernel.h |    4 +-
>  fs/ecryptfs/keystore.c        |  280 ++++++++++++++++++++++++++---------------
>  fs/ecryptfs/main.c            |    8 +-
>  4 files changed, 185 insertions(+), 108 deletions(-)
> 
> -- 
> 1.7.4
> 



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-03-22 21:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-21 15:00 [PATCH v2 0/5] eCryptfs key locking patches Roberto Sassu
2011-03-21 15:00 ` [PATCH v2 1/5] eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat Roberto Sassu
2011-03-21 15:00 ` [PATCH v2 2/5] eCryptfs: modified size of keysig in the ecryptfs_key_sig structure Roberto Sassu
2011-03-21 15:00 ` [PATCH v2 3/5] eCryptfs: verify authentication tokens before their use Roberto Sassu
2011-03-21 15:00 ` [PATCH v2 4/5] eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before mutex_lock Roberto Sassu
2011-03-21 15:00 ` [PATCH v2 5/5] eCryptfs: write lock requested keys Roberto Sassu
2011-03-22 21:32 ` [PATCH v2 0/5] eCryptfs key locking patches Tyler Hicks

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).