Index: sys/sys/filedesc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/filedesc.h,v retrieving revision 1.19.2.3 diff -u -r1.19.2.3 filedesc.h --- sys/sys/filedesc.h 2000/11/26 02:30:08 1.19.2.3 +++ sys/sys/filedesc.h 2002/04/19 14:25:39 @@ -142,6 +142,7 @@ void fdfree __P((struct proc *p)); int closef __P((struct file *fp,struct proc *p)); void fdcloseexec __P((struct proc *p)); +int fdcheckstd __P((struct proc *p)); struct file *holdfp __P((struct filedesc* fdp, int fd, int flag)); int getvnode __P((struct filedesc *fdp, int fd, struct file **fpp)); int fdissequential __P((struct file *)); Index: sys/kern/kern_exec.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v retrieving revision 1.107.2.13 diff -u -r1.107.2.13 kern_exec.c --- sys/kern/kern_exec.c 2002/01/22 17:22:59 1.107.2.13 +++ sys/kern/kern_exec.c 2002/04/19 14:25:39 @@ -328,6 +328,10 @@ vrele(vtmp); } } + /* Make sure file descriptors 0..2 are in use. */ + error = fdcheckstd(p); + if (error != 0) + goto exec_fail_dealloc; /* * Set the new credentials. */ Index: sys/kern/kern_descrip.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.81.2.10 diff -u -r1.81.2.10 kern_descrip.c --- sys/kern/kern_descrip.c 2002/02/16 09:23:37 1.81.2.10 +++ sys/kern/kern_descrip.c 2002/04/19 14:25:39 @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -1181,6 +1182,63 @@ } while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) fdp->fd_lastfile--; +} + +/* + * It is unsafe for set[ug]id processes to be started with file + * descriptors 0..2 closed, as these descriptors are given implicit + * significance in the Standard C library. fdcheckstd() will create a + * descriptor referencing /dev/null for each of stdin, stdout, and + * stderr that is not already open. + */ +int +fdcheckstd(p) + struct proc *p; +{ + struct nameidata nd; + struct filedesc *fdp; + struct file *fp; + register_t retval; + int fd, i, error, flags, devnull; + + fdp = p->p_fd; + if (fdp == NULL) + return (0); + devnull = -1; + error = 0; + for (i = 0; i < 3; i++) { + if (fdp->fd_ofiles[i] != NULL) + continue; + if (devnull < 0) { + error = falloc(p, &fp, &fd); + if (error != 0) + break; + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null", + p); + flags = FREAD | FWRITE; + error = vn_open(&nd, flags, 0); + if (error != 0) { + fdp->fd_ofiles[i] = NULL; + fdrop(fp, p); + break; + } + NDFREE(&nd, NDF_ONLY_PNBUF); + fp->f_data = (caddr_t)nd.ni_vp; + fp->f_flag = flags; + fp->f_ops = &vnops; + fp->f_type = DTYPE_VNODE; + VOP_UNLOCK(nd.ni_vp, 0, p); + devnull = fd; + } else { + error = fdalloc(p, 0, &fd); + if (error != 0) + break; + error = do_dup(fdp, devnull, fd, &retval, p); + if (error != 0) + break; + } + } + return (error); } /*