]> git.baikalelectronics.ru Git - kernel.git/commit
fs/select: Fix memory corruption in compat_get_fd_set()
authorHelge Deller <deller@gmx.de>
Wed, 23 Aug 2017 20:37:00 +0000 (22:37 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 28 Aug 2017 23:09:19 +0000 (16:09 -0700)
commit79de3cbe9a974e03a02b71da80da9ee0eb15a2d0
treea6ce183a8943e54682493b3217a6f8da43aca0fd
parent702e97621ec7e7a36034ebd7a446af04f59d6dee
fs/select: Fix memory corruption in compat_get_fd_set()

Commit 464d62421cb8 ("select: switch compat_{get,put}_fd_set() to
compat_{get,put}_bitmap()") changed the calculation on how many bytes
need to be zeroed when userspace handed over a NULL pointer for a fdset
array in the select syscall.

The calculation was changed in compat_get_fd_set() wrongly from
memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
to
memset(fdset, 0, ALIGN(nr, BITS_PER_LONG));

The ALIGN(nr, BITS_PER_LONG) calculates the number of _bits_ which need
to be zeroed in the target fdset array (rounded up to the next full bits
for an unsigned long).

But the memset() call expects the number of _bytes_ to be zeroed.

This leads to clearing more memory than wanted (on the stack area or
even at kmalloc()ed memory areas) and to random kernel crashes as we
have seen them on the parisc platform.

The correct change should have been

memset(fdset, 0, (ALIGN(nr, BITS_PER_LONG) / BITS_PER_LONG) * BYTES_PER_LONG);

which is the same as can be archieved with a call to

zero_fd_set(nr, fdset).

Fixes: 464d62421cb8 ("select: switch compat_{get,put}_fd_set() to compat_{get,put}_bitmap()"
Acked-by:: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/select.c