From b04eb6aa08ecc3e24df2f78ebc486011ebd74feb Mon Sep 17 00:00:00 2001 From: Mitchell Blank Jr Date: Mon, 10 Apr 2006 22:54:08 -0700 Subject: [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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/select.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'fs/select.c') 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, { fd_set_bits fds; void *bits; - int ret, size, max_fdset; + int ret, max_fdset; + unsigned int size; struct fdtable *fdt; /* Allocate small arguments on the stack to save memory and be faster */ 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, * since we used fdset we need to allocate memory in units of * long-words. */ - ret = -ENOMEM; size = FDS_BYTES(n); - if (6*size < SELECT_STACK_ALLOC) - bits = stack_fds; - else + bits = stack_fds; + if (size > sizeof(stack_fds) / 6) { + /* Not enough space in on-stack array; must use kmalloc */ + ret = -ENOMEM; bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; + if (!bits) + goto out_nofds; + } fds.in = bits; fds.out = bits + size; fds.ex = bits + 2*size; -- cgit v1.2.3