Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Nov 2002 12:09:02 +0100
From:      Olivier Houchard <cognet@ci0.org>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        freebsd-audit@FreeBSD.ORG
Subject:   Re: do_dup patch
Message-ID:  <20021125110902.GA10961@ci0.org>
In-Reply-To: <20021125210116.I56453-100000@gamplex.bde.org>
References:  <20021125093228.GA10213@ci0.org> <20021125210116.I56453-100000@gamplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Nov 25, 2002 at 09:32:05PM +1100, Bruce Evans wrote:
> On Mon, 25 Nov 2002, Olivier Houchard wrote:
> 
> > This patch makes the "new" and "old" do_dup arguments unsigned int instead of
> > int. I can't see any reason they would have to be int, and right now a call to
> > dup or dup2 with an invalid negative fd, such as dup(-999999); will panic a
> > -CURRENT box (the problem doesn't exist on -STABLE because the file descriptor
> > validity is checked in dup() and dup2()).
> > Is there anything wrong with committing this ?
> 
> Yes; it is sort of backwards.
> 
> File descriptors are small positive (signed) ints, and the dup() and dup2()
> syscalls take file descriptors as parameters.  However, dup() and dup2()
> are misdeclared as taking u_int's as their parameters.  This used to be
> obfuscate/optimize away an explicit comparison with 0 in the bounds check
> for the parameters.  E.g., in RELENG_4:
> 
> % #ifndef _SYS_SYSPROTO_H_
> % struct dup2_args {
> % 	u_int	from;
> % 	u_int	to;
>   	^^^^^
> Bogus type for bogus optimization.  This is pseudo-code; see
> <sys/sysproto.h> for the actual declaration.  This misdeclaration
> needs something like normal 2's complement machines to work since
> we never actually convert the parameters from ints to u_ints;
> we just pass ints and pretend that they are u_ints.
> 
> % };
> % #endif
> % /* ARGSUSED */
> % int
> % dup2(p, uap)
> % 	struct proc *p;
> % 	struct dup2_args *uap;
> % {
> % 	register struct filedesc *fdp = p->p_fd;
> % 	register u_int old = uap->from, new = uap->to;
> % 	int i, error;
> %
> % retry:
> % 	if (old >= fdp->fd_nfiles ||
>   	    ^^^^^^^^^^^^^^^^^^^^^
> 
> Bogus optimization.  The upper and lower bounds are checked in a
> single comparison.  The only reason to do this seems to be to
> hand-optimize for 20+-year old compilers on pdp11-like machines
> where the 2 comparisons can be collapes into a single machine
> instruction and the compiler doesn't do this automatically.
> 
> % 	    fdp->fd_ofiles[old] == NULL ||
> % 	    new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
> % 	    new >= maxfilesperproc) {
> % 		return (EBADF);
> % 	}
> 
> In -current, this has rotted to:
> 
> % int
> % dup2(td, uap)
> % 	struct thread *td;
> % 	struct dup2_args *uap;
> % {
> %
> % 	return (do_dup(td, DUP_FIXED, (int)uap->from, (int)uap->to,
>   	                              ^^^^^           ^^^^^
> 
> Bogus casts to break warnings about our type errors.
> 
> % 		    td->td_retval));
> 
> % }
> % ...
> % static int
> % do_dup(td, type, old, new, retval)
> % 	enum dup_type type;
> % 	int old, new;
> % 	register_t *retval;
> % 	struct thread *td;
> % {
> % 	register struct filedesc *fdp;
> % 	struct proc *p;
> % 	struct file *fp;
> % 	struct file *delfp;
> % 	int error, newfd;
> %
> % 	p = td->td_proc;
> % 	fdp = p->p_fd;
> %
> % 	/*
> % 	 * Verify we have a valid descriptor to dup from and possibly to
> % 	 * dup to.
> % 	 */
> % 	FILEDESC_LOCK(fdp);
> % 	if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL ||
>   	    ^^^^^^^^^^^^^^^^^^^^^
> 
> Bug.  The bogus optimization has been broken by changing the types.
> 
> % 	    new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
> % 	    new >= maxfilesperproc) {
> % 		FILEDESC_UNLOCK(fdp);
> % 		return (EBADF);
> % 	}
> 
> Bruce

Right.
So what would be the best ?
Changing dup and dup2 prototypes in syscall.master to make new and old
signed instead of unsigned and checking that new >= 0 && old >= 0 in
do_dup ?

Thanks,

Olivier

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021125110902.GA10961>