diff options
author | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2021-12-07 01:19:48 +0000 |
---|---|---|
committer | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2021-12-07 01:19:48 +0000 |
commit | 8555e51e3db8c3e12459dddbfa6e478b93e55bc3 (patch) | |
tree | 9cfefaf5cff034a9d52bec54f25f5962905b9d87 /sys/kern | |
parent | feaea13e9b89c8f232384c72e9d8368e2486d087 (diff) |
Make `unp_msgcount' and `unp_file' protection with `unp_gc_lock'
rwlock(9).
This save us from from races provided by unlocked access to the `f_count'
which cause false marking alive socket as dead. We always modify `f_count'
and `unp_msgcount' together so the `f_count' modification should also pass
the `unp_gc_rwlock' before `unp_msgcount' increment and after
`unp_msgcount' decrement. The locked `unp_file' assignment avoids us from
drain unp_gc() run.
This moves unp_gc() locking back when these wariables were protected with
the same lock which was taken for all garbage collector run but uses
another lock not `unp_lock'.
ok kettenis@ bluhm@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 1c0a4454458..7cb3cc39494 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.158 2021/11/17 22:56:19 mvs Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.159 2021/12/07 01:19:47 mvs Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -960,8 +960,11 @@ restart: fp = rp->fp; rp++; - if ((unp = fptounp(fp)) != NULL) - atomic_dec_long(&unp->unp_msgcount); + if ((unp = fptounp(fp)) != NULL) { + rw_enter_write(&unp_gc_lock); + unp->unp_msgcount--; + rw_exit_write(&unp_gc_lock); + } } mtx_enter(&unp_rights_mtx); @@ -1085,8 +1088,10 @@ morespace: rp->flags = fdp->fd_ofileflags[fd] & UF_PLEDGED; rp--; if ((unp = fptounp(fp)) != NULL) { - atomic_inc_long(&unp->unp_msgcount); + rw_enter_write(&unp_gc_lock); + unp->unp_msgcount++; unp->unp_file = fp; + rw_exit_write(&unp_gc_lock); } } fdpunlock(fdp); @@ -1099,8 +1104,11 @@ fail: for ( ; i > 0; i--) { rp++; fp = rp->fp; - if ((unp = fptounp(fp)) != NULL) - atomic_dec_long(&unp->unp_msgcount); + if ((unp = fptounp(fp)) != NULL) { + rw_enter_write(&unp_gc_lock); + unp->unp_msgcount--; + rw_exit_write(&unp_gc_lock); + } FRELE(fp, p); } @@ -1136,8 +1144,11 @@ unp_gc(void *arg __unused) fp = defer->ud_fp[i].fp; if (fp == NULL) continue; - if ((unp = fptounp(fp)) != NULL) - atomic_dec_long(&unp->unp_msgcount); + if ((unp = fptounp(fp)) != NULL) { + rw_enter_write(&unp_gc_lock); + unp->unp_msgcount--; + rw_exit_write(&unp_gc_lock); + } mtx_enter(&unp_rights_mtx); unp_rights--; mtx_leave(&unp_rights_mtx); |