Index: sys/filedesc.h =================================================================== RCS file: /base/FreeBSD-CVS/src/sys/sys/filedesc.h,v retrieving revision 1.15.2.1 diff -u -r1.15.2.1 filedesc.h --- filedesc.h 1999/08/29 16:32:22 1.15.2.1 +++ filedesc.h 2000/01/20 21:39:29 @@ -139,6 +139,7 @@ int fsetown __P((pid_t, struct sigio **)); void funsetown __P((struct sigio *)); void funsetownlst __P((struct sigiolst *)); +void setugidsafety __P((struct proc *p)); #endif #endif Index: kern/kern_descrip.c =================================================================== RCS file: /base/FreeBSD-CVS/src/sys/kern/kern_descrip.c,v retrieving revision 1.58.2.3 diff -u -r1.58.2.3 kern_descrip.c --- kern_descrip.c 1999/11/18 08:09:08 1.58.2.3 +++ kern_descrip.c 2000/01/20 21:40:00 @@ -984,6 +984,62 @@ } /* + * For setuid/setgid programs we don't want to people to use that setuidness + * to generate error messages which write to a file which otherwise would + * otherwise be off limits to the proces. + * + * This is a gross hack to plug the hole. A better solution would involve + * a special vop or other form of generalized access control mechanism. We + * go ahead and just reject all procfs file systems accesses as dangerous. + * + * Since setugidsafety calls this only for fd 0, 1 and 2, this check is + * sufficient. We also don't for setugidness since we know we are. + */ +static int +is_unsafe(struct file *fp) +{ + if (fp->f_type == DTYPE_VNODE && + ((struct vnode *)(fp->f_data))->v_tag == VT_PROCFS) + return (1); + return (0); +} + +/* + * Make this setguid thing safe, if at all possible. + */ +void +setugidsafety(p) + struct proc *p; +{ + struct filedesc *fdp = p->p_fd; + struct file **fpp; + char *fdfp; + register int i; + + /* Certain daemons might not have file descriptors. */ + if (fdp == NULL) + return; + + fpp = fdp->fd_ofiles; + fdfp = fdp->fd_ofileflags; + for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++) { + if (i > 2) + break; + if (*fpp != NULL && is_unsafe(*fpp)) { + if (*fdfp & UF_MAPPED) + (void) munmapfd(p, i); + (void) closef(*fpp, p); + *fpp = NULL; + *fdfp = 0; + if (i < fdp->fd_freefile) + fdp->fd_freefile = i; + } + } + while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) + fdp->fd_lastfile--; +} + +/* * Close any files on exec? */ void Index: kern/kern_exec.c =================================================================== RCS file: /base/FreeBSD-CVS/src/sys/kern/kern_exec.c,v retrieving revision 1.93.2.3 diff -u -r1.93.2.3 kern_exec.c --- kern_exec.c 1999/08/29 16:25:58 1.93.2.3 +++ kern_exec.c 2000/01/20 21:39:29 @@ -281,6 +281,7 @@ if (attr.va_mode & VSGID) p->p_ucred->cr_gid = attr.va_gid; setsugid(p); + setugidsafety(p); } else { if (p->p_ucred->cr_uid == p->p_cred->p_ruid && p->p_ucred->cr_gid == p->p_cred->p_rgid)