summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorVitaliy Makkoveev <mvs@cvs.openbsd.org>2021-12-07 01:19:48 +0000
committerVitaliy Makkoveev <mvs@cvs.openbsd.org>2021-12-07 01:19:48 +0000
commit8555e51e3db8c3e12459dddbfa6e478b93e55bc3 (patch)
tree9cfefaf5cff034a9d52bec54f25f5962905b9d87 /sys/kern
parentfeaea13e9b89c8f232384c72e9d8368e2486d087 (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.c27
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);