From nobody@FreeBSD.org  Tue Nov  8 16:57:50 2011
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 955EC10656DA
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  8 Nov 2011 16:57:50 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 855238FC18
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  8 Nov 2011 16:57:50 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id pA8GvomJ046709
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 8 Nov 2011 16:57:50 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id pA8GvoNR046708;
	Tue, 8 Nov 2011 16:57:50 GMT
	(envelope-from nobody)
Message-Id: <201111081657.pA8GvoNR046708@red.freebsd.org>
Date: Tue, 8 Nov 2011 16:57:50 GMT
From: Yui NARUSE <naruse@airemix.jp>
To: freebsd-gnats-submit@FreeBSD.org
Subject: When select(2) closed writing pipe, it will sticks.
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         162379
>Category:       kern
>Synopsis:       [libc] When select(2) closed writing pipe, it will sticks.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kib
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 08 17:00:25 UTC 2011
>Closed-Date:    Sun Nov 27 19:46:22 UTC 2011
>Last-Modified:  Sun Nov 27 19:46:22 UTC 2011
>Originator:     Yui NARUSE
>Release:        FreeBSD 8.2
>Organization:
>Environment:
FreeBSD freebsd82-64 8.2-RELEASE-p3 FreeBSD 8.2-RELEASE-p3 #0: Tue Sep 27 18:45:57 UTC 2011     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
When select(2) closed writing pipe, it will sticks.

FreeBSD 9.0-RC1 also reproduces this.
>How-To-Repeat:
Run following program, it will sticks.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#define max(x,y) ((x > y) ? x : y)
int
main(void) {
    int pipes[2];
    int res = pipe(pipes);
    if (res != 0) abort();
    int r = pipes[0];
    int w = pipes[1];
    res = close(w);
    if (res != 0) abort();
    fd_set readfds; FD_ZERO(&readfds);
    fd_set writefds; FD_ZERO(&writefds);
    fd_set exceptfds; FD_ZERO(&exceptfds);
    FD_SET(w, &writefds);
    res = select(max(r,w)+1, &readfds, &writefds, &exceptfds, NULL);
    if (res) perror("select");
    return 0;
}
>Fix:


>Release-Note:
>Audit-Trail:

From: Gleb Smirnoff <glebius@FreeBSD.org>
To: Yui NARUSE <naruse@airemix.jp>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/162379: When select(2) closed writing pipe, it will sticks.
Date: Thu, 10 Nov 2011 16:27:37 +0400

 On Tue, Nov 08, 2011 at 04:57:50PM +0000, Yui NARUSE wrote:
 Y> >How-To-Repeat:
 Y> Run following program, it will sticks.
 Y> 
 Y> #include <stdio.h>
 Y> #include <stdlib.h>
 Y> #include <errno.h>
 Y> #include <sys/select.h>
 Y> #define max(x,y) ((x > y) ? x : y)
 Y> int
 Y> main(void) {
 Y>     int pipes[2];
 Y>     int res = pipe(pipes);
 Y>     if (res != 0) abort();
 Y>     int r = pipes[0];
 Y>     int w = pipes[1];
 Y>     res = close(w);
 Y>     if (res != 0) abort();
 Y>     fd_set readfds; FD_ZERO(&readfds);
 Y>     fd_set writefds; FD_ZERO(&writefds);
 Y>     fd_set exceptfds; FD_ZERO(&exceptfds);
 Y>     FD_SET(w, &writefds);
 Y>     res = select(max(r,w)+1, &readfds, &writefds, &exceptfds, NULL);
 Y>     if (res) perror("select");
 Y>     return 0;
 Y> }
 Y> >Fix:
 
 According to SUS, issuing close() on a descriptor means deallocating it,
 and the argument value for close() is not a valid descriptor anymore
 after close().
 
 http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
 
 So, you are passing an invalid descriptor to FD_SET(). Behavior in this
 case is undefined. Quoting SUS:
 
 "The behavior of these macros is undefined if the fd argument is less than 0 or greater than or equal to FD_SETSIZE, or if fd is not a valid file descriptor, or if any of the arguments are expressions with side-effects."
 
 also
 
 "The pselect() and select() functions shall support regular files, terminal and pseudo-terminal devices, STREAMS-based files, FIFOs, pipes, and sockets. The behavior of pselect() and select() on file descriptors that refer to other types of file is unspecified."
 
 More info here:
 
 http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html
 
 If you don't mind, I am going to close this problem report.
 
 -- 
 Totus tuus, Glebius.

