Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Sep 1998 23:10:01 -0700 (PDT)
From:      Don Lewis <Don.Lewis@tsc.tdk.com>
To:        freebsd-bugs@FreeBSD.ORG
Subject:   Re: kern/7899: [PATCH] [SECURITY] SETOWN allows bypass of signal credential checks and has other bugs
Message-ID:  <199809140610.XAA07048@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/7899; it has been noted by GNATS.

From: Don Lewis <Don.Lewis@tsc.tdk.com>
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, <bde@zeta.org.au>, 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 <sys/systm.h>
  #include <sys/sysproto.h>
  #include <sys/conf.h>
 -#include <sys/filedesc.h>
  #include <sys/kernel.h>
  #include <sys/sysctl.h>
  #include <sys/vnode.h>
 @@ -58,6 +57,7 @@
  #include <sys/ttycom.h>
  #include <sys/fcntl.h>
  #include <sys/malloc.h>
 +#include <sys/filedesc.h>
  #include <sys/unistd.h>
  #include <sys/resourcevar.h>
  #include <sys/pipe.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 @@
  		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 <vm/vm_map.h>
  #include <sys/user.h>
  #include <vm/vm_zone.h>
 +#include <sys/filedesc.h>
  
  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 <sys/signalvar.h>
  #include <sys/kernel.h>
  #include <sys/poll.h>
 +#include <sys/filedesc.h>
  #ifdef DEVFS
  #include <sys/devfsext.h>
  #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 <sys/sockio.h>
  #include <sys/stat.h>
  #include <sys/uio.h>
 +#include <sys/filedesc.h>
  
  #include <net/if.h>
  #include <net/route.h>
 @@ -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 <sys/signalvar.h>
  #include <sys/resourcevar.h>
  #include <sys/malloc.h>
 +#include <sys/filedesc.h>		/* get fsetown, funsetown, fgetown */
  #if NSNP > 0
  #include <sys/snoop.h>
  #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 <sys/filio.h>
  #include <sys/sockio.h>
  #include <sys/ttycom.h>
 +#include <sys/filedesc.h>	/* get fsetown, funsetown, fgetown */
  
  #if defined(sparc) && BSD < 199103
  #include <sys/stream.h>
 @@ -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 <sys/ttycom.h>
  #include <sys/poll.h>
  #include <sys/signalvar.h>
 +#include <sys/filedesc.h>
  #include <sys/kernel.h>
  #include <sys/sysctl.h>
  #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 <sys/queue.h>			/* 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 <sys/ucred.h>
  #include <sys/queue.h>
 +#include <sys/filedesc.h>		/* 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



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