From owner-freebsd-bugs Sun Sep 13 23:10:11 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id XAA08166 for freebsd-bugs-outgoing; Sun, 13 Sep 1998 23:10:11 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id XAA08093 for ; Sun, 13 Sep 1998 23:10:06 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id XAA07048; Sun, 13 Sep 1998 23:10:01 -0700 (PDT) Date: Sun, 13 Sep 1998 23:10:01 -0700 (PDT) Message-Id: <199809140610.XAA07048@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.ORG From: Don Lewis Subject: Re: kern/7899: [PATCH] [SECURITY] SETOWN allows bypass of signal credential checks and has other bugs Reply-To: Don Lewis Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR kern/7899; it has been noted by GNATS. From: Don Lewis To: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-bugs@FreeBSD.ORG Cc: Subject: Re: kern/7899: [PATCH] [SECURITY] SETOWN allows bypass of signal credential checks and has other bugs Date: Sun, 13 Sep 1998 23:01:27 -0700 Bruce Evans, , pointed out some technical flaws with my original patch. Based on his input and some simplifications that I found, I have revised my patch. Bruce feels a more radical change is desirable, essentially having the device notify the file layer of new input and the file layer would signal the appropriate processes. IMHO, while this would fix the problems with the current implementation and looks like a cleaner solution on the surface, none of the data structures exist to propagate the flow of information in that direction, and adding them would be costly in terms of resources in order to support a facility that is not heavily used. BTW, I also forgot to mention that my patch decreases the number of CPU cycles consumed by heavy users of SIGIO since it bypasses the pfind() step. --- kern/kern_descrip.c.orig Fri Sep 4 18:13:51 1998 +++ kern/kern_descrip.c Sun Sep 13 22:34:56 1998 @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -58,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +71,7 @@ static MALLOC_DEFINE(M_FILEDESC, "file desc", "Open file descriptor table"); MALLOC_DEFINE(M_FILE, "file", "Open file structure"); +static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures"); static d_open_t fdopen; @@ -257,30 +258,13 @@ return (error); case F_GETOWN: - if (fp->f_type == DTYPE_SOCKET) { - p->p_retval[0] = ((struct socket *)fp->f_data)->so_pgid; - return (0); - } error = (*fp->f_ops->fo_ioctl) - (fp, TIOCGPGRP, (caddr_t)p->p_retval, p); - p->p_retval[0] = - p->p_retval[0]; + (fp, FIOGETOWN, (caddr_t)p->p_retval, p); return (error); case F_SETOWN: - if (fp->f_type == DTYPE_SOCKET) { - ((struct socket *)fp->f_data)->so_pgid = uap->arg; - return (0); - } - if (uap->arg <= 0) { - uap->arg = -uap->arg; - } else { - struct proc *p1 = pfind(uap->arg); - if (p1 == 0) - return (ESRCH); - uap->arg = p1->p_pgrp->pg_id; - } return ((*fp->f_ops->fo_ioctl) - (fp, TIOCSPGRP, (caddr_t)&uap->arg, p)); + (fp, FIOSETOWN, (caddr_t)&uap->arg, p)); case F_SETLKW: flg |= F_WAIT; @@ -363,6 +347,134 @@ fdp->fd_lastfile = new; *retval = new; return (0); +} + +/* + * If sigio is on the list associated with a process or process group, + * remove it. + */ +void +funsetown(sigio) + register struct sigio *sigio; +{ + register int s; + + if (sigio == NULL) + return; + + s = splhigh(); /* in case point assignment is not atomic */ + *(sigio->sio_myref) = NULL; + splx(s); + + if (sigio->sio_pgid < 0) { + SLIST_REMOVE(&(sigio->sio_pgrp->pg_sigiolst), sigio, + sigio, sio_pgsigio); + } else /* if ((*sigiop)->sio_pgid > 0) */ { + SLIST_REMOVE(&(sigio->sio_proc->p_sigiolst), sigio, + sigio, sio_pgsigio); + } + + crfree(sigio->sio_ucred); + + FREE(sigio, M_SIGIO); +} + +void +funsetownlst(sigiolst) + register struct sigiolst *sigiolst; +{ + register struct sigio *sigio; + + while ((sigio = sigiolst->slh_first) != NULL) + funsetown(sigio); +} + +/* + * Common code for FIOSETOWN ioctl called by F_SETOWN + * + * After permission checking, add sigio structure to the sigio list for + * the process or process group. + */ +int +fsetown(pgid, sigiop) + register pid_t pgid; + register struct sigio **sigiop; +{ + register struct proc *proc = NULL; + register struct pgrp *pgrp = NULL; + register struct sigio *sigio; + register int s; + + if (pgid == 0) { + funsetown(*sigiop); + return (0); + } else if (pgid > 0) { + proc = pfind(pgid); + if (proc == NULL) + return (ESRCH); + /* + * Policy - Don't allow a process to FSETOWN a process + * in another session. + * + * Remove this test to allow maximum flexibility or + * restrict FSETOWN to the current process or process + * group for maximum safety. + */ + else if (proc->p_session != curproc->p_session) + return (EPERM); + } else /* if (pgid < 0) */ { + pgrp = pgfind(-pgid); + if (pgrp == NULL) + return (ESRCH); + /* + * Policy - Don't allow a process to FSETOWN a process + * in another session. + * + * Remove this test to allow maximum flexibility or + * restrict FSETOWN to the current process or process + * group for maximum safety. + */ + else if (pgrp->pg_session != curproc->p_session) + return (EPERM); + } + + funsetown(*sigiop); + + MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, + M_WAITOK); + + if (pgid > 0) { + SLIST_INSERT_HEAD(&(proc->p_sigiolst), sigio, sio_pgsigio); + sigio->sio_proc = proc; + } else { + SLIST_INSERT_HEAD(&(pgrp->pg_sigiolst), sigio, sio_pgsigio); + sigio->sio_pgrp = pgrp; + } + + sigio->sio_pgid = pgid; + + crhold(curproc->p_ucred); + sigio->sio_ucred = curproc->p_ucred; + sigio->sio_ruid = curproc->p_cred->p_ruid; /* wish this was in ucred */ + + sigio->sio_myref = sigiop; + + s = splhigh(); /* in case point assignment is not atomic */ + *sigiop = sigio; + splx(s); + + return (0); +} + +/* + * Common code for FIOGETOWN ioctl called by F_GETOWN + */ +pid_t +fgetown(sigio) + register struct sigio *sigio; +{ + /* we could also return sigio->sio_{proc->p_pid,pgrp->pg_id} */ + return (sigio != NULL ? sigio->sio_pgid : 0); } /* --- kern/kern_exit.c.orig Fri Sep 4 18:13:52 1998 +++ kern/kern_exit.c Fri Sep 11 03:40:57 1998 @@ -186,6 +186,12 @@ untimeout(realitexpire, (caddr_t)p, p->p_ithandle); /* + * Reset any sigio structures pointing to us as a result of + * F_SETOWN with our pid + */ + funsetownlst(&(p->p_sigiolst)); + + /* * Close open files and release open-file table. * This may block! */ --- kern/kern_proc.c.orig Fri Sep 4 18:13:56 1998 +++ kern/kern_proc.c Fri Sep 11 05:12:51 1998 @@ -48,6 +48,7 @@ #include #include #include +#include static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); MALLOC_DEFINE(M_SESSION, "session", "session header"); @@ -242,6 +243,7 @@ LIST_INIT(&pgrp->pg_members); LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); pgrp->pg_jobc = 0; + SLIST_INIT(&(pgrp->pg_sigiolst)); } else if (pgrp == p->p_pgrp) return (0); @@ -283,6 +285,12 @@ pgdelete(pgrp) register struct pgrp *pgrp; { + + /* + * Reset any sigio structures pointing to us as a result of + * F_SETOWN with our pgid + */ + funsetownlst(&(pgrp->pg_sigiolst)); if (pgrp->pg_session->s_ttyp != NULL && pgrp->pg_session->s_ttyp->t_pgrp == pgrp) --- kern/kern_sig.c.orig Fri Sep 4 18:13:56 1998 +++ kern/kern_sig.c Fri Sep 11 05:26:34 1998 @@ -96,6 +96,16 @@ (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) +/* + * Policy -- Can real uid ruid with ucred uc send a signal to process q? + */ +#define CANSIGIO(ruid, uc, q) \ + ((uc)->cr_uid == 0 || \ + ruid == (q)->p_cred->p_ruid || \ + (uc)->cr_uid == (q)->p_cred->p_ruid || \ + ruid == (q)->p_ucred->cr_uid || \ + (uc)->cr_uid == (q)->p_ucred->cr_uid) + static int sugid_coredump; SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RW, &sugid_coredump, 0, ""); @@ -1419,4 +1429,31 @@ psignal(p, SIGSYS); return (EINVAL); +} + +/* + * Send a signal to a SIGIO or SIGURG to a process or process group using + * stored credentials rather than those of the current process + */ +void +pgsigio(sigio, signum, checkctty) + register struct sigio *sigio; + int signum, checkctty; +{ + if (sigio == NULL) + return; + + if (sigio->sio_pgid > 0) { + if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred, + sigio->sio_proc)) + psignal(sigio->sio_proc, signum); + } else if (sigio->sio_pgid < 0) { + register struct proc *p; + + for (p = sigio->sio_pgrp->pg_members.lh_first; p != NULL; + p = p->p_pglist.le_next) + if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred, p) && + (checkctty == 0 || (p->p_flag & P_CONTROLT))) + psignal(p, signum); + } } --- kern/subr_log.c.orig Fri Sep 4 18:14:00 1998 +++ kern/subr_log.c Sat Sep 12 22:34:20 1998 @@ -51,6 +51,7 @@ #include #include #include +#include #ifdef DEVFS #include #endif /*DEVFS*/ @@ -75,7 +76,8 @@ static struct logsoftc { int sc_state; /* see above for possibilities */ struct selinfo sc_selp; /* process waiting on select call */ - int sc_pgid; /* process/group for async I/O */ + struct sigio *sc_sigio; /* credentials and proc * or pgrp * + * for SIGIO/SIGURG */ } logsoftc; int log_open; /* also used in log() */ @@ -90,7 +92,7 @@ if (log_open) return (EBUSY); log_open = 1; - logsoftc.sc_pgid = p->p_pid; /* signal process only */ + fsetown(p->p_pid, &logsoftc.sc_sigio); /* signal process only */ return (0); } @@ -104,6 +106,7 @@ log_open = 0; logsoftc.sc_state = 0; + funsetown(logsoftc.sc_sigio); return (0); } @@ -183,12 +186,8 @@ if (!log_open) return; selwakeup(&logsoftc.sc_selp); - if (logsoftc.sc_state & LOG_ASYNC) { - if (logsoftc.sc_pgid < 0) - gsignal(-logsoftc.sc_pgid, SIGIO); - else if ((p = pfind(logsoftc.sc_pgid))) - psignal(p, SIGIO); - } + if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL) + pgsigio(logsoftc.sc_sigio, SIGIO, 0); if (logsoftc.sc_state & LOG_RDWAIT) { wakeup((caddr_t)msgbufp); logsoftc.sc_state &= ~LOG_RDWAIT; @@ -229,12 +228,20 @@ logsoftc.sc_state &= ~LOG_ASYNC; break; - case TIOCSPGRP: - logsoftc.sc_pgid = *(int *)data; + case FIOSETOWN: + return (fsetown(*(int *)data, &(logsoftc.sc_sigio))); + + case FIOGETOWN: + *(int *)data = fgetown(logsoftc.sc_sigio); break; + /* Deprecated */ + case TIOCSPGRP: + return (fsetown(-(*(int *)data), &(logsoftc.sc_sigio))); + + /* Deprecated */ case TIOCGPGRP: - *(int *)data = logsoftc.sc_pgid; + *(int *)data = -fgetown(logsoftc.sc_sigio); break; default: --- kern/sys_generic.c.orig Sat Sep 5 19:23:02 1998 +++ kern/sys_generic.c Sat Sep 12 22:37:45 1998 @@ -469,37 +469,6 @@ error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); break; - case FIOSETOWN: - tmp = *(int *)data; - if (fp->f_type == DTYPE_SOCKET) { - ((struct socket *)fp->f_data)->so_pgid = tmp; - error = 0; - break; - } - if (tmp <= 0) { - tmp = -tmp; - } else { - struct proc *p1 = pfind(tmp); - if (p1 == 0) { - error = ESRCH; - break; - } - tmp = p1->p_pgrp->pg_id; - } - error = (*fp->f_ops->fo_ioctl) - (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); - break; - - case FIOGETOWN: - if (fp->f_type == DTYPE_SOCKET) { - error = 0; - *(int *)data = ((struct socket *)fp->f_data)->so_pgid; - break; - } - error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); - *(int *)data = -*(int *)data; - break; - default: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); /* --- kern/sys_socket.c.orig Fri Sep 4 18:14:02 1998 +++ kern/sys_socket.c Sat Sep 12 21:56:55 1998 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -114,12 +115,18 @@ *(int *)data = so->so_rcv.sb_cc; return (0); - case SIOCSPGRP: - so->so_pgid = *(int *)data; + case FIOSETOWN: + return (fsetown(*(int *)data, &(so->so_sigio))); + + case FIOGETOWN: + *(int *)data = fgetown(so->so_sigio); return (0); + case SIOCSPGRP: + return (fsetown(-(*(int *)data), &(so->so_sigio))); + case SIOCGPGRP: - *(int *)data = so->so_pgid; + *(int *)data = -fgetown(so->so_sigio); return (0); case SIOCATMARK: --- kern/tty.c.orig Fri Sep 4 18:14:04 1998 +++ kern/tty.c Sat Sep 12 21:45:23 1998 @@ -90,6 +90,7 @@ #include #include #include +#include /* get fsetown, funsetown, fgetown */ #if NSNP > 0 #include #endif @@ -230,6 +231,8 @@ { int s; + funsetown(tp->t_sigio); + s = spltty(); if (constty == tp) constty = NULL; @@ -756,6 +759,25 @@ *(int *)data = ttnread(tp); splx(s); break; + + case FIOSETOWN: + /* + * Policy -- Don't allow FIOSETOWN on someone else's + * controlling tty + */ + if (tp->t_session != NULL && !isctty(p, tp)) + return (ENOTTY); + + error = fsetown(*(int *)data, &(tp->t_sigio)); + if (error) + return (error); + break; + case FIOGETOWN: + if (tp->t_session != NULL && !isctty(p, tp)) + return (ENOTTY); + *(int *)data = fgetown(tp->t_sigio); + break; + case TIOCEXCL: /* set exclusive use of tty */ s = spltty(); SET(tp->t_state, TS_XCLUDE); @@ -2082,8 +2104,8 @@ if (tp->t_rsel.si_pid != 0) selwakeup(&tp->t_rsel); - if (ISSET(tp->t_state, TS_ASYNC)) - pgsignal(tp->t_pgrp, SIGIO, 1); + if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) + pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL)); wakeup(TSA_HUP_OR_INPUT(tp)); } --- kern/uipc_socket.c.orig Fri Sep 4 18:14:06 1998 +++ kern/uipc_socket.c Fri Sep 11 03:40:58 1998 @@ -218,6 +218,8 @@ int s = splnet(); /* conservative */ int error = 0; + funsetown(so->so_sigio); + if (so->so_options & SO_ACCEPTCONN) { struct socket *sp, *sonext; @@ -1182,10 +1184,8 @@ { struct proc *p; - if (so->so_pgid < 0) - gsignal(-so->so_pgid, SIGURG); - else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) - psignal(p, SIGURG); + if (so->so_sigio != NULL) + pgsigio(so->so_sigio, SIGURG, 0); selwakeup(&so->so_rcv.sb_sel); } --- kern/uipc_socket2.c.orig Sat Sep 5 19:23:02 1998 +++ kern/uipc_socket2.c Sat Sep 12 21:46:49 1998 @@ -213,7 +213,7 @@ so->so_state = head->so_state | SS_NOFDREF; so->so_proto = head->so_proto; so->so_timeo = head->so_timeo; - so->so_pgid = head->so_pgid; + fsetown(fgetown(head->so_sigio), &(so->so_sigio)); so->so_uid = head->so_uid; (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); @@ -321,11 +321,8 @@ sb->sb_flags &= ~SB_WAIT; wakeup((caddr_t)&sb->sb_cc); } - if (so->so_state & SS_ASYNC) { - if (so->so_pgid < 0) - gsignal(-so->so_pgid, SIGIO); - else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) - psignal(p, SIGIO); + if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) { + pgsigio(so->so_sigio, SIGIO, 0); } if (sb->sb_flags & SB_UPCALL) (*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT); @@ -916,7 +913,7 @@ xso->so_qlimit = so->so_qlimit; xso->so_timeo = so->so_timeo; xso->so_error = so->so_error; - xso->so_pgid = so->so_pgid; + xso->so_pgid = so->so_sigio ? so->so_sigio->sio_pgid : 0; xso->so_oobmark = so->so_oobmark; sbtoxsockbuf(&so->so_snd, &xso->so_snd); sbtoxsockbuf(&so->so_rcv, &xso->so_rcv); --- kern/sys_pipe.c.orig Fri Sep 4 18:14:02 1998 +++ kern/sys_pipe.c Sat Sep 12 21:48:03 1998 @@ -256,7 +256,7 @@ cpipe->pipe_atime = cpipe->pipe_ctime; cpipe->pipe_mtime = cpipe->pipe_ctime; bzero(&cpipe->pipe_sel, sizeof cpipe->pipe_sel); - cpipe->pipe_pgid = NO_PID; + cpipe->pipe_sigio = NULL; #ifndef PIPE_NODIRECT /* @@ -315,11 +315,8 @@ cpipe->pipe_state &= ~PIPE_SEL; selwakeup(&cpipe->pipe_sel); } - if (cpipe->pipe_state & PIPE_ASYNC) { - if (cpipe->pipe_pgid < 0) - gsignal(-cpipe->pipe_pgid, SIGIO); - else if ((p = pfind(cpipe->pipe_pgid)) != NULL) - psignal(p, SIGIO); + if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_sigio) { + pgsigio(cpipe->pipe_sigio, SIGIO, 0); } } @@ -953,12 +950,20 @@ *(int *)data = mpipe->pipe_buffer.cnt; return (0); - case TIOCSPGRP: - mpipe->pipe_pgid = *(int *)data; + case FIOSETOWN: + return (fsetown(*(int *)data, &(mpipe->pipe_sigio))); + + case FIOGETOWN: + *(int *)data = fgetown(mpipe->pipe_sigio); return (0); + /* Deprecated */ + case TIOCSPGRP: + return (fsetown(-(*(int *)data), &(mpipe->pipe_sigio))); + + /* Deprecated */ case TIOCGPGRP: - *(int *)data = mpipe->pipe_pgid; + *(int *)data = -fgetown(mpipe->pipe_sigio); return (0); } @@ -1038,6 +1043,7 @@ { struct pipe *cpipe = (struct pipe *)fp->f_data; + funsetown(cpipe->pipe_sigio); pipeclose(cpipe); fp->f_data = NULL; return 0; --- net/bpf.c.orig Fri Sep 4 18:14:51 1998 +++ net/bpf.c Sat Sep 12 21:49:39 1998 @@ -61,6 +61,7 @@ #include #include #include +#include /* get fsetown, funsetown, fgetown */ #if defined(sparc) && BSD < 199103 #include @@ -379,6 +380,8 @@ register struct bpf_d *d = &bpf_dtab[minor(dev)]; register int s; + funsetown(d->bd_sigio); + s = splimp(); if (d->bd_bif) bpf_detachd(d); @@ -537,11 +540,8 @@ struct proc *p; wakeup((caddr_t)d); - if (d->bd_async && d->bd_sig) - if (d->bd_pgid > 0) - gsignal (d->bd_pgid, d->bd_sig); - else if (p = pfind (-d->bd_pgid)) - psignal (p, d->bd_sig); + if (d->bd_async && d->bd_sig && d->bd_sigio) + pgsigio(d->bd_sigio, d->bd_sig, 0); #if BSD >= 199103 selwakeup(&d->bd_sel); @@ -838,18 +838,22 @@ d->bd_async = *(int *)addr; break; -/* N.B. ioctl (FIOSETOWN) and fcntl (F_SETOWN) both end up doing the - equivalent of a TIOCSPGRP and hence end up here. *However* TIOCSPGRP's arg - is a process group if it's positive and a process id if it's negative. This - is exactly the opposite of what the other two functions want! Therefore - there is code in ioctl and fcntl to negate the arg before calling here. */ + case FIOSETOWN: + error = fsetown(*(int *)addr, &(d->bd_sigio)); + break; + + case FIOGETOWN: + *(int *)addr = fgetown(d->bd_sigio); + break; - case TIOCSPGRP: /* Process or group to send signals to */ - d->bd_pgid = *(int *)addr; + /* Deprecated */ + case TIOCSPGRP: + error = fsetown(-(*(int *)addr), &(d->bd_sigio)); break; + /* Deprecated */ case TIOCGPGRP: - *(int *)addr = d->bd_pgid; + *(int *)addr = -fgetown(d->bd_sigio); break; case BIOCSRSIG: /* Set receive signal */ --- net/bpfdesc.h.orig Sat Feb 22 01:40:57 1997 +++ net/bpfdesc.h Fri Sep 11 03:40:58 1998 @@ -78,7 +78,8 @@ u_char bd_immediate; /* true to return on packet arrival */ int bd_async; /* non-zero if packet reception should generate signal */ int bd_sig; /* signal to send upon packet reception */ - pid_t bd_pgid; /* process or group id for signal */ + struct sigio * bd_sigio; /* credentials and proc * or pgrp * + * for SIGIO/SIGURG */ #if BSD < 199103 u_char bd_selcoll; /* true if selects collide */ int bd_timedout; --- net/if_tun.c.orig Fri Sep 4 18:15:00 1998 +++ net/if_tun.c Sat Sep 12 21:50:53 1998 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #ifdef DEVFS @@ -215,7 +216,7 @@ } splx(s); } - tp->tun_pgrp = 0; + funsetown(tp->tun_sigio); selwakeup(&tp->tun_rsel); TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); @@ -372,11 +373,8 @@ tp->tun_flags &= ~TUN_RWAIT; wakeup((caddr_t)tp); } - if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) { - if (tp->tun_pgrp > 0) - gsignal(tp->tun_pgrp, SIGIO); - else if ((p = pfind(-tp->tun_pgrp)) != 0) - psignal(p, SIGIO); + if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) { + pgsigio(tp->tun_sigio, SIGIO, 0); } selwakeup(&tp->tun_rsel); return 0; @@ -434,12 +432,22 @@ *(int *)data = 0; splx(s); break; + case FIOSETOWN: + return (fsetown(*(int *)data, &(tp->tun_sigio))); + + case FIOGETOWN: + *(int *)data = fgetown(tp->tun_sigio); + return (0); + + /* Deprecated */ case TIOCSPGRP: - tp->tun_pgrp = *(int *)data; - break; + return (fsetown(-(*(int *)data), &(tp->tun_sigio))); + + /* Deprecated */ case TIOCGPGRP: - *(int *)data = tp->tun_pgrp; - break; + *(int *)data = -fgetown(tp->tun_sigio); + return (0); + default: return (ENOTTY); } --- net/if_tunvar.h.orig Fri Sep 11 04:13:34 1998 +++ net/if_tunvar.h Fri Sep 11 04:13:23 1998 @@ -42,7 +42,8 @@ #define TUN_READY (TUN_OPEN | TUN_INITED) struct ifnet tun_if; /* the interface */ - int tun_pgrp; /* the process group - if any */ + struct sigio *tun_sigio; /* credentials and proc * or pgrp * + * for SIGIO/SIGURG */ struct selinfo tun_rsel; /* read select */ struct selinfo tun_wsel; /* write select (not used) */ }; --- net/if_sl.c.orig Fri Sep 4 18:14:57 1998 +++ net/if_sl.c Fri Sep 11 15:41:59 1998 @@ -1016,7 +1016,7 @@ if (sc->sc_keepalive) { if (sc->sc_flags & SC_KEEPALIVE) - pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1); + pgsigio (sc->sc_ttyp->t_sigio, SIGURG, 1); else sc->sc_flags |= SC_KEEPALIVE; sc->sc_kahandle = timeout(sl_keepalive, sc, sc->sc_keepalive); --- sys/filedesc.h.orig Fri Sep 4 18:17:03 1998 +++ sys/filedesc.h Sat Sep 12 21:52:37 1998 @@ -37,6 +37,8 @@ #ifndef _SYS_FILEDESC_H_ #define _SYS_FILEDESC_H_ +#include /* For SLIST_HEAD, SLIST_ENTRY */ + /* * This structure is used for the management of descriptors. It may be * shared by multiple processes. @@ -91,10 +93,40 @@ */ #define OFILESIZE (sizeof(struct file *) + sizeof(char)) +/* + * Structure that holds + * The pgid used as an argument to F_SETOWN + * The credentials of the caller + * A pointer to the process or process group referenced by the pgid + * This structure is placed on an SLIST belonging to the proc or pgrp + * so that the entire list may be revoked when the process exits or the + * process group disappears. + */ +struct sigio { + union { + struct proc *siu_proc; /* Process to receive SIGIO/SIGURG */ + struct pgrp *siu_pgrp; /* Process group to receive ... */ + } sio_u; + SLIST_ENTRY(sigio) sio_pgsigio; /* sigio's for process or group */ + struct sigio **sio_myref; /* location of the pointer that holds + * the reference */ + struct ucred *sio_ucred; /* Current credentials */ + uid_t sio_ruid; /* Real user id */ + pid_t sio_pgid; /* pgid for signals */ +}; +#define sio_proc sio_u.siu_proc +#define sio_pgrp sio_u.siu_pgrp + +SLIST_HEAD(sigiolst, sigio); + #ifdef KERNEL /* * Kernel global variables and routines. */ +void funsetown __P((struct sigio *)); +void funsetownlst __P((struct sigiolst *)); +int fsetown __P((pid_t, struct sigio **)); +pid_t fgetown __P((struct sigio *)); int dupfdopen __P((struct filedesc *, int, int, int, int)); int fdalloc __P((struct proc *p, int want, int *result)); int fdavail __P((struct proc *p, int n)); @@ -109,6 +141,10 @@ int getvnode __P((struct filedesc *fdp, int fd, struct file **fpp)); int fdissequential __P((struct file *)); void fdsequential __P((struct file *, int)); +#endif + +#ifdef MALLOC_DECLARE +MALLOC_DECLARE(M_SIGIO); #endif #endif --- sys/pipe.h.orig Fri Sep 4 18:17:06 1998 +++ sys/pipe.h Fri Sep 11 04:39:16 1998 @@ -102,7 +102,8 @@ struct timespec pipe_atime; /* time of last access */ struct timespec pipe_mtime; /* time of last modify */ struct timespec pipe_ctime; /* time of status change */ - int pipe_pgid; /* process/group for async I/O */ + struct sigio *pipe_sigio; /* credentials and proc * or pgrp * + * for SIGIO/SIGURG */ struct pipe *pipe_peer; /* link with other direction */ u_int pipe_state; /* pipe status info */ int pipe_busy; /* busy flag, mostly to handle rundown sanely */ --- sys/proc.h.orig Fri Sep 4 18:17:07 1998 +++ sys/proc.h Fri Sep 11 04:23:59 1998 @@ -52,6 +52,7 @@ #endif #include #include +#include /* For struct sigiolst */ /* * One structure allocated per session. @@ -71,6 +72,7 @@ LIST_ENTRY(pgrp) pg_hash; /* Hash chain. */ LIST_HEAD(, proc) pg_members; /* Pointer to pgrp members. */ struct session *pg_session; /* Pointer to session. */ + struct sigiolst pg_sigiolst; /* List of sigio sources */ pid_t pg_id; /* Pgrp id. */ int pg_jobc; /* # procs qualifying pgrp for job control */ }; @@ -160,6 +162,7 @@ unsigned char p_pfsflags; /* procfs flags */ char p_pad3[2]; /* padding for alignment */ register_t p_retval[2]; /* syscall aux returns */ + struct sigiolst p_sigiolst; /* List of sigio sources */ /* End area that is zeroed on creation. */ #define p_endzero p_startcopy --- sys/signalvar.h.orig Fri Sep 4 18:17:08 1998 +++ sys/signalvar.h Fri Sep 11 05:07:14 1998 @@ -152,6 +152,7 @@ #ifdef KERNEL struct pgrp; struct proc; +struct sigio; /* * Machine-independent functions: @@ -166,6 +167,7 @@ void sigexit __P((struct proc *p, int signum)); void siginit __P((struct proc *p)); void trapsignal __P((struct proc *p, int sig, u_long code)); +void pgsigio __P((struct sigio *, int signum, int checkctty)); /* * Machine-dependent functions: --- sys/socketvar.h.orig Fri Sep 4 18:17:09 1998 +++ sys/socketvar.h Sat Sep 12 21:52:52 1998 @@ -77,7 +77,8 @@ short so_qlimit; /* max number queued connections */ short so_timeo; /* connection timeout */ u_short so_error; /* error affecting connection */ - pid_t so_pgid; /* pgid for signals */ + struct sigio *so_sigio; /* credentials and proc * or pgrp * + * for SIGIO/SIGURG */ u_long so_oobmark; /* chars to oob mark */ /* * Variables for socket buffering. --- sys/tty.h.orig Fri Sep 4 18:17:12 1998 +++ sys/tty.h Fri Sep 11 03:40:59 1998 @@ -79,6 +79,8 @@ int t_timeout; /* Timeout for ttywait() */ struct pgrp *t_pgrp; /* Foreground process group. */ struct session *t_session; /* Enclosing session. */ + struct sigio *t_sigio; /* credentials and proc * or pgrp * + * for SIGIO/SIGURG */ struct selinfo t_rsel; /* Tty read/oob select. */ struct selinfo t_wsel; /* Tty write select. */ struct termios t_termios; /* Termios state. */ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message