diff options
author | peter <peter@FreeBSD.org> | 2001-02-07 23:28:01 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2001-02-07 23:28:01 +0000 |
commit | c1207542eefdfb96c8a733127ca5fae827a5263e (patch) | |
tree | a6b96e709e4f8d480b111ea264d9e8119675b6a1 /sys | |
parent | 6ab203b6cab304a5b453d5363ebd316e0c2ead06 (diff) | |
download | FreeBSD-src-c1207542eefdfb96c8a733127ca5fae827a5263e.zip FreeBSD-src-c1207542eefdfb96c8a733127ca5fae827a5263e.tar.gz |
The code I picked up from NetBSD in '97 had a nasty bug. It limited
the index of the pollfd array to the number of fd's currently open, not
the maximum number of fd's. ie: if you had 0,1,2 open, you could not
use pollfd slots higher than 20. The specs say we only have to support
OPEN_MAX [64] entries but we allow way more than that.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/sys_generic.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index b6c2bfc..4b2c5d8 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -55,6 +55,7 @@ #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/poll.h> +#include <sys/resourcevar.h> #include <sys/selinfo.h> #include <sys/sysctl.h> #include <sys/sysent.h> @@ -857,14 +858,21 @@ poll(p, uap) caddr_t bits; char smallbits[32 * sizeof(struct pollfd)]; struct timeval atv, rtv, ttv; - int s, ncoll, error = 0, timo; + int s, ncoll, error = 0, timo, lim, nfds; size_t ni; - if (SCARG(uap, nfds) > p->p_fd->fd_nfiles) { - /* forgiving; slightly wrong */ - SCARG(uap, nfds) = p->p_fd->fd_nfiles; - } - ni = SCARG(uap, nfds) * sizeof(struct pollfd); + nfds = SCARG(uap, nfds); + /* + * This is kinda bogus. We have fd limits, but that doesn't + * map too well to the size of the pfd[] array. Make sure + * we let the process use at least FD_SETSIZE entries. + * The specs say we only have to support OPEN_MAX entries (64). + */ + lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); + lim = min(lim, FD_SETSIZE); + if (nfds > lim) + return (EINVAL); + ni = nfds * sizeof(struct pollfd); if (ni > sizeof(smallbits)) bits = malloc(ni, M_TEMP, M_WAITOK); else @@ -891,7 +899,7 @@ retry: ncoll = nselcoll; p->p_flag |= P_SELECT; PROC_UNLOCK(p); - error = pollscan(p, (struct pollfd *)bits, SCARG(uap, nfds)); + error = pollscan(p, (struct pollfd *)bits, nfds); PROC_LOCK(p); if (error || p->p_retval[0]) goto done; |