Skip to content

Commit

Permalink
eCryptfs: Unlock keys needed by ecryptfsd
Browse files Browse the repository at this point in the history
Fixes a regression caused by b5695d0

Kernel keyring keys containing eCryptfs authentication tokens should not
be write locked when calling out to ecryptfsd to wrap and unwrap file
encryption keys. The eCryptfs kernel code can not hold the key's write
lock because ecryptfsd needs to request the key after receiving such a
request from the kernel.

Without this fix, all file opens and creates will timeout and fail when
using the eCryptfs PKI infrastructure. This is not an issue when using
passphrase-based mount keys, which is the most widely deployed eCryptfs
configuration.

Signed-off-by: Tyler Hicks <[email protected]>
Acked-by: Roberto Sassu <[email protected]>
Tested-by: Roberto Sassu <[email protected]>
Tested-by: Alexis Hafner1 <[email protected]>
Cc: <[email protected]> [2.6.39+]
  • Loading branch information
Tyler Hicks committed Jul 29, 2011
1 parent 55f9c40 commit b2987a5
Showing 1 changed file with 25 additions and 22 deletions.
47 changes: 25 additions & 22 deletions fs/ecryptfs/keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -1871,11 +1871,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
* just one will be sufficient to decrypt to get the FEK. */
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;
}
list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) {
candidate_auth_tok = &auth_tok_list_item->auth_tok;
if (unlikely(ecryptfs_verbosity > 0)) {
Expand Down Expand Up @@ -1912,14 +1907,22 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
memcpy(&(candidate_auth_tok->token.private_key),
&(matching_auth_tok->token.private_key),
sizeof(struct ecryptfs_private_key));
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
rc = decrypt_pki_encrypted_session_key(candidate_auth_tok,
crypt_stat);
} else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
memcpy(&(candidate_auth_tok->token.password),
&(matching_auth_tok->token.password),
sizeof(struct ecryptfs_password));
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
rc = decrypt_passphrase_encrypted_session_key(
candidate_auth_tok, crypt_stat);
} else {
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
rc = -EINVAL;
}
if (rc) {
struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;
Expand Down Expand Up @@ -1959,15 +1962,12 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
out_wipe_list:
wipe_auth_tok_list(&auth_tok_list);
out:
if (auth_tok_key) {
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
}
return rc;
}

static int
pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
pki_encrypt_session_key(struct key *auth_tok_key,
struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat,
struct ecryptfs_key_record *key_rec)
{
Expand All @@ -1982,6 +1982,8 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
crypt_stat->cipher,
crypt_stat->key_size),
crypt_stat, &payload, &payload_len);
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
goto out;
Expand Down Expand Up @@ -2011,6 +2013,8 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
* write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
* @dest: Buffer into which to write the packet
* @remaining_bytes: Maximum number of bytes that can be writtn
* @auth_tok_key: The authentication token key to unlock and put when done with
* @auth_tok
* @auth_tok: The authentication token used for generating the tag 1 packet
* @crypt_stat: The cryptographic context
* @key_rec: The key record struct for the tag 1 packet
Expand All @@ -2021,7 +2025,7 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
*/
static int
write_tag_1_packet(char *dest, size_t *remaining_bytes,
struct ecryptfs_auth_tok *auth_tok,
struct key *auth_tok_key, struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat,
struct ecryptfs_key_record *key_rec, size_t *packet_size)
{
Expand All @@ -2042,12 +2046,15 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes,
memcpy(key_rec->enc_key,
auth_tok->session_key.encrypted_key,
auth_tok->session_key.encrypted_key_size);
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
goto encrypted_session_key_set;
}
if (auth_tok->session_key.encrypted_key_size == 0)
auth_tok->session_key.encrypted_key_size =
auth_tok->token.private_key.key_size;
rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
rc = pki_encrypt_session_key(auth_tok_key, auth_tok, crypt_stat,
key_rec);
if (rc) {
printk(KERN_ERR "Failed to encrypt session key via a key "
"module; rc = [%d]\n", rc);
Expand Down Expand Up @@ -2424,6 +2431,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
&max, auth_tok,
crypt_stat, key_rec,
&written);
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
"writing tag 3 packet\n");
Expand All @@ -2441,8 +2450,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
}
(*len) += written;
} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
rc = write_tag_1_packet(dest_base + (*len),
&max, auth_tok,
rc = write_tag_1_packet(dest_base + (*len), &max,
auth_tok_key, auth_tok,
crypt_stat, key_rec, &written);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
Expand All @@ -2451,14 +2460,13 @@ ecryptfs_generate_key_packet_set(char *dest_base,
}
(*len) += written;
} else {
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
ecryptfs_printk(KERN_WARNING, "Unsupported "
"authentication token type\n");
rc = -EINVAL;
goto out_free;
}
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
auth_tok_key = NULL;
}
if (likely(max > 0)) {
dest_base[(*len)] = 0x00;
Expand All @@ -2471,11 +2479,6 @@ ecryptfs_generate_key_packet_set(char *dest_base,
out:
if (rc)
(*len) = 0;
if (auth_tok_key) {
up_write(&(auth_tok_key->sem));
key_put(auth_tok_key);
}

mutex_unlock(&crypt_stat->keysig_list_mutex);
return rc;
}
Expand Down

0 comments on commit b2987a5

Please sign in to comment.