From de184682fa22833c7b18a96a136bc031ae786434 Mon Sep 17 00:00:00 2001 From: truckman Date: Wed, 11 Nov 1998 10:04:13 +0000 Subject: [PATCH] Installed the second patch attached to kern/7899 with some changes suggested by bde, a few other tweaks to get the patch to apply cleanly again and some improvements to the comments. This change closes some fairly minor security holes associated with F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN had on tty devices. For more details, see the description on the PR. Because this patch increases the size of the proc and pgrp structures, it is necessary to re-install the includes and recompile libkvm, the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w. PR: kern/7899 Reviewed by: bde, elvind --- sys/kern/kern_descrip.c | 142 ++++++++++++++++++++++++++++++++++------ sys/kern/kern_exit.c | 8 ++- sys/kern/kern_proc.c | 10 ++- sys/kern/kern_sig.c | 39 ++++++++++- sys/kern/subr_log.c | 30 +++++---- sys/kern/sys_generic.c | 33 +--------- sys/kern/sys_pipe.c | 26 ++++---- sys/kern/sys_socket.c | 15 +++-- sys/kern/tty.c | 27 +++++++- sys/kern/uipc_sockbuf.c | 14 ++-- sys/kern/uipc_socket.c | 9 ++- sys/kern/uipc_socket2.c | 14 ++-- sys/net/bpf.c | 33 +++++----- sys/net/bpfdesc.h | 4 +- sys/net/if_tun.c | 29 ++++---- sys/net/if_tunvar.h | 4 +- sys/sys/filedesc.h | 32 ++++++++- sys/sys/pipe.h | 4 +- sys/sys/proc.h | 5 +- sys/sys/signalvar.h | 4 +- sys/sys/socketvar.h | 4 +- sys/sys/tty.h | 3 +- 22 files changed, 343 insertions(+), 146 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index e3d736b417b4..d2ef3e17f09e 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 - * $Id: kern_descrip.c,v 1.54 1998/07/15 06:10:16 bde Exp $ + * $Id: kern_descrip.c,v 1.55 1998/07/29 17:38:13 bde Exp $ */ #include "opt_compat.h" @@ -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 @@ fcntl(p, uap) 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; @@ -365,6 +349,124 @@ finishdup(fdp, old, new, retval) return (0); } +/* + * If sigio is on the list associated with a process or process group, + * disable signalling from the device, remove sigio from the list and + * free sigio. + */ +void +funsetown(sigio) + struct sigio *sigio; +{ + int s; + + if (sigio == NULL) + return; + s = splhigh(); + *(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); +} + +/* Free a list of sigio structures. */ +void +funsetownlst(sigiolst) + struct sigiolst *sigiolst; +{ + struct sigio *sigio; + + while ((sigio = sigiolst->slh_first) != NULL) + funsetown(sigio); +} + +/* + * This is common code for FIOSETOWN ioctl called by fcntl(fd, F_SETOWN, arg). + * + * After permission checking, add a sigio structure to the sigio list for + * the process or process group. + */ +int +fsetown(pgid, sigiop) + pid_t pgid; + struct sigio **sigiop; +{ + struct proc *proc = NULL; + struct pgrp *pgrp = NULL; + struct sigio *sigio; + 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; + /* It would be convenient if p_ruid was in ucred. */ + sigio->sio_ruid = curproc->p_cred->p_ruid; + sigio->sio_myref = sigiop; + s = splhigh(); + *sigiop = sigio; + splx(s); + return (0); +} + +/* + * This is common code for FIOGETOWN ioctl called by fcntl(fd, F_GETOWN, arg). + */ +pid_t +fgetown(sigio) + struct sigio *sigio; +{ + return (sigio != NULL ? sigio->sio_pgid : 0); +} + /* * Close a file descriptor. */ diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 84ae1a1d2dd3..fd5e23ef7189 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 - * $Id: kern_exit.c,v 1.67 1998/06/05 21:44:20 dg Exp $ + * $Id: kern_exit.c,v 1.68 1998/11/10 09:16:29 peter Exp $ */ #include "opt_compat.h" @@ -186,6 +186,12 @@ exit1(p, rv) if (timevalisset(&p->p_realtimer.it_value)) 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! diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index d546ad771911..a51735880943 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 - * $Id: kern_proc.c,v 1.37 1998/07/11 07:45:40 bde Exp $ + * $Id: kern_proc.c,v 1.38 1998/11/09 15:07:41 truckman Exp $ */ #include @@ -48,6 +48,7 @@ #include #include #include +#include static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); MALLOC_DEFINE(M_SESSION, "session", "session header"); @@ -243,6 +244,7 @@ enterpgrp(p, pgid, mksess) 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); @@ -285,6 +287,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) pgrp->pg_session->s_ttyp->t_pgrp = NULL; diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 290917ac4a10..29baceed4afb 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 - * $Id: kern_sig.c,v 1.47 1998/09/14 23:25:18 jdp Exp $ + * $Id: kern_sig.c,v 1.48 1998/10/21 16:31:38 jdp Exp $ */ #include "opt_compat.h" @@ -86,6 +86,16 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, &kern_logsigexit, 0, (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) + int sugid_coredump; SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RW, &sugid_coredump, 0, ""); @@ -1344,3 +1354,30 @@ nosys(p, args) 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) + 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) { + 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); + } +} diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c index 80193d400743..01d8c4eb6a06 100644 --- a/sys/kern/subr_log.c +++ b/sys/kern/subr_log.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)subr_log.c 8.1 (Berkeley) 6/10/93 - * $Id: subr_log.c,v 1.29 1998/05/28 09:30:20 phk Exp $ + * $Id: subr_log.c,v 1.30 1998/06/07 17:11:38 dfr Exp $ */ /* @@ -51,6 +51,7 @@ #include #include #include +#include #ifdef DEVFS #include #endif /*DEVFS*/ @@ -75,7 +76,7 @@ static struct cdevsw log_cdevsw = 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; /* information for SIGIO */ } logsoftc; int log_open; /* also used in log() */ @@ -90,7 +91,7 @@ logopen(dev, flags, mode, p) 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 +105,7 @@ logclose(dev, flag, mode, p) log_open = 0; logsoftc.sc_state = 0; + funsetown(logsoftc.sc_sigio); return (0); } @@ -183,12 +185,8 @@ logwakeup() 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 +227,20 @@ logioctl(dev, com, data, flag, p) 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; + /* This is deprecated, FIOSETOWN should be used instead. */ + case TIOCSPGRP: + return (fsetown(-(*(int *)data), &logsoftc.sc_sigio)); + + /* This is deprecated, FIOGETOWN should be used instead */ case TIOCGPGRP: - *(int *)data = logsoftc.sc_pgid; + *(int *)data = -fgetown(logsoftc.sc_sigio); break; default: diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index bb8f7a3a70b0..e16fed7cfbd6 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94 - * $Id: sys_generic.c,v 1.40 1998/08/24 08:39:38 dfr Exp $ + * $Id: sys_generic.c,v 1.41 1998/09/05 14:30:11 bde Exp $ */ #include "opt_ktrace.h" @@ -469,37 +469,6 @@ ioctl(p, uap) 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); /* diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 5f6789752c28..b95cdd28e078 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -16,7 +16,7 @@ * 4. Modifications may be freely made to this file if the above conditions * are met. * - * $Id: sys_pipe.c,v 1.43 1998/10/13 08:24:40 dg Exp $ + * $Id: sys_pipe.c,v 1.44 1998/10/28 13:36:58 dg Exp $ */ /* @@ -256,7 +256,6 @@ pipeinit(cpipe) 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; #ifndef PIPE_NODIRECT /* @@ -315,12 +314,8 @@ pipeselwakeup(cpipe) 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); } /* ARGSUSED */ @@ -953,12 +948,20 @@ pipe_ioctl(fp, cmd, data, p) *(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); + /* This is deprecated, FIOSETOWN should be used instead. */ + case TIOCSPGRP: + return (fsetown(-(*(int *)data), &mpipe->pipe_sigio)); + + /* This is deprecated, FIOGETOWN should be used instead. */ case TIOCGPGRP: - *(int *)data = mpipe->pipe_pgid; + *(int *)data = -fgetown(mpipe->pipe_sigio); return (0); } @@ -1038,6 +1041,7 @@ pipe_close(fp, p) { struct pipe *cpipe = (struct pipe *)fp->f_data; + funsetown(cpipe->pipe_sigio); pipeclose(cpipe); fp->f_data = NULL; return 0; diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 5b65bea89362..8cf30cdcaf55 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 - * $Id: sys_socket.c,v 1.17 1998/03/28 10:33:07 bde Exp $ + * $Id: sys_socket.c,v 1.18 1998/06/07 17:11:40 dfr Exp $ */ #include @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -114,12 +115,18 @@ soo_ioctl(fp, cmd, data, p) *(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: diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 7d34873e2e4d..8a043fd215a8 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)tty.c 8.8 (Berkeley) 1/21/94 - * $Id: tty.c,v 1.105 1998/07/11 10:41:15 bde Exp $ + * $Id: tty.c,v 1.106 1998/08/19 04:01:00 bde Exp $ */ /*- @@ -90,6 +90,7 @@ #include #include #include +#include #if NSNP > 0 #include #endif @@ -230,6 +231,7 @@ ttyclose(tp) { int s; + funsetown(tp->t_sigio); s = spltty(); if (constty == tp) constty = NULL; @@ -756,6 +758,25 @@ ttioctl(tp, cmd, data, flag) *(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 +2103,8 @@ ttwakeup(tp) 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)); } diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 23c7751776e7..6c55ca0fff42 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_socket2.c,v 1.39 1998/09/05 13:24:39 bde Exp $ + * $Id: uipc_socket2.c,v 1.40 1998/11/04 20:22:11 fenner Exp $ */ #include @@ -213,7 +213,7 @@ sonewconn(head, connstatus) 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,12 +321,8 @@ sowakeup(so, sb) 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); } @@ -918,7 +914,7 @@ sotoxsocket(struct socket *so, struct xsocket *xso) 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); diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 05d312f65302..275e94b44bc0 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 - * $Id: uipc_socket.c,v 1.44 1998/08/31 15:34:55 wollman Exp $ + * $Id: uipc_socket.c,v 1.45 1998/08/31 18:07:23 wollman Exp $ */ #include @@ -218,6 +218,7 @@ soclose(so) int s = splnet(); /* conservative */ int error = 0; + funsetown(so->so_sigio); if (so->so_options & SO_ACCEPTCONN) { struct socket *sp, *sonext; @@ -1182,10 +1183,8 @@ sohasoutofband(so) { 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); } diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 23c7751776e7..6c55ca0fff42 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_socket2.c,v 1.39 1998/09/05 13:24:39 bde Exp $ + * $Id: uipc_socket2.c,v 1.40 1998/11/04 20:22:11 fenner Exp $ */ #include @@ -213,7 +213,7 @@ sonewconn(head, connstatus) 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,12 +321,8 @@ sowakeup(so, sb) 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); } @@ -918,7 +914,7 @@ sotoxsocket(struct socket *so, struct xsocket *xso) 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); diff --git a/sys/net/bpf.c b/sys/net/bpf.c index f9a217b5e334..39d2d266d532 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -37,7 +37,7 @@ * * @(#)bpf.c 8.2 (Berkeley) 3/28/94 * - * $Id: bpf.c,v 1.43 1998/10/04 23:04:48 alex Exp $ + * $Id: bpf.c,v 1.44 1998/10/08 00:32:08 alex Exp $ */ #include "bpfilter.h" @@ -61,6 +61,7 @@ #include #include #include +#include #if defined(sparc) && BSD < 199103 #include @@ -379,6 +380,7 @@ bpfclose(dev, flags, fmt, p) 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 +539,8 @@ bpf_wakeup(d) 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); @@ -834,18 +833,22 @@ bpfioctl(dev, cmd, addr, flags, p) 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 TIOCSPGRP: /* Process or group to send signals to */ - d->bd_pgid = *(int *)addr; + case FIOSETOWN: + error = fsetown(*(int *)addr, &d->bd_sigio); break; + case FIOGETOWN: + *(int *)addr = fgetown(d->bd_sigio); + break; + + /* This is deprecated, FIOSETOWN should be used instead. */ + case TIOCSPGRP: + error = fsetown(-(*(int *)addr), &d->bd_sigio); + break; + + /* This is deprecated, FIOGETOWN should be used instead. */ case TIOCGPGRP: - *(int *)addr = d->bd_pgid; + *(int *)addr = -fgetown(d->bd_sigio); break; case BIOCSRSIG: /* Set receive signal */ diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h index aa7f4622816c..03d0defa495d 100644 --- a/sys/net/bpfdesc.h +++ b/sys/net/bpfdesc.h @@ -37,7 +37,7 @@ * * @(#)bpfdesc.h 8.1 (Berkeley) 6/10/93 * - * $Id$ + * $Id: bpfdesc.h,v 1.10 1997/02/22 09:40:57 peter Exp $ */ #ifndef _NET_BPFDESC_H_ @@ -78,7 +78,7 @@ struct bpf_d { 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; /* information for SIGIO */ #if BSD < 199103 u_char bd_selcoll; /* true if selects collide */ int bd_timedout; diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index e00ce0c5bd3d..d62488ff5b3f 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #ifdef DEVFS @@ -215,7 +216,7 @@ tunclose(dev, foo, bar, p) } 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,12 +373,8 @@ tunoutput(ifp, m0, dst, rt) 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 +431,22 @@ tunioctl(dev, cmd, data, flag, p) *(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); + + /* This is deprecated, FIOSETOWN should be used instead. */ case TIOCSPGRP: - tp->tun_pgrp = *(int *)data; - break; + return (fsetown(-(*(int *)data), &tp->tun_sigio)); + + /* This is deprecated, FIOGETOWN should be used instead. */ case TIOCGPGRP: - *(int *)data = tp->tun_pgrp; - break; + *(int *)data = -fgetown(tp->tun_sigio); + return (0); + default: return (ENOTTY); } diff --git a/sys/net/if_tunvar.h b/sys/net/if_tunvar.h index c44911bcc15c..d0ef510e98d9 100644 --- a/sys/net/if_tunvar.h +++ b/sys/net/if_tunvar.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id:$ + * $Id: if_tunvar.h,v 1.1 1998/01/11 17:52:33 brian Exp $ */ #ifndef _NET_IF_TUNVAR_H_ @@ -42,7 +42,7 @@ struct tun_softc { #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; /* information for SIGIO */ struct selinfo tun_rsel; /* read select */ struct selinfo tun_wsel; /* write select (not used) */ }; diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index 444c3ef139a7..6d3fb26c7e3e 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -31,12 +31,14 @@ * SUCH DAMAGE. * * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 - * $Id: filedesc.h,v 1.12 1997/10/12 20:25:57 phk Exp $ + * $Id: filedesc.h,v 1.13 1997/12/05 18:58:10 bde Exp $ */ #ifndef _SYS_FILEDESC_H_ #define _SYS_FILEDESC_H_ +#include + /* * This structure is used for the management of descriptors. It may be * shared by multiple processes. @@ -91,6 +93,30 @@ struct filedesc0 { */ #define OFILESIZE (sizeof(struct file *) + sizeof(char)) +/* + * This structure that holds the information needed to send a SIGIO or + * a SIGURG signal to a process or process group when new data arrives + * on a device or socket. The 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 to this structure */ + 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. @@ -109,6 +135,10 @@ void fdcloseexec __P((struct proc *p)); int getvnode __P((struct filedesc *fdp, int fd, struct file **fpp)); int fdissequential __P((struct file *)); void fdsequential __P((struct file *, int)); +pid_t fgetown __P((struct sigio *)); +int fsetown __P((pid_t, struct sigio **)); +void funsetown __P((struct sigio *)); +void funsetownlst __P((struct sigiolst *)); #endif #endif diff --git a/sys/sys/pipe.h b/sys/sys/pipe.h index 7454cdf7a3ba..064334d689b0 100644 --- a/sys/sys/pipe.h +++ b/sys/sys/pipe.h @@ -18,7 +18,7 @@ * 5. Modifications may be freely made to this file if the above conditions * are met. * - * $Id: pipe.h,v 1.9 1997/04/09 16:53:45 bde Exp $ + * $Id: pipe.h,v 1.10 1998/03/26 20:53:26 phk Exp $ */ #ifndef _SYS_PIPE_H_ @@ -102,7 +102,7 @@ struct pipe { 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; /* information for SIGIO */ 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 */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 635832291d02..82cc217ab2e2 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)proc.h 8.15 (Berkeley) 5/19/95 - * $Id: proc.h,v 1.58 1998/05/28 09:30:26 phk Exp $ + * $Id: proc.h,v 1.59 1998/11/09 15:08:04 truckman Exp $ */ #ifndef _SYS_PROC_H_ @@ -52,6 +52,7 @@ #endif #include #include +#include /* For struct sigiolst */ /* * One structure allocated per session. @@ -72,6 +73,7 @@ struct pgrp { 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 */ }; @@ -161,6 +163,7 @@ struct proc { 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 diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 3976a4fd2ea3..1ca6bedb2e76 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)signalvar.h 8.6 (Berkeley) 2/19/95 - * $Id: signalvar.h,v 1.18 1998/03/28 10:33:23 bde Exp $ + * $Id: signalvar.h,v 1.19 1998/09/14 05:36:51 jdp Exp $ */ #ifndef _SYS_SIGNALVAR_H_ /* tmp for user.h */ @@ -152,6 +152,7 @@ static int sigprop[NSIG + 1] = { #ifdef KERNEL struct pgrp; struct proc; +struct sigio; extern int sugid_coredump; /* Sysctl variable kern.sugid_coredump */ @@ -163,6 +164,7 @@ char *expand_name __P((const char*, int, int)); void gsignal __P((int pgid, int sig)); int issignal __P((struct proc *p)); void killproc __P((struct proc *p, char *why)); +void pgsigio __P((struct sigio *, int signum, int checkctty)); void pgsignal __P((struct pgrp *pgrp, int sig, int checkctty)); void postsig __P((int sig)); void psignal __P((struct proc *p, int sig)); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 3a53ca7777a2..05cd6961b2e4 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 - * $Id: socketvar.h,v 1.29 1998/08/23 03:07:17 wollman Exp $ + * $Id: socketvar.h,v 1.30 1998/11/05 14:28:25 dg Exp $ */ #ifndef _SYS_SOCKETVAR_H_ @@ -77,7 +77,7 @@ struct socket { 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; /* information for SIGIO/SIGURG */ u_long so_oobmark; /* chars to oob mark */ /* * Variables for socket buffering. diff --git a/sys/sys/tty.h b/sys/sys/tty.h index d3dd4df6bbf3..3caca7e195b4 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)tty.h 8.6 (Berkeley) 1/21/94 - * $Id: tty.h,v 1.41 1998/03/07 15:36:25 bde Exp $ + * $Id: tty.h,v 1.42 1998/06/07 17:13:04 dfr Exp $ */ #ifndef _SYS_TTY_H_ @@ -79,6 +79,7 @@ struct tty { int t_timeout; /* Timeout for ttywait() */ struct pgrp *t_pgrp; /* Foreground process group. */ struct session *t_session; /* Enclosing session. */ + struct sigio *t_sigio; /* information for SIGIO */ struct selinfo t_rsel; /* Tty read/oob select. */ struct selinfo t_wsel; /* Tty write select. */ struct termios t_termios; /* Termios state. */