diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-02-14 09:46:22 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-02-14 09:46:22 +0000 |
commit | 58933502fc90b2a07cab7800af4d0011c1af53a9 (patch) | |
tree | a1fd5078c1172baf93afa556370494cba2f62efd /sys/kern | |
parent | c273f009fba9f1ea033d1f358126da8a8af45b98 (diff) |
Wrap the NET_LOCK() into a per-socket solock() that does nothing for
unix domain sockets.
This should prevent the multiple deadlock related to unix domain sockets.
Inputs from millert@ and bluhm@, ok bluhm@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/sys_socket.c | 10 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 131 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 49 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 26 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 31 |
5 files changed, 132 insertions, 115 deletions
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 5e969cd8164..c8dbe8724a6 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_socket.c,v 1.28 2017/01/31 12:16:20 mpi Exp $ */ +/* $OpenBSD: sys_socket.c,v 1.29 2017/02/14 09:46:21 mpi Exp $ */ /* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */ /* @@ -127,10 +127,10 @@ soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p) } if (IOCGROUP(cmd) == 'r') return (EOPNOTSUPP); - NET_LOCK(s); + s = solock(so); error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)NULL, p)); - NET_UNLOCK(s); + sounlock(s); return (error); } @@ -187,10 +187,10 @@ soo_stat(struct file *fp, struct stat *ub, struct proc *p) ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; ub->st_uid = so->so_euid; ub->st_gid = so->so_egid; - NET_LOCK(s); + s = solock(so); (void) ((*so->so_proto->pr_usrreq)(so, PRU_SENSE, (struct mbuf *)ub, NULL, NULL, p)); - NET_UNLOCK(s); + sounlock(s); return (0); } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 0619f25143e..a12d868e2cd 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.176 2017/02/01 20:59:47 dhill Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.177 2017/02/14 09:46:21 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -135,16 +135,16 @@ socreate(int dom, struct socket **aso, int type, int proto) so->so_egid = p->p_ucred->cr_gid; so->so_cpid = p->p_p->ps_pid; so->so_proto = prp; - NET_LOCK(s); + s = solock(so); error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL, (struct mbuf *)(long)proto, NULL, p); if (error) { so->so_state |= SS_NOFDREF; sofree(so); - NET_UNLOCK(s); + sounlock(s); return (error); } - NET_UNLOCK(s); + sounlock(s); *aso = so; return (0); } @@ -154,9 +154,9 @@ sobind(struct socket *so, struct mbuf *nam, struct proc *p) { int s, error; - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, p); - NET_UNLOCK(s); + sounlock(s); return (error); } @@ -171,11 +171,11 @@ solisten(struct socket *so, int backlog) if (isspliced(so) || issplicedback(so)) return (EOPNOTSUPP); #endif /* SOCKET_SPLICE */ - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, NULL, NULL, curproc); if (error) { - NET_UNLOCK(s); + sounlock(s); return (error); } if (TAILQ_FIRST(&so->so_q) == NULL) @@ -185,14 +185,14 @@ solisten(struct socket *so, int backlog) if (backlog < sominconn) backlog = sominconn; so->so_qlimit = backlog; - NET_UNLOCK(s); + sounlock(s); return (0); } void sofree(struct socket *so) { - NET_ASSERT_LOCKED(); + soassertlocked(so); if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; @@ -232,7 +232,7 @@ soclose(struct socket *so) struct socket *so2; int s, error = 0; - NET_LOCK(s); + s = solock(so); if (so->so_options & SO_ACCEPTCONN) { while ((so2 = TAILQ_FIRST(&so->so_q0)) != NULL) { (void) soqremque(so2, 0); @@ -256,7 +256,7 @@ soclose(struct socket *so) (so->so_state & SS_NBIO)) goto drop; while (so->so_state & SS_ISCONNECTED) { - error = rwsleep(&so->so_timeo, &netlock, + error = sosleep(so, &so->so_timeo, PSOCK | PCATCH, "netcls", so->so_linger * hz); if (error) @@ -276,14 +276,14 @@ discard: panic("soclose NOFDREF: so %p, so_type %d", so, so->so_type); so->so_state |= SS_NOFDREF; sofree(so); - NET_UNLOCK(s); + sounlock(s); return (error); } int soabort(struct socket *so) { - NET_ASSERT_LOCKED(); + soassertlocked(so); return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL, NULL, NULL, curproc); @@ -294,7 +294,7 @@ soaccept(struct socket *so, struct mbuf *nam) { int error = 0; - NET_ASSERT_LOCKED(); + soassertlocked(so); if ((so->so_state & SS_NOFDREF) == 0) panic("soaccept !NOFDREF: so %p, so_type %d", so, so->so_type); @@ -315,7 +315,7 @@ soconnect(struct socket *so, struct mbuf *nam) if (so->so_options & SO_ACCEPTCONN) return (EOPNOTSUPP); - NET_LOCK(s); + s = solock(so); /* * If protocol is connection-based, can only connect once. * Otherwise, if connected, try to disconnect first. @@ -329,7 +329,7 @@ soconnect(struct socket *so, struct mbuf *nam) else error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, NULL, nam, NULL, curproc); - NET_UNLOCK(s); + sounlock(s); return (error); } @@ -338,10 +338,10 @@ soconnect2(struct socket *so1, struct socket *so2) { int s, error; - NET_LOCK(s); + s = solock(so1); error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, NULL, (struct mbuf *)so2, NULL, curproc); - NET_UNLOCK(s); + sounlock(s); return (error); } @@ -350,7 +350,7 @@ sodisconnect(struct socket *so) { int error; - NET_ASSERT_LOCKED(); + soassertlocked(so); if ((so->so_state & SS_ISCONNECTED) == 0) return (ENOTCONN); @@ -418,14 +418,14 @@ sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, (sizeof(struct fdpass) / sizeof(int))); } -#define snderr(errno) { error = errno; NET_UNLOCK(s); goto release; } +#define snderr(errno) { error = errno; sounlock(s); goto release; } restart: if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags), NULL)) != 0) goto out; so->so_state |= SS_ISSENDING; do { - NET_LOCK(s); + s = solock(so); if (so->so_state & SS_CANTSENDMORE) snderr(EPIPE); if (so->so_error) { @@ -453,14 +453,14 @@ restart: if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) snderr(EWOULDBLOCK); sbunlock(&so->so_snd); - error = sbwait(&so->so_snd); + error = sbwait(so, &so->so_snd); so->so_state &= ~SS_ISSENDING; - NET_UNLOCK(s); + sounlock(s); if (error) goto out; goto restart; } - NET_UNLOCK(s); + sounlock(s); space -= clen; do { if (uio == NULL) { @@ -480,13 +480,13 @@ restart: if (flags & MSG_EOR) top->m_flags |= M_EOR; } - NET_LOCK(s); + s = solock(so); if (resid == 0) so->so_state &= ~SS_ISSENDING; error = (*so->so_proto->pr_usrreq)(so, (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, top, addr, control, curproc); - NET_UNLOCK(s); + sounlock(s); clen = 0; control = NULL; top = NULL; @@ -615,7 +615,7 @@ sbsync(struct sockbuf *sb, struct mbuf *nextrecord) * followed by an optional mbuf or mbufs containing ancillary data, * and then zero or more mbufs of data. * In order to avoid blocking network for the entire time here, we release - * the NET_LOCK() while doing the actual copy to user space. + * the solock() while doing the actual copy to user space. * Although the sockbuf is locked, new data may still be appended, * and thus we must maintain consistency of the sockbuf during that time. * @@ -649,10 +649,10 @@ soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, flags |= MSG_DONTWAIT; if (flags & MSG_OOB) { m = m_get(M_WAIT, MT_DATA); - NET_LOCK(s); + s = solock(so); error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, (struct mbuf *)(long)(flags & MSG_PEEK), NULL, curproc); - NET_UNLOCK(s); + sounlock(s); if (error) goto bad; do { @@ -670,7 +670,7 @@ bad: restart: if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags), NULL)) != 0) return (error); - NET_LOCK(s); + s = solock(so); m = so->so_rcv.sb_mb; #ifdef SOCKET_SPLICE @@ -734,8 +734,8 @@ restart: SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); sbunlock(&so->so_rcv); - error = sbwait(&so->so_rcv); - NET_UNLOCK(s); + error = sbwait(so, &so->so_rcv); + sounlock(s); if (error) return (error); goto restart; @@ -801,11 +801,9 @@ dontblock: if (pr->pr_domain->dom_externalize && mtod(cm, struct cmsghdr *)->cmsg_type == SCM_RIGHTS) { - NET_UNLOCK(s); error = (*pr->pr_domain->dom_externalize) (cm, controllen, flags); - NET_LOCK(s); } *controlp = cm; } else { @@ -873,9 +871,9 @@ dontblock: SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove"); SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); resid = uio->uio_resid; - NET_UNLOCK(s); + sounlock(s); uio_error = uiomove(mtod(m, caddr_t) + moff, len, uio); - NET_LOCK(s); + s = solock(so); if (uio_error) uio->uio_resid = resid - len; } else @@ -954,10 +952,10 @@ dontblock: break; SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); - error = sbwait(&so->so_rcv); + error = sbwait(so, &so->so_rcv); if (error) { sbunlock(&so->so_rcv); - NET_UNLOCK(s); + sounlock(s); return (0); } if ((m = so->so_rcv.sb_mb) != NULL) @@ -993,7 +991,7 @@ dontblock: if (orig_resid == uio->uio_resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { sbunlock(&so->so_rcv); - NET_UNLOCK(s); + sounlock(s); goto restart; } @@ -1004,7 +1002,7 @@ dontblock: *flagsp |= flags; release: sbunlock(&so->so_rcv); - NET_UNLOCK(s); + sounlock(s); return (error); } @@ -1014,7 +1012,7 @@ soshutdown(struct socket *so, int how) struct protosw *pr = so->so_proto; int s, error = 0; - NET_LOCK(s); + s = solock(so); switch (how) { case SHUT_RD: case SHUT_RDWR: @@ -1030,7 +1028,7 @@ soshutdown(struct socket *so, int how) error = EINVAL; break; } - NET_UNLOCK(s); + sounlock(s); return (error); } @@ -1043,7 +1041,8 @@ sorflush(struct socket *so) struct sockbuf asb; sb->sb_flags |= SB_NOINTR; - (void) sblock(sb, M_WAITOK, &netlock); + sblock(sb, M_WAITOK, + (pr->pr_domain->dom_family != PF_LOCAL) ? &netlock : NULL); socantrcvmore(so); sbunlock(sb); asb = *sb; @@ -1094,10 +1093,10 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv) if ((error = sblock(&so->so_rcv, (so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK, NULL)) != 0) return (error); - NET_LOCK(s); + s = solock(so); if (so->so_sp->ssp_socket) sounsplice(so, so->so_sp->ssp_socket, 1); - NET_UNLOCK(s); + sounlock(s); sbunlock(&so->so_rcv); return (0); } @@ -1126,7 +1125,7 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv) FRELE(fp, curproc); return (error); } - NET_LOCK(s); + s = solock(so); if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) { error = EBUSY; @@ -1167,7 +1166,7 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv) } release: - NET_UNLOCK(s); + sounlock(s); sbunlock(&sosp->so_snd); sbunlock(&so->so_rcv); FRELE(fp, curproc); @@ -1177,7 +1176,7 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv) void sounsplice(struct socket *so, struct socket *sosp, int wakeup) { - NET_ASSERT_LOCKED(); + soassertlocked(so); task_del(sosplice_taskq, &so->so_splicetask); timeout_del(&so->so_idleto); @@ -1194,12 +1193,12 @@ soidle(void *arg) struct socket *so = arg; int s; - NET_LOCK(s); + s = solock(so); if (so->so_rcv.sb_flagsintr & SB_SPLICE) { so->so_error = ETIMEDOUT; sounsplice(so, so->so_sp->ssp_socket, 1); } - NET_UNLOCK(s); + sounlock(s); } void @@ -1208,7 +1207,7 @@ sotask(void *arg) struct socket *so = arg; int s; - NET_LOCK(s); + s = solock(so); if (so->so_rcv.sb_flagsintr & SB_SPLICE) { /* * We may not sleep here as sofree() and unsplice() may be @@ -1217,7 +1216,7 @@ sotask(void *arg) */ somove(so, M_DONTWAIT); } - NET_UNLOCK(s); + sounlock(s); /* Avoid user land starvation. */ yield(); @@ -1239,7 +1238,7 @@ somove(struct socket *so, int wait) int error = 0, maxreached = 0; short state; - NET_ASSERT_LOCKED(); + soassertlocked(so); nextpkt: if (so->so_error) { @@ -1509,7 +1508,7 @@ somove(struct socket *so, int wait) void sorwakeup(struct socket *so) { - NET_ASSERT_LOCKED(); + soassertlocked(so); #ifdef SOCKET_SPLICE if (so->so_rcv.sb_flagsintr & SB_SPLICE) { @@ -1541,7 +1540,7 @@ sorwakeup(struct socket *so) void sowwakeup(struct socket *so) { - NET_ASSERT_LOCKED(); + soassertlocked(so); #ifdef SOCKET_SPLICE if (so->so_snd.sb_flagsintr & SB_SPLICE) @@ -1558,10 +1557,10 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) if (level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) { - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, level, optname, m0); - NET_UNLOCK(s); + sounlock(s); return (error); } error = ENOPROTOOPT; @@ -1705,10 +1704,10 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) struct domain *dom = so->so_proto->pr_domain; level = dom->dom_protosw->pr_protocol; - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_ctloutput) (PRCO_SETOPT, so, level, optname, m0); - NET_UNLOCK(s); + sounlock(s); return (error); } error = ENOPROTOOPT; @@ -1737,10 +1736,10 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) break; } if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) { - NET_LOCK(s); + s = solock(so); (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, level, optname, m0); - NET_UNLOCK(s); + sounlock(s); m = NULL; /* freed by protocol */ } } @@ -1761,10 +1760,10 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) m = m_get(M_WAIT, MT_SOOPTS); m->m_len = 0; - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so, level, optname, m); - NET_UNLOCK(s); + sounlock(s); if (error) { m_free(m); return (error); @@ -1849,10 +1848,10 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) struct domain *dom = so->so_proto->pr_domain; level = dom->dom_protosw->pr_protocol; - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_ctloutput) (PRCO_GETOPT, so, level, optname, m); - NET_UNLOCK(s); + sounlock(s); if (error) { (void)m_free(m); return (error); diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index b991120eb7a..3a09b229477 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.71 2017/01/25 06:15:50 mpi Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.72 2017/02/14 09:46:21 mpi Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -38,6 +38,7 @@ #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/protosw.h> +#include <sys/domain.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/signalvar.h> @@ -147,7 +148,7 @@ sonewconn(struct socket *head, int connstatus) struct socket *so; int soqueue = connstatus ? 1 : 0; - NET_ASSERT_LOCKED(); + soassertlocked(head); if (mclpools[0].pr_nout > mclpools[0].pr_hardlimit * 95 / 100) return (NULL); @@ -267,16 +268,52 @@ socantrcvmore(struct socket *so) sorwakeup(so); } +int +solock(struct socket *so) +{ + int s; + + if (so->so_proto->pr_domain->dom_family != PF_LOCAL) + NET_LOCK(s); + else + s = -42; + + return (s); +} + +void +sounlock(int s) +{ + if (s != -42) + NET_UNLOCK(s); +} + +void +soassertlocked(struct socket *so) +{ + if (so->so_proto->pr_domain->dom_family != PF_LOCAL) + NET_ASSERT_LOCKED(); +} + +int +sosleep(struct socket *so, void *ident, int prio, const char *wmesg, int timo) +{ + if (so->so_proto->pr_domain->dom_family != PF_LOCAL) + return rwsleep(ident, &netlock, prio, wmesg, timo); + else + return tsleep(ident, prio, wmesg, timo); +} + /* * Wait for data to arrive at/drain from a socket buffer. */ int -sbwait(struct sockbuf *sb) +sbwait(struct socket *so, struct sockbuf *sb) { - NET_ASSERT_LOCKED(); + soassertlocked(so); sb->sb_flagsintr |= SB_WAIT; - return (rwsleep(&sb->sb_cc, &netlock, + return (sosleep(so, &sb->sb_cc, (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "netio", sb->sb_timeo)); } @@ -338,7 +375,7 @@ sbunlock(struct sockbuf *sb) void sowakeup(struct socket *so, struct sockbuf *sb) { - NET_ASSERT_LOCKED(); + soassertlocked(so); selwakeup(&sb->sb_sel); sb->sb_flagsintr &= ~SB_SEL; diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 40433a86527..c9ce131df23 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.149 2017/02/11 19:51:06 guenther Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.150 2017/02/14 09:46:21 mpi Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -285,9 +285,9 @@ doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, } nam = m_get(M_WAIT, MT_SONAME); - - NET_LOCK(s); + head = headfp->f_data; + s = solock(head); if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) { error = EINVAL; goto out; @@ -304,8 +304,8 @@ doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, head->so_error = ECONNABORTED; break; } - error = rwsleep(&head->so_timeo, &netlock, PSOCK | PCATCH, - "netcon", 0); + error = sosleep(head, &head->so_timeo, PSOCK | PCATCH, "netcon", + 0); if (error) goto out; } @@ -342,7 +342,7 @@ doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, *retval = tmpfd; } out: - NET_UNLOCK(s); + sounlock(s); m_freem(nam); if (error) { fdplock(fdp); @@ -406,9 +406,9 @@ sys_connect(struct proc *p, void *v, register_t *retval) m_freem(nam); return (EINPROGRESS); } - NET_LOCK(s); + s = solock(so); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - error = rwsleep(&so->so_timeo, &netlock, PSOCK | PCATCH, + error = sosleep(so, &so->so_timeo, PSOCK | PCATCH, "netcon2", 0); if (error) { if (error == EINTR || error == ERESTART) @@ -420,7 +420,7 @@ sys_connect(struct proc *p, void *v, register_t *retval) error = so->so_error; so->so_error = 0; } - NET_UNLOCK(s); + sounlock(s); bad: if (!interrupted) so->so_state &= ~SS_ISCONNECTING; @@ -1044,9 +1044,9 @@ sys_getsockname(struct proc *p, void *v, register_t *retval) if (error) goto bad; m = m_getclr(M_WAIT, MT_SONAME); - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p); - NET_UNLOCK(s); + sounlock(s); if (error) goto bad; error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); @@ -1087,9 +1087,9 @@ sys_getpeername(struct proc *p, void *v, register_t *retval) if (error) goto bad; m = m_getclr(M_WAIT, MT_SONAME); - NET_LOCK(s); + s = solock(so); error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p); - NET_UNLOCK(s); + sounlock(s); if (error) goto bad; error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 0c1819b5c35..01fee7121f8 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.115 2017/02/09 11:18:55 mpi Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.116 2017/02/14 09:46:21 mpi Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -121,6 +121,9 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, error = EINVAL; goto release; } + + NET_ASSERT_UNLOCKED(); + switch (req) { case PRU_ATTACH: @@ -132,17 +135,11 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, break; case PRU_DETACH: - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); unp_detach(unp); - rw_enter_write(&netlock); break; case PRU_BIND: - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); error = unp_bind(unp, nam, p); - rw_enter_write(&netlock); break; case PRU_LISTEN: @@ -151,10 +148,7 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, break; case PRU_CONNECT: - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); error = unp_connect(so, nam, p); - rw_enter_write(&netlock); break; case PRU_CONNECT2: @@ -222,10 +216,7 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, error = EISCONN; break; } - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); error = unp_connect(so, nam, p); - rw_enter_write(&netlock); if (error) break; } else { @@ -398,8 +389,6 @@ unp_detach(struct unpcb *unp) { struct vnode *vp; - NET_ASSERT_UNLOCKED(); - LIST_REMOVE(unp, unp_link); if (unp->unp_vnode) { unp->unp_vnode->v_socket = NULL; @@ -411,10 +400,7 @@ unp_detach(struct unpcb *unp) unp_disconnect(unp); while (!SLIST_EMPTY(&unp->unp_refs)) unp_drop(SLIST_FIRST(&unp->unp_refs), ECONNRESET); - /* XXXSMP The assert is wrong */ - rw_enter_write(&netlock); soisdisconnected(unp->unp_socket); - rw_exit_write(&netlock); unp->unp_socket->so_pcb = NULL; m_freem(unp->unp_addr); free(unp, M_PCB, sizeof *unp); @@ -505,9 +491,7 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) struct socket *so2, *so3; struct unpcb *unp, *unp2, *unp3; struct nameidata nd; - int error, s; - - NET_ASSERT_UNLOCKED(); + int error; if (soun->sun_family != AF_UNIX) return (EAFNOSUPPORT); @@ -539,12 +523,11 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) error = EPROTOTYPE; goto bad; } - NET_LOCK(s); if (so->so_proto->pr_flags & PR_CONNREQUIRED) { if ((so2->so_options & SO_ACCEPTCONN) == 0 || (so3 = sonewconn(so2, 0)) == 0) { error = ECONNREFUSED; - goto unlock; + goto bad; } unp = sotounpcb(so); unp2 = sotounpcb(so2); @@ -563,8 +546,6 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) } } error = unp_connect2(so, so2); -unlock: - NET_UNLOCK(s); bad: vput(vp); return (error); |