|
@@ -29,6 +29,7 @@
|
|
#include <linux/sched/rt.h>
|
|
#include <linux/sched/rt.h>
|
|
#include <linux/freezer.h>
|
|
#include <linux/freezer.h>
|
|
#include <net/busy_poll.h>
|
|
#include <net/busy_poll.h>
|
|
|
|
+#include <linux/vmalloc.h>
|
|
|
|
|
|
#include <asm/uaccess.h>
|
|
#include <asm/uaccess.h>
|
|
|
|
|
|
@@ -554,7 +555,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
|
|
fd_set_bits fds;
|
|
fd_set_bits fds;
|
|
void *bits;
|
|
void *bits;
|
|
int ret, max_fds;
|
|
int ret, max_fds;
|
|
- unsigned int size;
|
|
|
|
|
|
+ size_t size, alloc_size;
|
|
struct fdtable *fdt;
|
|
struct fdtable *fdt;
|
|
/* Allocate small arguments on the stack to save memory and be faster */
|
|
/* Allocate small arguments on the stack to save memory and be faster */
|
|
long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
|
|
long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
|
|
@@ -581,7 +582,14 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
|
|
if (size > sizeof(stack_fds) / 6) {
|
|
if (size > sizeof(stack_fds) / 6) {
|
|
/* Not enough space in on-stack array; must use kmalloc */
|
|
/* Not enough space in on-stack array; must use kmalloc */
|
|
ret = -ENOMEM;
|
|
ret = -ENOMEM;
|
|
- bits = kmalloc(6 * size, GFP_KERNEL);
|
|
|
|
|
|
+ if (size > (SIZE_MAX / 6))
|
|
|
|
+ goto out_nofds;
|
|
|
|
+
|
|
|
|
+ alloc_size = 6 * size;
|
|
|
|
+ bits = kmalloc(alloc_size, GFP_KERNEL|__GFP_NOWARN);
|
|
|
|
+ if (!bits && alloc_size > PAGE_SIZE)
|
|
|
|
+ bits = vmalloc(alloc_size);
|
|
|
|
+
|
|
if (!bits)
|
|
if (!bits)
|
|
goto out_nofds;
|
|
goto out_nofds;
|
|
}
|
|
}
|
|
@@ -618,7 +626,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
|
|
|
|
|
|
out:
|
|
out:
|
|
if (bits != stack_fds)
|
|
if (bits != stack_fds)
|
|
- kfree(bits);
|
|
|
|
|
|
+ kvfree(bits);
|
|
out_nofds:
|
|
out_nofds:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|