From: Gleb Smirnoff <glebius@FreeBSD.org>
To: Yui NARUSE <naruse@airemix.jp>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/162379: When select(2) closed writing pipe, it will sticks.
Date: Thu, 10 Nov 2011 17:04:16 +0400

   Yui,
 
   I have been pointed to the fact that select(2) should return EBADF in
 this case. This is clearly seen in standard document,
 
  http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html
 
 so problem acknowledged.
 
 Also, it appeared that your report is dup of kern/155606.
 
 -- 
 Totus tuus, Glebius.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/162379: commit references a PR
Date: Sun, 13 Nov 2011 10:28:15 +0000 (UTC)

 Author: kib
 Date: Sun Nov 13 10:28:01 2011
 New Revision: 227485
 URL: http://svn.freebsd.org/changeset/base/227485
 
 Log:
   To limit amount of the kernel memory allocated, and to optimize the
   iteration over the fdsets, kern_select() limits the length of the
   fdsets copied in by the last valid file descriptor index. If any bit
   is set in a mask above the limit, current implementation ignores the
   filedescriptor, instead of returning EBADF.
   
   Fix the issue by scanning the tails of fdset before entering the
   select loop and returning EBADF if any bit above last valid
   filedescriptor index is set. The performance impact of the additional
   check is only imposed on the (somewhat) buggy applications that pass
   bad file descriptors to select(2) or pselect(2).
   
   PR:	kern/155606, kern/162379
   Discussed with:	cognet, glebius
   Tested by:	andreast (powerpc, all 64/32bit ABI combinations, big-endian),
          marius (sparc64, big-endian)
   MFC after:    2 weeks
 
 Modified:
   head/sys/kern/sys_generic.c
 
 Modified: head/sys/kern/sys_generic.c
 ==============================================================================
 --- head/sys/kern/sys_generic.c	Sun Nov 13 06:39:49 2011	(r227484)
 +++ head/sys/kern/sys_generic.c	Sun Nov 13 10:28:01 2011	(r227485)
 @@ -831,6 +831,54 @@ sys_select(struct thread *td, struct sel
  	    NFDBITS));
  }
  
 +/*
 + * In the unlikely case when user specified n greater then the last
 + * open file descriptor, check that no bits are set after the last
 + * valid fd.  We must return EBADF if any is set.
 + *
 + * There are applications that rely on the behaviour.
 + *
 + * nd is fd_lastfile + 1.
 + */
 +static int
 +select_check_badfd(fd_set *fd_in, int nd, int ndu, int abi_nfdbits)
 +{
 +	char *addr, *oaddr;
 +	int b, i, res;
 +	uint8_t bits;
 +
 +	if (nd >= ndu || fd_in == NULL)
 +		return (0);
 +
 +	oaddr = NULL;
 +	bits = 0; /* silence gcc */
 +	for (i = nd; i < ndu; i++) {
 +		b = i / NBBY;
 +#if BYTE_ORDER == LITTLE_ENDIAN
 +		addr = (char *)fd_in + b;
 +#else
 +		addr = (char *)fd_in;
 +		if (abi_nfdbits == NFDBITS) {
 +			addr += rounddown(b, sizeof(fd_mask)) +
 +			    sizeof(fd_mask) - 1 - b % sizeof(fd_mask);
 +		} else {
 +			addr += rounddown(b, sizeof(uint32_t)) +
 +			    sizeof(uint32_t) - 1 - b % sizeof(uint32_t);
 +		}
 +#endif
 +		if (addr != oaddr) {
 +			res = fubyte(addr);
 +			if (res == -1)
 +				return (EFAULT);
 +			oaddr = addr;
 +			bits = res;
 +		}
 +		if ((bits & (1 << (i % NBBY))) != 0)
 +			return (EBADF);
 +	}
 +	return (0);
 +}
 +
  int
  kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
      fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
 @@ -845,14 +893,26 @@ kern_select(struct thread *td, int nd, f
  	fd_mask s_selbits[howmany(2048, NFDBITS)];
  	fd_mask *ibits[3], *obits[3], *selbits, *sbp;
  	struct timeval atv, rtv, ttv;
 -	int error, timo;
 +	int error, lf, ndu, timo;
  	u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
  
  	if (nd < 0)
  		return (EINVAL);
  	fdp = td->td_proc->p_fd;
 -	if (nd > fdp->fd_lastfile + 1)
 -		nd = fdp->fd_lastfile + 1;
 +	ndu = nd;
 +	lf = fdp->fd_lastfile;
 +	if (nd > lf + 1)
 +		nd = lf + 1;
 +
 +	error = select_check_badfd(fd_in, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ou, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ex, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
  
  	/*
  	 * Allocate just enough bits for the non-null fd_sets.  Use the
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: kib 
State-Changed-When: Sun Nov 27 18:46:11 UTC 2011 
State-Changed-Why:  
Take. 


Responsible-Changed-From-To: freebsd-bugs->kib 
Responsible-Changed-By: kib 
Responsible-Changed-When: Sun Nov 27 18:46:11 UTC 2011 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=162379 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/162379: commit references a PR
Date: Sun, 27 Nov 2011 18:49:40 +0000 (UTC)

 Author: kib
 Date: Sun Nov 27 18:49:16 2011
 New Revision: 228032
 URL: http://svn.freebsd.org/changeset/base/228032
 
 Log:
   MFC r227485:
   To limit amount of the kernel memory allocated, and to optimize the
   iteration over the fdsets, kern_select() limits the length of the
   fdsets copied in by the last valid file descriptor index. If any bit
   is set in a mask above the limit, current implementation ignores the
   filedescriptor, instead of returning EBADF.
   
   Fix the issue by scanning the tails of fdset before entering the
   select loop and returning EBADF if any bit above last valid
   filedescriptor index is set. The performance impact of the additional
   check is only imposed on the (somewhat) buggy applications that pass
   bad file descriptors to select(2) or pselect(2).
   
   PR:	kern/155606, kern/162379
   Approved by:	re (bz)
 
 Modified:
   stable/9/sys/kern/sys_generic.c
 Directory Properties:
   stable/9/sys/   (props changed)
 
 Modified: stable/9/sys/kern/sys_generic.c
 ==============================================================================
 --- stable/9/sys/kern/sys_generic.c	Sun Nov 27 17:51:13 2011	(r228031)
 +++ stable/9/sys/kern/sys_generic.c	Sun Nov 27 18:49:16 2011	(r228032)
 @@ -831,6 +831,54 @@ sys_select(struct thread *td, struct sel
  	    NFDBITS));
  }
  
 +/*
 + * In the unlikely case when user specified n greater then the last
 + * open file descriptor, check that no bits are set after the last
 + * valid fd.  We must return EBADF if any is set.
 + *
 + * There are applications that rely on the behaviour.
 + *
 + * nd is fd_lastfile + 1.
 + */
 +static int
 +select_check_badfd(fd_set *fd_in, int nd, int ndu, int abi_nfdbits)
 +{
 +	char *addr, *oaddr;
 +	int b, i, res;
 +	uint8_t bits;
 +
 +	if (nd >= ndu || fd_in == NULL)
 +		return (0);
 +
 +	oaddr = NULL;
 +	bits = 0; /* silence gcc */
 +	for (i = nd; i < ndu; i++) {
 +		b = i / NBBY;
 +#if BYTE_ORDER == LITTLE_ENDIAN
 +		addr = (char *)fd_in + b;
 +#else
 +		addr = (char *)fd_in;
 +		if (abi_nfdbits == NFDBITS) {
 +			addr += rounddown(b, sizeof(fd_mask)) +
 +			    sizeof(fd_mask) - 1 - b % sizeof(fd_mask);
 +		} else {
 +			addr += rounddown(b, sizeof(uint32_t)) +
 +			    sizeof(uint32_t) - 1 - b % sizeof(uint32_t);
 +		}
 +#endif
 +		if (addr != oaddr) {
 +			res = fubyte(addr);
 +			if (res == -1)
 +				return (EFAULT);
 +			oaddr = addr;
 +			bits = res;
 +		}
 +		if ((bits & (1 << (i % NBBY))) != 0)
 +			return (EBADF);
 +	}
 +	return (0);
 +}
 +
  int
  kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
      fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
 @@ -845,14 +893,26 @@ kern_select(struct thread *td, int nd, f
  	fd_mask s_selbits[howmany(2048, NFDBITS)];
  	fd_mask *ibits[3], *obits[3], *selbits, *sbp;
  	struct timeval atv, rtv, ttv;
 -	int error, timo;
 +	int error, lf, ndu, timo;
  	u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
  
  	if (nd < 0)
  		return (EINVAL);
  	fdp = td->td_proc->p_fd;
 -	if (nd > fdp->fd_lastfile + 1)
 -		nd = fdp->fd_lastfile + 1;
 +	ndu = nd;
 +	lf = fdp->fd_lastfile;
 +	if (nd > lf + 1)
 +		nd = lf + 1;
 +
 +	error = select_check_badfd(fd_in, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ou, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ex, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
  
  	/*
  	 * Allocate just enough bits for the non-null fd_sets.  Use the
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/162379: commit references a PR
Date: Sun, 27 Nov 2011 19:01:08 +0000 (UTC)

 Author: kib
 Date: Sun Nov 27 19:00:52 2011
 New Revision: 228034
 URL: http://svn.freebsd.org/changeset/base/228034
 
 Log:
   MFC r227485:
   To limit amount of the kernel memory allocated, and to optimize the
   iteration over the fdsets, kern_select() limits the length of the
   fdsets copied in by the last valid file descriptor index. If any bit
   is set in a mask above the limit, current implementation ignores the
   filedescriptor, instead of returning EBADF.
   
   Fix the issue by scanning the tails of fdset before entering the
   select loop and returning EBADF if any bit above last valid
   filedescriptor index is set. The performance impact of the additional
   check is only imposed on the (somewhat) buggy applications that pass
   bad file descriptors to select(2) or pselect(2).
   
   PR:	kern/155606, kern/162379
   Approved by:	re (bz)
 
 Modified:
   releng/9.0/sys/kern/sys_generic.c
 Directory Properties:
   releng/9.0/sys/   (props changed)
 
 Modified: releng/9.0/sys/kern/sys_generic.c
 ==============================================================================
 --- releng/9.0/sys/kern/sys_generic.c	Sun Nov 27 18:56:04 2011	(r228033)
 +++ releng/9.0/sys/kern/sys_generic.c	Sun Nov 27 19:00:52 2011	(r228034)
 @@ -831,6 +831,54 @@ sys_select(struct thread *td, struct sel
  	    NFDBITS));
  }
  
 +/*
 + * In the unlikely case when user specified n greater then the last
 + * open file descriptor, check that no bits are set after the last
 + * valid fd.  We must return EBADF if any is set.
 + *
 + * There are applications that rely on the behaviour.
 + *
 + * nd is fd_lastfile + 1.
 + */
 +static int
 +select_check_badfd(fd_set *fd_in, int nd, int ndu, int abi_nfdbits)
 +{
 +	char *addr, *oaddr;
 +	int b, i, res;
 +	uint8_t bits;
 +
 +	if (nd >= ndu || fd_in == NULL)
 +		return (0);
 +
 +	oaddr = NULL;
 +	bits = 0; /* silence gcc */
 +	for (i = nd; i < ndu; i++) {
 +		b = i / NBBY;
 +#if BYTE_ORDER == LITTLE_ENDIAN
 +		addr = (char *)fd_in + b;
 +#else
 +		addr = (char *)fd_in;
 +		if (abi_nfdbits == NFDBITS) {
 +			addr += rounddown(b, sizeof(fd_mask)) +
 +			    sizeof(fd_mask) - 1 - b % sizeof(fd_mask);
 +		} else {
 +			addr += rounddown(b, sizeof(uint32_t)) +
 +			    sizeof(uint32_t) - 1 - b % sizeof(uint32_t);
 +		}
 +#endif
 +		if (addr != oaddr) {
 +			res = fubyte(addr);
 +			if (res == -1)
 +				return (EFAULT);
 +			oaddr = addr;
 +			bits = res;
 +		}
 +		if ((bits & (1 << (i % NBBY))) != 0)
 +			return (EBADF);
 +	}
 +	return (0);
 +}
 +
  int
  kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
      fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
 @@ -845,14 +893,26 @@ kern_select(struct thread *td, int nd, f
  	fd_mask s_selbits[howmany(2048, NFDBITS)];
  	fd_mask *ibits[3], *obits[3], *selbits, *sbp;
  	struct timeval atv, rtv, ttv;
 -	int error, timo;
 +	int error, lf, ndu, timo;
  	u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
  
  	if (nd < 0)
  		return (EINVAL);
  	fdp = td->td_proc->p_fd;
 -	if (nd > fdp->fd_lastfile + 1)
 -		nd = fdp->fd_lastfile + 1;
 +	ndu = nd;
 +	lf = fdp->fd_lastfile;
 +	if (nd > lf + 1)
 +		nd = lf + 1;
 +
 +	error = select_check_badfd(fd_in, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ou, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ex, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
  
  	/*
  	 * Allocate just enough bits for the non-null fd_sets.  Use the
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/162379: commit references a PR
Date: Sun, 27 Nov 2011 19:36:48 +0000 (UTC)

 Author: kib
 Date: Sun Nov 27 19:36:36 2011
 New Revision: 228038
 URL: http://svn.freebsd.org/changeset/base/228038
 
 Log:
   MFC r227485:
   To limit amount of the kernel memory allocated, and to optimize the
   iteration over the fdsets, kern_select() limits the length of the
   fdsets copied in by the last valid file descriptor index. If any bit
   is set in a mask above the limit, current implementation ignores the
   filedescriptor, instead of returning EBADF.
   
   Fix the issue by scanning the tails of fdset before entering the
   select loop and returning EBADF if any bit above last valid
   filedescriptor index is set. The performance impact of the additional
   check is only imposed on the (somewhat) buggy applications that pass
   bad file descriptors to select(2) or pselect(2).
   
   PR:	kern/155606, kern/162379
 
 Modified:
   stable/8/sys/kern/sys_generic.c
 Directory Properties:
   stable/8/sys/   (props changed)
 
 Modified: stable/8/sys/kern/sys_generic.c
 ==============================================================================
 --- stable/8/sys/kern/sys_generic.c	Sun Nov 27 19:13:45 2011	(r228037)
 +++ stable/8/sys/kern/sys_generic.c	Sun Nov 27 19:36:36 2011	(r228038)
 @@ -829,6 +829,54 @@ select(struct thread *td, struct select_
  	    NFDBITS));
  }
  
 +/*
 + * In the unlikely case when user specified n greater then the last
 + * open file descriptor, check that no bits are set after the last
 + * valid fd.  We must return EBADF if any is set.
 + *
 + * There are applications that rely on the behaviour.
 + *
 + * nd is fd_lastfile + 1.
 + */
 +static int
 +select_check_badfd(fd_set *fd_in, int nd, int ndu, int abi_nfdbits)
 +{
 +	char *addr, *oaddr;
 +	int b, i, res;
 +	uint8_t bits;
 +
 +	if (nd >= ndu || fd_in == NULL)
 +		return (0);
 +
 +	oaddr = NULL;
 +	bits = 0; /* silence gcc */
 +	for (i = nd; i < ndu; i++) {
 +		b = i / NBBY;
 +#if BYTE_ORDER == LITTLE_ENDIAN
 +		addr = (char *)fd_in + b;
 +#else
 +		addr = (char *)fd_in;
 +		if (abi_nfdbits == NFDBITS) {
 +			addr += rounddown(b, sizeof(fd_mask)) +
 +			    sizeof(fd_mask) - 1 - b % sizeof(fd_mask);
 +		} else {
 +			addr += rounddown(b, sizeof(uint32_t)) +
 +			    sizeof(uint32_t) - 1 - b % sizeof(uint32_t);
 +		}
 +#endif
 +		if (addr != oaddr) {
 +			res = fubyte(addr);
 +			if (res == -1)
 +				return (EFAULT);
 +			oaddr = addr;
 +			bits = res;
 +		}
 +		if ((bits & (1 << (i % NBBY))) != 0)
 +			return (EBADF);
 +	}
 +	return (0);
 +}
 +
  int
  kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
      fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
 @@ -843,14 +891,26 @@ kern_select(struct thread *td, int nd, f
  	fd_mask s_selbits[howmany(2048, NFDBITS)];
  	fd_mask *ibits[3], *obits[3], *selbits, *sbp;
  	struct timeval atv, rtv, ttv;
 -	int error, timo;
 +	int error, lf, ndu, timo;
  	u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
  
  	if (nd < 0)
  		return (EINVAL);
  	fdp = td->td_proc->p_fd;
 -	if (nd > fdp->fd_lastfile + 1)
 -		nd = fdp->fd_lastfile + 1;
 +	ndu = nd;
 +	lf = fdp->fd_lastfile;
 +	if (nd > lf + 1)
 +		nd = lf + 1;
 +
 +	error = select_check_badfd(fd_in, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ou, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
 +	error = select_check_badfd(fd_ex, nd, ndu, abi_nfdbits);
 +	if (error != 0)
 +		return (error);
  
  	/*
  	 * Allocate just enough bits for the non-null fd_sets.  Use the
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: kib 
State-Changed-When: Sun Nov 27 19:46:03 UTC 2011 
State-Changed-Why:  
Merged to HEAD, 9 and 8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=162379 
>Unformatted:
