]>
Commit | Line | Data |
---|---|---|
0d1514e0 GKH |
1 | From b2987a5e05ec7a1af7ca42e5d5349d7a22753031 Mon Sep 17 00:00:00 2001 |
2 | From: Tyler Hicks <tyhicks@linux.vnet.ibm.com> | |
3 | Date: Tue, 26 Jul 2011 19:47:08 -0500 | |
4 | Subject: eCryptfs: Unlock keys needed by ecryptfsd | |
5 | ||
6 | From: Tyler Hicks <tyhicks@linux.vnet.ibm.com> | |
7 | ||
8 | commit b2987a5e05ec7a1af7ca42e5d5349d7a22753031 upstream. | |
9 | ||
10 | Fixes a regression caused by b5695d04634fa4ccca7dcbc05bb4a66522f02e0b | |
11 | ||
12 | Kernel keyring keys containing eCryptfs authentication tokens should not | |
13 | be write locked when calling out to ecryptfsd to wrap and unwrap file | |
14 | encryption keys. The eCryptfs kernel code can not hold the key's write | |
15 | lock because ecryptfsd needs to request the key after receiving such a | |
16 | request from the kernel. | |
17 | ||
18 | Without this fix, all file opens and creates will timeout and fail when | |
19 | using the eCryptfs PKI infrastructure. This is not an issue when using | |
20 | passphrase-based mount keys, which is the most widely deployed eCryptfs | |
21 | configuration. | |
22 | ||
23 | Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com> | |
24 | Acked-by: Roberto Sassu <roberto.sassu@polito.it> | |
25 | Tested-by: Roberto Sassu <roberto.sassu@polito.it> | |
26 | Tested-by: Alexis Hafner1 <haf@zurich.ibm.com> | |
27 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
28 | ||
29 | --- | |
30 | fs/ecryptfs/keystore.c | 47 +++++++++++++++++++++++++---------------------- | |
31 | 1 file changed, 25 insertions(+), 22 deletions(-) | |
32 | ||
33 | --- a/fs/ecryptfs/keystore.c | |
34 | +++ b/fs/ecryptfs/keystore.c | |
35 | @@ -1868,11 +1868,6 @@ int ecryptfs_parse_packet_set(struct ecr | |
36 | * just one will be sufficient to decrypt to get the FEK. */ | |
37 | find_next_matching_auth_tok: | |
38 | found_auth_tok = 0; | |
39 | - if (auth_tok_key) { | |
40 | - up_write(&(auth_tok_key->sem)); | |
41 | - key_put(auth_tok_key); | |
42 | - auth_tok_key = NULL; | |
43 | - } | |
44 | list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) { | |
45 | candidate_auth_tok = &auth_tok_list_item->auth_tok; | |
46 | if (unlikely(ecryptfs_verbosity > 0)) { | |
47 | @@ -1909,14 +1904,22 @@ found_matching_auth_tok: | |
48 | memcpy(&(candidate_auth_tok->token.private_key), | |
49 | &(matching_auth_tok->token.private_key), | |
50 | sizeof(struct ecryptfs_private_key)); | |
51 | + up_write(&(auth_tok_key->sem)); | |
52 | + key_put(auth_tok_key); | |
53 | rc = decrypt_pki_encrypted_session_key(candidate_auth_tok, | |
54 | crypt_stat); | |
55 | } else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) { | |
56 | memcpy(&(candidate_auth_tok->token.password), | |
57 | &(matching_auth_tok->token.password), | |
58 | sizeof(struct ecryptfs_password)); | |
59 | + up_write(&(auth_tok_key->sem)); | |
60 | + key_put(auth_tok_key); | |
61 | rc = decrypt_passphrase_encrypted_session_key( | |
62 | candidate_auth_tok, crypt_stat); | |
63 | + } else { | |
64 | + up_write(&(auth_tok_key->sem)); | |
65 | + key_put(auth_tok_key); | |
66 | + rc = -EINVAL; | |
67 | } | |
68 | if (rc) { | |
69 | struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp; | |
70 | @@ -1956,15 +1959,12 @@ found_matching_auth_tok: | |
71 | out_wipe_list: | |
72 | wipe_auth_tok_list(&auth_tok_list); | |
73 | out: | |
74 | - if (auth_tok_key) { | |
75 | - up_write(&(auth_tok_key->sem)); | |
76 | - key_put(auth_tok_key); | |
77 | - } | |
78 | return rc; | |
79 | } | |
80 | ||
81 | static int | |
82 | -pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |
83 | +pki_encrypt_session_key(struct key *auth_tok_key, | |
84 | + struct ecryptfs_auth_tok *auth_tok, | |
85 | struct ecryptfs_crypt_stat *crypt_stat, | |
86 | struct ecryptfs_key_record *key_rec) | |
87 | { | |
88 | @@ -1979,6 +1979,8 @@ pki_encrypt_session_key(struct ecryptfs_ | |
89 | crypt_stat->cipher, | |
90 | crypt_stat->key_size), | |
91 | crypt_stat, &payload, &payload_len); | |
92 | + up_write(&(auth_tok_key->sem)); | |
93 | + key_put(auth_tok_key); | |
94 | if (rc) { | |
95 | ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); | |
96 | goto out; | |
97 | @@ -2008,6 +2010,8 @@ out: | |
98 | * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet | |
99 | * @dest: Buffer into which to write the packet | |
100 | * @remaining_bytes: Maximum number of bytes that can be writtn | |
101 | + * @auth_tok_key: The authentication token key to unlock and put when done with | |
102 | + * @auth_tok | |
103 | * @auth_tok: The authentication token used for generating the tag 1 packet | |
104 | * @crypt_stat: The cryptographic context | |
105 | * @key_rec: The key record struct for the tag 1 packet | |
106 | @@ -2018,7 +2022,7 @@ out: | |
107 | */ | |
108 | static int | |
109 | write_tag_1_packet(char *dest, size_t *remaining_bytes, | |
110 | - struct ecryptfs_auth_tok *auth_tok, | |
111 | + struct key *auth_tok_key, struct ecryptfs_auth_tok *auth_tok, | |
112 | struct ecryptfs_crypt_stat *crypt_stat, | |
113 | struct ecryptfs_key_record *key_rec, size_t *packet_size) | |
114 | { | |
115 | @@ -2039,12 +2043,15 @@ write_tag_1_packet(char *dest, size_t *r | |
116 | memcpy(key_rec->enc_key, | |
117 | auth_tok->session_key.encrypted_key, | |
118 | auth_tok->session_key.encrypted_key_size); | |
119 | + up_write(&(auth_tok_key->sem)); | |
120 | + key_put(auth_tok_key); | |
121 | goto encrypted_session_key_set; | |
122 | } | |
123 | if (auth_tok->session_key.encrypted_key_size == 0) | |
124 | auth_tok->session_key.encrypted_key_size = | |
125 | auth_tok->token.private_key.key_size; | |
126 | - rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec); | |
127 | + rc = pki_encrypt_session_key(auth_tok_key, auth_tok, crypt_stat, | |
128 | + key_rec); | |
129 | if (rc) { | |
130 | printk(KERN_ERR "Failed to encrypt session key via a key " | |
131 | "module; rc = [%d]\n", rc); | |
132 | @@ -2421,6 +2428,8 @@ ecryptfs_generate_key_packet_set(char *d | |
133 | &max, auth_tok, | |
134 | crypt_stat, key_rec, | |
135 | &written); | |
136 | + up_write(&(auth_tok_key->sem)); | |
137 | + key_put(auth_tok_key); | |
138 | if (rc) { | |
139 | ecryptfs_printk(KERN_WARNING, "Error " | |
140 | "writing tag 3 packet\n"); | |
141 | @@ -2438,8 +2447,8 @@ ecryptfs_generate_key_packet_set(char *d | |
142 | } | |
143 | (*len) += written; | |
144 | } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { | |
145 | - rc = write_tag_1_packet(dest_base + (*len), | |
146 | - &max, auth_tok, | |
147 | + rc = write_tag_1_packet(dest_base + (*len), &max, | |
148 | + auth_tok_key, auth_tok, | |
149 | crypt_stat, key_rec, &written); | |
150 | if (rc) { | |
151 | ecryptfs_printk(KERN_WARNING, "Error " | |
152 | @@ -2448,14 +2457,13 @@ ecryptfs_generate_key_packet_set(char *d | |
153 | } | |
154 | (*len) += written; | |
155 | } else { | |
156 | + up_write(&(auth_tok_key->sem)); | |
157 | + key_put(auth_tok_key); | |
158 | ecryptfs_printk(KERN_WARNING, "Unsupported " | |
159 | "authentication token type\n"); | |
160 | rc = -EINVAL; | |
161 | goto out_free; | |
162 | } | |
163 | - up_write(&(auth_tok_key->sem)); | |
164 | - key_put(auth_tok_key); | |
165 | - auth_tok_key = NULL; | |
166 | } | |
167 | if (likely(max > 0)) { | |
168 | dest_base[(*len)] = 0x00; | |
169 | @@ -2468,11 +2476,6 @@ out_free: | |
170 | out: | |
171 | if (rc) | |
172 | (*len) = 0; | |
173 | - if (auth_tok_key) { | |
174 | - up_write(&(auth_tok_key->sem)); | |
175 | - key_put(auth_tok_key); | |
176 | - } | |
177 | - | |
178 | mutex_unlock(&crypt_stat->keysig_list_mutex); | |
179 | return rc; | |
180 | } |