diff options
author | green <green@FreeBSD.org> | 2000-08-29 11:28:06 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2000-08-29 11:28:06 +0000 |
commit | 0fa5ae2859837ce45dfa1d212731cbed7a6bf037 (patch) | |
tree | a0487072d9e3fda944c9970116207cd67e21e923 /sys/kern/uipc_usrreq.c | |
parent | 0290d697a80874eccbc3e0228ae5f2acb2b7522c (diff) | |
download | FreeBSD-src-0fa5ae2859837ce45dfa1d212731cbed7a6bf037.zip FreeBSD-src-0fa5ae2859837ce45dfa1d212731cbed7a6bf037.tar.gz |
Remove any possibility of hiwat-related race conditions by changing
the chgsbsize() call to use a "subject" pointer (&sb.sb_hiwat) and
a u_long target to set it to. The whole thing is splnet().
This fixes a problem that jdp has been able to provoke.
Diffstat (limited to 'sys/kern/uipc_usrreq.c')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index a0b4072..c4a3326 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -217,6 +217,7 @@ uipc_rcvd(struct socket *so, int flags) { struct unpcb *unp = sotounpcb(so); struct socket *so2; + u_long newhiwat; if (unp == 0) return EINVAL; @@ -235,9 +236,10 @@ uipc_rcvd(struct socket *so, int flags) */ so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt; unp->unp_mbcnt = so->so_rcv.sb_mbcnt; - so2->so_snd.sb_hiwat += unp->unp_cc - so->so_rcv.sb_cc; - (void)chgsbsize(so2->so_cred->cr_uid, - (rlim_t)unp->unp_cc - so->so_rcv.sb_cc, RLIM_INFINITY); + newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - + so->so_rcv.sb_cc; + (void)chgsbsize(so2->so_cred->cr_uid, &so2->so_snd.sb_hiwat, + newhiwat, RLIM_INFINITY); unp->unp_cc = so->so_rcv.sb_cc; sowwakeup(so2); break; @@ -257,6 +259,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, int error = 0; struct unpcb *unp = sotounpcb(so); struct socket *so2; + u_long newhiwat; if (unp == 0) { error = EINVAL; @@ -342,10 +345,10 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, so->so_snd.sb_mbmax -= so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt; unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt; - so->so_snd.sb_hiwat -= - so2->so_rcv.sb_cc - unp->unp_conn->unp_cc; - (void)chgsbsize(so->so_cred->cr_uid, - (rlim_t)unp->unp_conn->unp_cc - so2->so_rcv.sb_cc, RLIM_INFINITY); + newhiwat = so->so_snd.sb_hiwat - + (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc); + (void)chgsbsize(so->so_cred->cr_uid, &so->so_snd.sb_hiwat, + newhiwat, RLIM_INFINITY); unp->unp_conn->unp_cc = so2->so_rcv.sb_cc; sorwakeup(so2); m = 0; |