We can't call fsetown() from sonewconn() because sonewconn() is be called

from an interrupt context and fsetown() wants to peek at curproc, call
malloc(..., M_WAITOK), and fiddle with various unprotected data structures.
The fix is to move the code that duplicates the F_SETOWN/FIOSETOWN state
of the original socket to the new socket from sonewconn() to accept1(),
since accept1() runs in the correct context.  Deferring this until the
process calls accept() is harmless since the process can't do anything
useful with SIGIO on the new socket until it has the descriptor for that
socket.

One could make the case for not bothering to duplicate the
F_SETOWN/FIOSETOWN state and requiring the process to explicitly make the
fcntl() or ioctl() call on the new socket, but this would be incompatible
with the previous implementation and might break programs which rely on
the old semantics.

This bug was discovered by Andrew Gallatin <gallatin@cs.duke.edu>.
This commit is contained in:
Don Lewis 1998-11-23 00:45:39 +00:00
parent 22b9c86cfd
commit 9d2b090975
3 changed files with 5 additions and 5 deletions

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
* $Id: uipc_socket2.c,v 1.40 1998/11/04 20:22:11 fenner Exp $
* $Id: uipc_socket2.c,v 1.41 1998/11/11 10:03:56 truckman Exp $
*/
#include <sys/param.h>
@ -213,7 +213,6 @@ sonewconn(head, connstatus)
so->so_state = head->so_state | SS_NOFDREF;
so->so_proto = head->so_proto;
so->so_timeo = head->so_timeo;
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);

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
* $Id: uipc_socket2.c,v 1.40 1998/11/04 20:22:11 fenner Exp $
* $Id: uipc_socket2.c,v 1.41 1998/11/11 10:03:56 truckman Exp $
*/
#include <sys/param.h>
@ -213,7 +213,6 @@ sonewconn(head, connstatus)
so->so_state = head->so_state | SS_NOFDREF;
so->so_proto = head->so_proto;
so->so_timeo = head->so_timeo;
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);

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
* $Id: uipc_syscalls.c,v 1.45 1998/11/15 16:55:09 dg Exp $
* $Id: uipc_syscalls.c,v 1.46 1998/11/18 09:00:47 dg Exp $
*/
#include "opt_compat.h"
@ -260,6 +260,8 @@ accept1(p, uap, compat)
so->so_state &= ~SS_COMP;
so->so_head = NULL;
if (head->so_sigio != NULL)
fsetown(fgetown(head->so_sigio), &so->so_sigio);
fp->f_type = DTYPE_SOCKET;
fp->f_flag = fflag;