summaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2016-07-03 17:01:26 -0400
committerTheodore Ts'o <tytso@mit.edu>2016-07-03 17:09:33 -0400
commit86a574de4590ffe6fd3f3ca34cdcf655a78e36ec (patch)
tree37646e0f13ef16a5a55a15571330944c6ede92bf /drivers/char/random.c
parentc92e040d575a7389d72e7e6f25e2033bfb867f8b (diff)
random: strengthen input validation for RNDADDTOENTCNT
Don't allow RNDADDTOENTCNT or RNDADDENTROPY to accept a negative entropy value. It doesn't make any sense to subtract from the entropy counter, and it can trigger a warning: random: negative entropy/overflow: pool input count -40000 ------------[ cut here ]------------ WARNING: CPU: 3 PID: 6828 at drivers/char/random.c:670[< none >] credit_entropy_bits+0x21e/0xad0 drivers/char/random.c:670 Modules linked in: CPU: 3 PID: 6828 Comm: a.out Not tainted 4.7.0-rc4+ #4 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 ffffffff880b58e0 ffff88005dd9fcb0 ffffffff82cc838f ffffffff87158b40 fffffbfff1016b1c 0000000000000000 0000000000000000 ffffffff87158b40 ffffffff83283dae 0000000000000009 ffff88005dd9fcf8 ffffffff8136d27f Call Trace: [< inline >] __dump_stack lib/dump_stack.c:15 [<ffffffff82cc838f>] dump_stack+0x12e/0x18f lib/dump_stack.c:51 [<ffffffff8136d27f>] __warn+0x19f/0x1e0 kernel/panic.c:516 [<ffffffff8136d48c>] warn_slowpath_null+0x2c/0x40 kernel/panic.c:551 [<ffffffff83283dae>] credit_entropy_bits+0x21e/0xad0 drivers/char/random.c:670 [< inline >] credit_entropy_bits_safe drivers/char/random.c:734 [<ffffffff8328785d>] random_ioctl+0x21d/0x250 drivers/char/random.c:1546 [< inline >] vfs_ioctl fs/ioctl.c:43 [<ffffffff8185316c>] do_vfs_ioctl+0x18c/0xff0 fs/ioctl.c:674 [< inline >] SYSC_ioctl fs/ioctl.c:689 [<ffffffff8185405f>] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:680 [<ffffffff86a995c0>] entry_SYSCALL_64_fastpath+0x23/0xc1 arch/x86/entry/entry_64.S:207 ---[ end trace 5d4902b2ba842f1f ]--- This was triggered using the test program: // autogenerated by syzkaller (http://github.com/google/syzkaller) int main() { int fd = open("/dev/random", O_RDWR); int val = -5000; ioctl(fd, RNDADDTOENTCNT, &val); return 0; } It's harmless in that (a) only root can trigger it, and (b) after complaining the code never does let the entropy count go negative, but it's better to simply not allow this userspace from passing in a negative entropy value altogether. Google-Bug-Id: #29575089 Reported-By: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 783dee11cdc9..8d0af74f6569 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -738,15 +738,18 @@ retry:
738 } 738 }
739} 739}
740 740
741static void credit_entropy_bits_safe(struct entropy_store *r, int nbits) 741static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
742{ 742{
743 const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1)); 743 const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
744 744
745 if (nbits < 0)
746 return -EINVAL;
747
745 /* Cap the value to avoid overflows */ 748 /* Cap the value to avoid overflows */
746 nbits = min(nbits, nbits_max); 749 nbits = min(nbits, nbits_max);
747 nbits = max(nbits, -nbits_max);
748 750
749 credit_entropy_bits(r, nbits); 751 credit_entropy_bits(r, nbits);
752 return 0;
750} 753}
751 754
752/********************************************************************* 755/*********************************************************************
@@ -1823,8 +1826,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
1823 return -EPERM; 1826 return -EPERM;
1824 if (get_user(ent_count, p)) 1827 if (get_user(ent_count, p))
1825 return -EFAULT; 1828 return -EFAULT;
1826 credit_entropy_bits_safe(&input_pool, ent_count); 1829 return credit_entropy_bits_safe(&input_pool, ent_count);
1827 return 0;
1828 case RNDADDENTROPY: 1830 case RNDADDENTROPY:
1829 if (!capable(CAP_SYS_ADMIN)) 1831 if (!capable(CAP_SYS_ADMIN))
1830 return -EPERM; 1832 return -EPERM;
@@ -1838,8 +1840,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
1838 size); 1840 size);
1839 if (retval < 0) 1841 if (retval < 0)
1840 return retval; 1842 return retval;
1841 credit_entropy_bits_safe(&input_pool, ent_count); 1843 return credit_entropy_bits_safe(&input_pool, ent_count);
1842 return 0;
1843 case RNDZAPENTCNT: 1844 case RNDZAPENTCNT:
1844 case RNDCLEARPOOL: 1845 case RNDCLEARPOOL:
1845 /* 1846 /*