aboutsummaryrefslogtreecommitdiffstats
path: root/fs/select.c
diff options
context:
space:
mode:
authorMitchell Blank Jr <mitch@sfgoth.com>2006-04-11 01:54:08 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:41 -0400
commitb04eb6aa08ecc3e24df2f78ebc486011ebd74feb (patch)
tree8dbf6a2449f886f0db9c3082dabdf83d4c4f04f7 /fs/select.c
parenta9cdf410ca8f59b52bc7061a6751050010c7cc5b (diff)
[PATCH] select: don't overflow if (SELECT_STACK_ALLOC % sizeof(long) != 0)
If SELECT_STACK_ALLOC is not a multiple of sizeof(long) then stack_fds[] would be shorter than SELECT_STACK_ALLOC bytes and could overflow later in the function. Fixed by simply rearranging the test later to work on sizeof(stack_fds) Currently SELECT_STACK_ALLOC is 256 so this doesn't happen, but it's nasty to have things like this hidden in the code. What if later someone decides to change SELECT_STACK_ALLOC to 300? Signed-off-by: Mitchell Blank Jr <mitch@sfgoth.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/select.c')
-rw-r--r--fs/select.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/fs/select.c b/fs/select.c
index fce0fd1bb1d1..a8109baa5e46 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -311,7 +311,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
311{ 311{
312 fd_set_bits fds; 312 fd_set_bits fds;
313 void *bits; 313 void *bits;
314 int ret, size, max_fdset; 314 int ret, max_fdset;
315 unsigned int size;
315 struct fdtable *fdt; 316 struct fdtable *fdt;
316 /* Allocate small arguments on the stack to save memory and be faster */ 317 /* Allocate small arguments on the stack to save memory and be faster */
317 long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; 318 long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
@@ -333,14 +334,15 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
333 * since we used fdset we need to allocate memory in units of 334 * since we used fdset we need to allocate memory in units of
334 * long-words. 335 * long-words.
335 */ 336 */
336 ret = -ENOMEM;
337 size = FDS_BYTES(n); 337 size = FDS_BYTES(n);
338 if (6*size < SELECT_STACK_ALLOC) 338 bits = stack_fds;
339 bits = stack_fds; 339 if (size > sizeof(stack_fds) / 6) {
340 else 340 /* Not enough space in on-stack array; must use kmalloc */
341 ret = -ENOMEM;
341 bits = kmalloc(6 * size, GFP_KERNEL); 342 bits = kmalloc(6 * size, GFP_KERNEL);
342 if (!bits) 343 if (!bits)
343 goto out_nofds; 344 goto out_nofds;
345 }
344 fds.in = bits; 346 fds.in = bits;
345 fds.out = bits + size; 347 fds.out = bits + size;
346 fds.ex = bits + 2*size; 348 fds.ex = bits + 2*size;