diff options
Diffstat (limited to 'fs/select.c')
| -rw-r--r-- | fs/select.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/select.c b/fs/select.c index 2e56325c73c4..f10a10317d54 100644 --- a/fs/select.c +++ b/fs/select.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/personality.h> /* for STICKY_TIMEOUTS */ | 22 | #include <linux/personality.h> /* for STICKY_TIMEOUTS */ |
| 23 | #include <linux/file.h> | 23 | #include <linux/file.h> |
| 24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| 25 | #include <linux/rcupdate.h> | ||
| 25 | 26 | ||
| 26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 27 | 28 | ||
| @@ -185,9 +186,9 @@ int do_select(int n, fd_set_bits *fds, long *timeout) | |||
| 185 | int retval, i; | 186 | int retval, i; |
| 186 | long __timeout = *timeout; | 187 | long __timeout = *timeout; |
| 187 | 188 | ||
| 188 | spin_lock(¤t->files->file_lock); | 189 | rcu_read_lock(); |
| 189 | retval = max_select_fd(n, fds); | 190 | retval = max_select_fd(n, fds); |
| 190 | spin_unlock(¤t->files->file_lock); | 191 | rcu_read_unlock(); |
| 191 | 192 | ||
| 192 | if (retval < 0) | 193 | if (retval < 0) |
| 193 | return retval; | 194 | return retval; |
| @@ -329,8 +330,10 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s | |||
| 329 | goto out_nofds; | 330 | goto out_nofds; |
| 330 | 331 | ||
| 331 | /* max_fdset can increase, so grab it once to avoid race */ | 332 | /* max_fdset can increase, so grab it once to avoid race */ |
| 333 | rcu_read_lock(); | ||
| 332 | fdt = files_fdtable(current->files); | 334 | fdt = files_fdtable(current->files); |
| 333 | max_fdset = fdt->max_fdset; | 335 | max_fdset = fdt->max_fdset; |
| 336 | rcu_read_unlock(); | ||
| 334 | if (n > max_fdset) | 337 | if (n > max_fdset) |
| 335 | n = max_fdset; | 338 | n = max_fdset; |
| 336 | 339 | ||
| @@ -469,10 +472,14 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti | |||
| 469 | struct poll_list *head; | 472 | struct poll_list *head; |
| 470 | struct poll_list *walk; | 473 | struct poll_list *walk; |
| 471 | struct fdtable *fdt; | 474 | struct fdtable *fdt; |
| 475 | int max_fdset; | ||
| 472 | 476 | ||
| 473 | /* Do a sanity check on nfds ... */ | 477 | /* Do a sanity check on nfds ... */ |
| 478 | rcu_read_lock(); | ||
| 474 | fdt = files_fdtable(current->files); | 479 | fdt = files_fdtable(current->files); |
| 475 | if (nfds > fdt->max_fdset && nfds > OPEN_MAX) | 480 | max_fdset = fdt->max_fdset; |
| 481 | rcu_read_unlock(); | ||
| 482 | if (nfds > max_fdset && nfds > OPEN_MAX) | ||
| 476 | return -EINVAL; | 483 | return -EINVAL; |
| 477 | 484 | ||
| 478 | if (timeout) { | 485 | if (timeout) { |
