diff options
Diffstat (limited to 'fs/ecryptfs/miscdev.c')
-rw-r--r-- | fs/ecryptfs/miscdev.c | 56 |
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 | ||
452 | memdup: | ||
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); |