Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/uipc_socket.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/uipc_socket.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.192 retrieving revision 1.197 diff -u -p -r1.192 -r1.197 --- src/sys/kern/uipc_socket.c 2009/10/03 01:41:39 1.192 +++ src/sys/kern/uipc_socket.c 2009/12/29 03:48:18 1.197 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_socket.c,v 1.192 2009/10/03 01:41:39 elad Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.197 2009/12/29 03:48:18 elad Exp $ */ /*- * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -63,7 +63,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.192 2009/10/03 01:41:39 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.197 2009/12/29 03:48:18 elad Exp $"); #include "opt_compat_netbsd.h" #include "opt_sock_counters.h" @@ -386,7 +386,7 @@ sosend_loan(struct socket *so, struct ui for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE) pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]), - VM_PROT_READ); + VM_PROT_READ, 0); pmap_update(pmap_kernel()); lva += (vaddr_t) iov->iov_base & PAGE_MASK; @@ -440,10 +440,15 @@ socket_listener_cb(kauth_cred_t cred, ka result = KAUTH_RESULT_DEFER; req = (enum kauth_network_req)arg0; - if (action != KAUTH_NETWORK_SOCKET) + if ((action != KAUTH_NETWORK_SOCKET) && + (action != KAUTH_NETWORK_BIND)) return result; switch (req) { + case KAUTH_REQ_NETWORK_BIND_PORT: + result = KAUTH_RESULT_ALLOW; + break; + case KAUTH_REQ_NETWORK_SOCKET_DROP: { /* Normal users can only drop their own connections. */ struct socket *so = (struct socket *)arg1; @@ -556,7 +561,6 @@ socreate(int dom, struct socket **aso, i so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner; so->so_mowner = &prp->pr_domain->dom_mowner; #endif - /* so->so_cred = kauth_cred_dup(l->l_cred); */ uid = kauth_cred_geteuid(l->l_cred); so->so_uidinfo = uid_find(uid); so->so_egid = kauth_cred_getegid(l->l_cred); @@ -699,7 +703,6 @@ sofree(struct socket *so) /* Remove acccept filter if one is present. */ if (so->so_accf != NULL) (void)accept_filt_clear(so); - /* kauth_cred_free(so->so_cred); */ sounlock(so); if (refs == 0) /* XXX */ soput(so); @@ -900,6 +903,7 @@ sosend(struct socket *so, struct mbuf *a struct proc *p; long space, len, resid, clen, mlen; int error, s, dontroute, atomic; + short wakeup_state = 0; p = l->l_proc; sodopendfree(); @@ -974,11 +978,17 @@ sosend(struct socket *so, struct mbuf *a goto release; } sbunlock(&so->so_snd); + if (wakeup_state & SS_RESTARTSYS) { + error = ERESTART; + goto out; + } error = sbwait(&so->so_snd); if (error) goto out; + wakeup_state = so->so_state; goto restart; } + wakeup_state = 0; mp = ⊤ space -= clen; do { @@ -1154,6 +1164,7 @@ soreceive(struct socket *so, struct mbuf struct mbuf *nextrecord; int mbuf_removed = 0; const struct domain *dom; + short wakeup_state = 0; pr = so->so_proto; atomic = pr->pr_flags & PR_ATOMIC; @@ -1268,12 +1279,16 @@ soreceive(struct socket *so, struct mbuf SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); sbunlock(&so->so_rcv); - error = sbwait(&so->so_rcv); + if (wakeup_state & SS_RESTARTSYS) + error = ERESTART; + else + error = sbwait(&so->so_rcv); if (error != 0) { sounlock(so); splx(s); return error; } + wakeup_state = so->so_state; goto restart; } dontblock: @@ -1412,6 +1427,7 @@ soreceive(struct socket *so, struct mbuf panic("receive 3"); #endif so->so_state &= ~SS_RCVATMARK; + wakeup_state = 0; len = uio->uio_resid; if (so->so_oobmark && len > so->so_oobmark - offset) len = so->so_oobmark - offset; @@ -1544,7 +1560,10 @@ soreceive(struct socket *so, struct mbuf NULL, (struct mbuf *)(long)flags, NULL, l); SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); - error = sbwait(&so->so_rcv); + if (wakeup_state & SS_RESTARTSYS) + error = ERESTART; + else + error = sbwait(&so->so_rcv); if (error != 0) { sbunlock(&so->so_rcv); sounlock(so); @@ -1553,6 +1572,7 @@ soreceive(struct socket *so, struct mbuf } if ((m = so->so_rcv.sb_mb) != NULL) nextrecord = m->m_nextpkt; + wakeup_state = so->so_state; } } @@ -1619,18 +1639,23 @@ soshutdown(struct socket *so, int how) return error; } -int -sodrain(struct socket *so) +void +sorestart(struct socket *so) { - int error; - + /* + * An application has called close() on an fd on which another + * of its threads has called a socket system call. + * Mark this and wake everyone up, and code that would block again + * instead returns ERESTART. + * On system call re-entry the fd is validated and EBADF returned. + * Any other fd will block again on the 2nd syscall. + */ solock(so); - so->so_state |= SS_ISDRAINING; + so->so_state |= SS_RESTARTSYS; cv_broadcast(&so->so_cv); - error = soshutdown(so, SHUT_RDWR); + cv_broadcast(&so->so_snd.sb_cv); + cv_broadcast(&so->so_rcv.sb_cv); sounlock(so); - - return error; } void