aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/miscdev.c
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2012-01-12 05:30:44 -0500
committerTyler Hicks <tyhicks@canonical.com>2012-01-25 15:43:39 -0500
commitdb10e556518eb9d21ee92ff944530d84349684f4 (patch)
tree84a82f496a4fe4ee90812b5d7f2cd358f9730911 /fs/ecryptfs/miscdev.c
parentbb4503615d95d6826b7907986ad574e3157877e8 (diff)
eCryptfs: Sanitize write counts of /dev/ecryptfs
A malicious count value specified when writing to /dev/ecryptfs may result in a a very large kernel memory allocation. This patch peeks at the specified packet payload size, adds that to the size of the packet headers and compares the result with the write count value. The resulting maximum memory allocation size is approximately 532 bytes. Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Reported-by: Sasha Levin <levinsasha928@gmail.com> Cc: <stable@vger.kernel.org>
Diffstat (limited to 'fs/ecryptfs/miscdev.c')
-rw-r--r--fs/ecryptfs/miscdev.c56
1 files changed, 38 insertions, 18 deletions
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 940a82e63dc..0dc5a3d554a 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -409,11 +409,47 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
409 ssize_t sz = 0; 409 ssize_t sz = 0;
410 char *data; 410 char *data;
411 uid_t euid = current_euid(); 411 uid_t euid = current_euid();
412 unsigned char packet_size_peek[3];
412 int rc; 413 int rc;
413 414
414 if (count == 0) 415 if (count == 0) {
415 goto out; 416 goto out;
417 } else if (count == (1 + 4)) {
418 /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
419 goto memdup;
420 } else if (count < (1 + 4 + 1)
421 || count > (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4
422 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)) {
423 printk(KERN_WARNING "%s: Acceptable packet size range is "
424 "[%d-%lu], but amount of data written is [%zu].",
425 __func__, (1 + 4 + 1),
426 (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4
427 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES), count);
428 return -EINVAL;
429 }
430
431 if (copy_from_user(packet_size_peek, (buf + 1 + 4),
432 sizeof(packet_size_peek))) {
433 printk(KERN_WARNING "%s: Error while inspecting packet size\n",
434 __func__);
435 return -EFAULT;
436 }
437
438 rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
439 &packet_size_length);
440 if (rc) {
441 printk(KERN_WARNING "%s: Error parsing packet length; "
442 "rc = [%d]\n", __func__, rc);
443 return rc;
444 }
445
446 if ((1 + 4 + packet_size_length + packet_size) != count) {
447 printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
448 packet_size);
449 return -EINVAL;
450 }
416 451
452memdup:
417 data = memdup_user(buf, count); 453 data = memdup_user(buf, count);
418 if (IS_ERR(data)) { 454 if (IS_ERR(data)) {
419 printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", 455 printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
@@ -435,23 +471,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
435 } 471 }
436 memcpy(&counter_nbo, &data[i], 4); 472 memcpy(&counter_nbo, &data[i], 4);
437 seq = be32_to_cpu(counter_nbo); 473 seq = be32_to_cpu(counter_nbo);
438 i += 4; 474 i += 4 + packet_size_length;
439 rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
440 &packet_size_length);
441 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, 475 rc = ecryptfs_miscdev_response(&data[i], packet_size,
456 euid, current_user_ns(), 476 euid, current_user_ns(),
457 task_pid(current), seq); 477 task_pid(current), seq);