aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-02-22 09:38:34 -0500
committerDavid Howells <dhowells@redhat.com>2018-02-22 09:58:38 -0500
commitd9f4bb1a0f4db493efe6d7c58ffe696a57de7eb3 (patch)
tree259ac728946dd076a4b118f6e504929fe42b08d4
parent4b34968e77ad09628cfb3c4a7daf2adc2cefc6e8 (diff)
KEYS: Use individual pages in big_key for crypto buffers
kmalloc() can't always allocate large enough buffers for big_key to use for crypto (1MB + some metadata) so we cannot use that to allocate the buffer. Further, vmalloc'd pages can't be passed to sg_init_one() and the aead crypto accessors cannot be called progressively and must be passed all the data in one go (which means we can't pass the data in one block at a time). Fix this by allocating the buffer pages individually and passing them through a multientry scatterlist to the crypto layer. This has the bonus advantage that we don't have to allocate a contiguous series of pages. We then vmap() the page list and pass that through to the VFS read/write routines. This can trigger a warning: WARNING: CPU: 0 PID: 60912 at mm/page_alloc.c:3883 __alloc_pages_nodemask+0xb7c/0x15f8 ([<00000000002acbb6>] __alloc_pages_nodemask+0x1ee/0x15f8) [<00000000002dd356>] kmalloc_order+0x46/0x90 [<00000000002dd3e0>] kmalloc_order_trace+0x40/0x1f8 [<0000000000326a10>] __kmalloc+0x430/0x4c0 [<00000000004343e4>] big_key_preparse+0x7c/0x210 [<000000000042c040>] key_create_or_update+0x128/0x420 [<000000000042e52c>] SyS_add_key+0x124/0x220 [<00000000007bba2c>] system_call+0xc4/0x2b0 from the keyctl/padd/useradd test of the keyutils testsuite on s390x. Note that it might be better to shovel data through in page-sized lumps instead as there's no particular need to use a monolithic buffer unless the kernel itself wants to access the data. Fixes: 13100a72f40f ("Security: Keys: Big keys stored encrypted") Reported-by: Paul Bunyan <pbunyan@redhat.com> Signed-off-by: David Howells <dhowells@redhat.com> cc: Kirill Marinushkin <k.marinushkin@gmail.com>
-rw-r--r--security/keys/big_key.c110
1 files changed, 87 insertions, 23 deletions
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 929e14978c42..fa728f662a6f 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -22,6 +22,13 @@
22#include <keys/big_key-type.h> 22#include <keys/big_key-type.h>
23#include <crypto/aead.h> 23#include <crypto/aead.h>
24 24
25struct big_key_buf {
26 unsigned int nr_pages;
27 void *virt;
28 struct scatterlist *sg;
29 struct page *pages[];
30};
31
25/* 32/*
26 * Layout of key payload words. 33 * Layout of key payload words.
27 */ 34 */
@@ -91,10 +98,9 @@ static DEFINE_MUTEX(big_key_aead_lock);
91/* 98/*
92 * Encrypt/decrypt big_key data 99 * Encrypt/decrypt big_key data
93 */ 100 */
94static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) 101static int big_key_crypt(enum big_key_op op, struct big_key_buf *buf, size_t datalen, u8 *key)
95{ 102{
96 int ret; 103 int ret;
97 struct scatterlist sgio;
98 struct aead_request *aead_req; 104 struct aead_request *aead_req;
99 /* We always use a zero nonce. The reason we can get away with this is 105 /* We always use a zero nonce. The reason we can get away with this is
100 * because we're using a different randomly generated key for every 106 * because we're using a different randomly generated key for every
@@ -109,8 +115,7 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
109 return -ENOMEM; 115 return -ENOMEM;
110 116
111 memset(zero_nonce, 0, sizeof(zero_nonce)); 117 memset(zero_nonce, 0, sizeof(zero_nonce));
112 sg_init_one(&sgio, data, datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0)); 118 aead_request_set_crypt(aead_req, buf->sg, buf->sg, datalen, zero_nonce);
113 aead_request_set_crypt(aead_req, &sgio, &sgio, datalen, zero_nonce);
114 aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); 119 aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
115 aead_request_set_ad(aead_req, 0); 120 aead_request_set_ad(aead_req, 0);
116 121
@@ -130,21 +135,81 @@ error:
130} 135}
131 136
132/* 137/*
138 * Free up the buffer.
139 */
140static void big_key_free_buffer(struct big_key_buf *buf)
141{
142 unsigned int i;
143
144 if (buf->virt) {
145 memset(buf->virt, 0, buf->nr_pages * PAGE_SIZE);
146 vunmap(buf->virt);
147 }
148
149 for (i = 0; i < buf->nr_pages; i++)
150 if (buf->pages[i])
151 __free_page(buf->pages[i]);
152
153 kfree(buf);
154}
155
156/*
157 * Allocate a buffer consisting of a set of pages with a virtual mapping
158 * applied over them.
159 */
160static void *big_key_alloc_buffer(size_t len)
161{
162 struct big_key_buf *buf;
163 unsigned int npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
164 unsigned int i, l;
165
166 buf = kzalloc(sizeof(struct big_key_buf) +
167 sizeof(struct page) * npg +
168 sizeof(struct scatterlist) * npg,
169 GFP_KERNEL);
170 if (!buf)
171 return NULL;
172
173 buf->nr_pages = npg;
174 buf->sg = (void *)(buf->pages + npg);
175 sg_init_table(buf->sg, npg);
176
177 for (i = 0; i < buf->nr_pages; i++) {
178 buf->pages[i] = alloc_page(GFP_KERNEL);
179 if (!buf->pages[i])
180 goto nomem;
181
182 l = min_t(size_t, len, PAGE_SIZE);
183 sg_set_page(&buf->sg[i], buf->pages[i], l, 0);
184 len -= l;
185 }
186
187 buf->virt = vmap(buf->pages, buf->nr_pages, VM_MAP, PAGE_KERNEL);
188 if (!buf->virt)
189 goto nomem;
190
191 return buf;
192
193nomem:
194 big_key_free_buffer(buf);
195 return NULL;
196}
197
198/*
133 * Preparse a big key 199 * Preparse a big key
134 */ 200 */
135int big_key_preparse(struct key_preparsed_payload *prep) 201int big_key_preparse(struct key_preparsed_payload *prep)
136{ 202{
203 struct big_key_buf *buf;
137 struct path *path = (struct path *)&prep->payload.data[big_key_path]; 204 struct path *path = (struct path *)&prep->payload.data[big_key_path];
138 struct file *file; 205 struct file *file;
139 u8 *enckey; 206 u8 *enckey;
140 u8 *data = NULL;
141 ssize_t written; 207 ssize_t written;
142 size_t datalen = prep->datalen; 208 size_t datalen = prep->datalen, enclen = datalen + ENC_AUTHTAG_SIZE;
143 int ret; 209 int ret;
144 210
145 ret = -EINVAL;
146 if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data) 211 if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
147 goto error; 212 return -EINVAL;
148 213
149 /* Set an arbitrary quota */ 214 /* Set an arbitrary quota */
150 prep->quotalen = 16; 215 prep->quotalen = 16;
@@ -157,13 +222,12 @@ int big_key_preparse(struct key_preparsed_payload *prep)
157 * 222 *
158 * File content is stored encrypted with randomly generated key. 223 * File content is stored encrypted with randomly generated key.
159 */ 224 */
160 size_t enclen = datalen + ENC_AUTHTAG_SIZE;
161 loff_t pos = 0; 225 loff_t pos = 0;
162 226
163 data = kmalloc(enclen, GFP_KERNEL); 227 buf = big_key_alloc_buffer(enclen);
164 if (!data) 228 if (!buf)
165 return -ENOMEM; 229 return -ENOMEM;
166 memcpy(data, prep->data, datalen); 230 memcpy(buf->virt, prep->data, datalen);
167 231
168 /* generate random key */ 232 /* generate random key */
169 enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL); 233 enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
@@ -176,7 +240,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
176 goto err_enckey; 240 goto err_enckey;
177 241
178 /* encrypt aligned data */ 242 /* encrypt aligned data */
179 ret = big_key_crypt(BIG_KEY_ENC, data, datalen, enckey); 243 ret = big_key_crypt(BIG_KEY_ENC, buf, datalen, enckey);
180 if (ret) 244 if (ret)
181 goto err_enckey; 245 goto err_enckey;
182 246
@@ -187,7 +251,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
187 goto err_enckey; 251 goto err_enckey;
188 } 252 }
189 253
190 written = kernel_write(file, data, enclen, &pos); 254 written = kernel_write(file, buf->virt, enclen, &pos);
191 if (written != enclen) { 255 if (written != enclen) {
192 ret = written; 256 ret = written;
193 if (written >= 0) 257 if (written >= 0)
@@ -202,7 +266,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
202 *path = file->f_path; 266 *path = file->f_path;
203 path_get(path); 267 path_get(path);
204 fput(file); 268 fput(file);
205 kzfree(data); 269 big_key_free_buffer(buf);
206 } else { 270 } else {
207 /* Just store the data in a buffer */ 271 /* Just store the data in a buffer */
208 void *data = kmalloc(datalen, GFP_KERNEL); 272 void *data = kmalloc(datalen, GFP_KERNEL);
@@ -220,7 +284,7 @@ err_fput:
220err_enckey: 284err_enckey:
221 kzfree(enckey); 285 kzfree(enckey);
222error: 286error:
223 kzfree(data); 287 big_key_free_buffer(buf);
224 return ret; 288 return ret;
225} 289}
226 290
@@ -298,15 +362,15 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
298 return datalen; 362 return datalen;
299 363
300 if (datalen > BIG_KEY_FILE_THRESHOLD) { 364 if (datalen > BIG_KEY_FILE_THRESHOLD) {
365 struct big_key_buf *buf;
301 struct path *path = (struct path *)&key->payload.data[big_key_path]; 366 struct path *path = (struct path *)&key->payload.data[big_key_path];
302 struct file *file; 367 struct file *file;
303 u8 *data;
304 u8 *enckey = (u8 *)key->payload.data[big_key_data]; 368 u8 *enckey = (u8 *)key->payload.data[big_key_data];
305 size_t enclen = datalen + ENC_AUTHTAG_SIZE; 369 size_t enclen = datalen + ENC_AUTHTAG_SIZE;
306 loff_t pos = 0; 370 loff_t pos = 0;
307 371
308 data = kmalloc(enclen, GFP_KERNEL); 372 buf = big_key_alloc_buffer(enclen);
309 if (!data) 373 if (!buf)
310 return -ENOMEM; 374 return -ENOMEM;
311 375
312 file = dentry_open(path, O_RDONLY, current_cred()); 376 file = dentry_open(path, O_RDONLY, current_cred());
@@ -316,26 +380,26 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
316 } 380 }
317 381
318 /* read file to kernel and decrypt */ 382 /* read file to kernel and decrypt */
319 ret = kernel_read(file, data, enclen, &pos); 383 ret = kernel_read(file, buf->virt, enclen, &pos);
320 if (ret >= 0 && ret != enclen) { 384 if (ret >= 0 && ret != enclen) {
321 ret = -EIO; 385 ret = -EIO;
322 goto err_fput; 386 goto err_fput;
323 } 387 }
324 388
325 ret = big_key_crypt(BIG_KEY_DEC, data, enclen, enckey); 389 ret = big_key_crypt(BIG_KEY_DEC, buf, enclen, enckey);
326 if (ret) 390 if (ret)
327 goto err_fput; 391 goto err_fput;
328 392
329 ret = datalen; 393 ret = datalen;
330 394
331 /* copy decrypted data to user */ 395 /* copy decrypted data to user */
332 if (copy_to_user(buffer, data, datalen) != 0) 396 if (copy_to_user(buffer, buf->virt, datalen) != 0)
333 ret = -EFAULT; 397 ret = -EFAULT;
334 398
335err_fput: 399err_fput:
336 fput(file); 400 fput(file);
337error: 401error:
338 kzfree(data); 402 big_key_free_buffer(buf);
339 } else { 403 } else {
340 ret = datalen; 404 ret = datalen;
341 if (copy_to_user(buffer, key->payload.data[big_key_data], 405 if (copy_to_user(buffer, key->payload.data[big_key_data],