aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/miscdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ecryptfs/miscdev.c')
-rw-r--r--fs/ecryptfs/miscdev.c140
1 files changed, 85 insertions, 55 deletions
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 940a82e63dc3..349209dc6a91 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -218,6 +218,29 @@ out_unlock:
218 return rc; 218 return rc;
219} 219}
220 220
221/*
222 * miscdevfs packet format:
223 * Octet 0: Type
224 * Octets 1-4: network byte order msg_ctx->counter
225 * Octets 5-N0: Size of struct ecryptfs_message to follow
226 * Octets N0-N1: struct ecryptfs_message (including data)
227 *
228 * Octets 5-N1 not written if the packet type does not include a message
229 */
230#define PKT_TYPE_SIZE 1
231#define PKT_CTR_SIZE 4
232#define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE)
233#define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
234 + ECRYPTFS_MIN_PKT_LEN_SIZE)
235/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */
236#define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
237 + ECRYPTFS_MAX_PKT_LEN_SIZE \
238 + sizeof(struct ecryptfs_message) \
239 + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)
240#define PKT_TYPE_OFFSET 0
241#define PKT_CTR_OFFSET PKT_TYPE_SIZE
242#define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE)
243
221/** 244/**
222 * ecryptfs_miscdev_read - format and send message from queue 245 * ecryptfs_miscdev_read - format and send message from queue
223 * @file: fs/ecryptfs/euid miscdevfs handle (ignored) 246 * @file: fs/ecryptfs/euid miscdevfs handle (ignored)
@@ -237,7 +260,7 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
237 struct ecryptfs_daemon *daemon; 260 struct ecryptfs_daemon *daemon;
238 struct ecryptfs_msg_ctx *msg_ctx; 261 struct ecryptfs_msg_ctx *msg_ctx;
239 size_t packet_length_size; 262 size_t packet_length_size;
240 char packet_length[3]; 263 char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
241 size_t i; 264 size_t i;
242 size_t total_length; 265 size_t total_length;
243 uid_t euid = current_euid(); 266 uid_t euid = current_euid();
@@ -305,15 +328,8 @@ check_list:
305 packet_length_size = 0; 328 packet_length_size = 0;
306 msg_ctx->msg_size = 0; 329 msg_ctx->msg_size = 0;
307 } 330 }
308 /* miscdevfs packet format: 331 total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
309 * Octet 0: Type 332 + msg_ctx->msg_size);
310 * Octets 1-4: network byte order msg_ctx->counter
311 * Octets 5-N0: Size of struct ecryptfs_message to follow
312 * Octets N0-N1: struct ecryptfs_message (including data)
313 *
314 * Octets 5-N1 not written if the packet type does not
315 * include a message */
316 total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
317 if (count < total_length) { 333 if (count < total_length) {
318 rc = 0; 334 rc = 0;
319 printk(KERN_WARNING "%s: Only given user buffer of " 335 printk(KERN_WARNING "%s: Only given user buffer of "
@@ -324,9 +340,10 @@ check_list:
324 rc = -EFAULT; 340 rc = -EFAULT;
325 if (put_user(msg_ctx->type, buf)) 341 if (put_user(msg_ctx->type, buf))
326 goto out_unlock_msg_ctx; 342 goto out_unlock_msg_ctx;
327 if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1))) 343 if (put_user(cpu_to_be32(msg_ctx->counter),
344 (__be32 __user *)(&buf[PKT_CTR_OFFSET])))
328 goto out_unlock_msg_ctx; 345 goto out_unlock_msg_ctx;
329 i = 5; 346 i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
330 if (msg_ctx->msg) { 347 if (msg_ctx->msg) {
331 if (copy_to_user(&buf[i], packet_length, packet_length_size)) 348 if (copy_to_user(&buf[i], packet_length, packet_length_size))
332 goto out_unlock_msg_ctx; 349 goto out_unlock_msg_ctx;
@@ -391,12 +408,6 @@ out:
391 * @count: Amount of data in @buf 408 * @count: Amount of data in @buf
392 * @ppos: Pointer to offset in file (ignored) 409 * @ppos: Pointer to offset in file (ignored)
393 * 410 *
394 * miscdevfs packet format:
395 * Octet 0: Type
396 * Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
397 * Octets 5-N0: Size of struct ecryptfs_message to follow
398 * Octets N0-N1: struct ecryptfs_message (including data)
399 *
400 * Returns the number of bytes read from @buf 411 * Returns the number of bytes read from @buf
401 */ 412 */
402static ssize_t 413static ssize_t
@@ -405,60 +416,78 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
405{ 416{
406 __be32 counter_nbo; 417 __be32 counter_nbo;
407 u32 seq; 418 u32 seq;
408 size_t packet_size, packet_size_length, i; 419 size_t packet_size, packet_size_length;
409 ssize_t sz = 0;
410 char *data; 420 char *data;
411 uid_t euid = current_euid(); 421 uid_t euid = current_euid();
412 int rc; 422 unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE];
423 ssize_t rc;
413 424
414 if (count == 0) 425 if (count == 0) {
415 goto out; 426 return 0;
427 } else if (count == MIN_NON_MSG_PKT_SIZE) {
428 /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
429 goto memdup;
430 } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) {
431 printk(KERN_WARNING "%s: Acceptable packet size range is "
432 "[%d-%lu], but amount of data written is [%zu].",
433 __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count);
434 return -EINVAL;
435 }
436
437 if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET],
438 sizeof(packet_size_peek))) {
439 printk(KERN_WARNING "%s: Error while inspecting packet size\n",
440 __func__);
441 return -EFAULT;
442 }
416 443
444 rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
445 &packet_size_length);
446 if (rc) {
447 printk(KERN_WARNING "%s: Error parsing packet length; "
448 "rc = [%zd]\n", __func__, rc);
449 return rc;
450 }
451
452 if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size)
453 != count) {
454 printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
455 packet_size);
456 return -EINVAL;
457 }
458
459memdup:
417 data = memdup_user(buf, count); 460 data = memdup_user(buf, count);
418 if (IS_ERR(data)) { 461 if (IS_ERR(data)) {
419 printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", 462 printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
420 __func__, PTR_ERR(data)); 463 __func__, PTR_ERR(data));
421 goto out; 464 return PTR_ERR(data);
422 } 465 }
423 sz = count; 466 switch (data[PKT_TYPE_OFFSET]) {
424 i = 0;
425 switch (data[i++]) {
426 case ECRYPTFS_MSG_RESPONSE: 467 case ECRYPTFS_MSG_RESPONSE:
427 if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) { 468 if (count < (MIN_MSG_PKT_SIZE
469 + sizeof(struct ecryptfs_message))) {
428 printk(KERN_WARNING "%s: Minimum acceptable packet " 470 printk(KERN_WARNING "%s: Minimum acceptable packet "
429 "size is [%zd], but amount of data written is " 471 "size is [%zd], but amount of data written is "
430 "only [%zd]. Discarding response packet.\n", 472 "only [%zd]. Discarding response packet.\n",
431 __func__, 473 __func__,
432 (1 + 4 + 1 + sizeof(struct ecryptfs_message)), 474 (MIN_MSG_PKT_SIZE
433 count); 475 + sizeof(struct ecryptfs_message)), count);
476 rc = -EINVAL;
434 goto out_free; 477 goto out_free;
435 } 478 }
436 memcpy(&counter_nbo, &data[i], 4); 479 memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);
437 seq = be32_to_cpu(counter_nbo); 480 seq = be32_to_cpu(counter_nbo);
438 i += 4; 481 rc = ecryptfs_miscdev_response(
439 rc = ecryptfs_parse_packet_length(&data[i], &packet_size, 482 &data[PKT_LEN_OFFSET + packet_size_length],
440 &packet_size_length); 483 packet_size, euid, current_user_ns(),
484 task_pid(current), seq);
441 if (rc) { 485 if (rc) {
442 printk(KERN_WARNING "%s: Error parsing packet length; "
443 "rc = [%d]\n", __func__, rc);
444 goto out_free;
445 }
446 i += packet_size_length;
447 if ((1 + 4 + packet_size_length + packet_size) != count) {
448 printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
449 " + packet_size([%zd]))([%zd]) != "
450 "count([%zd]). Invalid packet format.\n",
451 __func__, packet_size_length, packet_size,
452 (1 + packet_size_length + packet_size), count);
453 goto out_free;
454 }
455 rc = ecryptfs_miscdev_response(&data[i], packet_size,
456 euid, current_user_ns(),
457 task_pid(current), seq);
458 if (rc)
459 printk(KERN_WARNING "%s: Failed to deliver miscdev " 486 printk(KERN_WARNING "%s: Failed to deliver miscdev "
460 "response to requesting operation; rc = [%d]\n", 487 "response to requesting operation; rc = [%zd]\n",
461 __func__, rc); 488 __func__, rc);
489 goto out_free;
490 }
462 break; 491 break;
463 case ECRYPTFS_MSG_HELO: 492 case ECRYPTFS_MSG_HELO:
464 case ECRYPTFS_MSG_QUIT: 493 case ECRYPTFS_MSG_QUIT:
@@ -467,12 +496,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
467 ecryptfs_printk(KERN_WARNING, "Dropping miscdev " 496 ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
468 "message of unrecognized type [%d]\n", 497 "message of unrecognized type [%d]\n",
469 data[0]); 498 data[0]);
470 break; 499 rc = -EINVAL;
500 goto out_free;
471 } 501 }
502 rc = count;
472out_free: 503out_free:
473 kfree(data); 504 kfree(data);
474out: 505 return rc;
475 return sz;
476} 506}
477 507
478 508