Re: [PATCH v3] eCryptfs: Unlock keys needed by ecryptfsd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday, July 27, 2011 02:47:08 AM Tyler Hicks wrote:
> Fixes a regression caused by b5695d04634fa4ccca7dcbc05bb4a66522f02e0b
> 
> 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 <tyhicks@xxxxxxxxxxxxxxxxxx>
> Cc: Roberto Sassu <roberto.sassu@xxxxxxxxx>
> Cc: Alexis Hafner1 <haf@xxxxxxxxxxxxxx>
> Cc: <da_fox@xxxxxxxxxxxxxxxxx>

I've tested it. It seems that the issue has been solved.

Acked-by: Roberto Sassu <roberto.sassu@xxxxxxxxx>


> ---
>  fs/ecryptfs/keystore.c |   47
> +++++++++++++++++++++++++---------------------- 1 files changed, 25
> insertions(+), 22 deletions(-)
> 
> diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
> index 27a7fef..89dc18e 100644
> --- a/fs/ecryptfs/keystore.c
> +++ b/fs/ecryptfs/keystore.c
> @@ -1868,11 +1868,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)) {
> @@ -1909,14 +1904,22 @@ found_matching_auth_tok:
>  		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;
> @@ -1956,15 +1959,12 @@ found_matching_auth_tok:
>  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)
>  {
> @@ -1979,6 +1979,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;
> @@ -2008,6 +2010,8 @@ out:
>   * 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
> @@ -2018,7 +2022,7 @@ out:
>   */
>  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)
>  {
> @@ -2039,12 +2043,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);
> @@ -2421,6 +2428,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");
> @@ -2438,8 +2447,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 "
> @@ -2448,14 +2457,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;
> @@ -2468,11 +2476,6 @@ out_free:
>  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;
>  }
--
To unsubscribe from this list: send the line "unsubscribe ecryptfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Crypto]     [Device Mapper Crypto]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux