Subject: Re: sys_select() EBADF bug
To: Greywolf <greywolf@starwolf.com>
From: Tad Hunt <tad@entrisphere.com>
List: tech-kern
Date: 11/14/2002 15:38:57
Hmm.  I didn't realize that you could shrink the resource limits
below something that was already open and still have the files open.
This should fix that problem then:

by making nd unsigned, we can make this cost about the same as
before by removing the "if(SCARG(uap, nd) < 0)" check.

	sys_select()
	{
		...
		u_int nd;
		...

		nd = SCARG(uap, nd);

		/*
		 * it is possible to shrink the resource limits below the current
		 * number of open files.  Make sure that we handle that case.
		 */
		if (nd > p->p_fd->fd_nfiles && nd > p->p_rlimit[RLIMIT_NOFILE].rlim_cur)
			return (EINVAL);
		...
	}

In message <Pine.NEB.4.44.0211141522390.625-100000@lothlorien.starwolf.com>, you said:
;On Thu, 14 Nov 2002, Tad Hunt wrote:
;
;# Currently, select will happily block forever if a bad fd is in the
;# list and greater than fd_nfiles.  selscan() was already rewritten
;# to use fd_getfile(), which correctly handles a fd beyond the end
;# of the array.
;#
;# This way, if the process puts a fd > the number of open files in,
;# it will still get an EBADF error back from select(2).
;
;So what do you do in the case the proc.curproc.rlimit.nofiles.* gets
;pushed below the selected fd?  It's still a valid descriptor.
;
;Now, granted, it's a contrived edge case, but...what if?  Theoretically,
;we might want to keep stdin, stdout, stderr opened, and maybe open a
;socket or two, but decrease nofiles to 0 to prevent a given process from
;(re)opening another file (call it paranoia).  What then on select()?
;
;				--*greywolf;
;--
;NetBSD: No Worries!