diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2021-10-24 07:02:48 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2021-10-24 07:02:48 +0000 |
commit | 5c59fd748e54b73743cd348940723ae3ae61a903 (patch) | |
tree | d658047149ce21a3131a02a3435316fd54474e2c /sys/kern | |
parent | 50bf60990b76f89bcfab0921ae44a6bc9f04d3b1 (diff) |
Set klist lock for sockets to make socket event filters MP-safe
The filterops instances already provide f_modify and f_process
callbacks with proper internal locking. Locking of socket klists
has been the missing detail for MP-safety.
OK mpi@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/uipc_socket.c | 58 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 6 |
2 files changed, 50 insertions, 14 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index afab85de1ee..f0d7046c40c 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.266 2021/10/22 15:11:32 mpi Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.267 2021/10/24 07:02:47 visa Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -88,7 +88,7 @@ int filt_solistenprocess(struct knote *kn, struct kevent *kev); int filt_solisten_common(struct knote *kn, struct socket *so); const struct filterops solisten_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_solisten, @@ -97,7 +97,7 @@ const struct filterops solisten_filtops = { }; const struct filterops soread_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_soread, @@ -106,7 +106,7 @@ const struct filterops soread_filtops = { }; const struct filterops sowrite_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sowdetach, .f_event = filt_sowrite, @@ -115,7 +115,7 @@ const struct filterops sowrite_filtops = { }; const struct filterops soexcept_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_soexcept, @@ -173,6 +173,8 @@ socreate(int dom, struct socket **aso, int type, int proto) return (EPROTOTYPE); so = pool_get(&socket_pool, PR_WAITOK | PR_ZERO); rw_init(&so->so_lock, "solock"); + klist_init(&so->so_rcv.sb_sel.si_note, &socket_klistops, so); + klist_init(&so->so_snd.sb_sel.si_note, &socket_klistops, so); sigio_init(&so->so_sigio); TAILQ_INIT(&so->so_q0); TAILQ_INIT(&so->so_q); @@ -262,6 +264,8 @@ sofree(struct socket *so, int s) } } sigio_free(&so->so_sigio); + klist_free(&so->so_rcv.sb_sel.si_note); + klist_free(&so->so_snd.sb_sel.si_note); #ifdef SOCKET_SPLICE if (so->so_sp) { if (issplicedback(so)) { @@ -2042,9 +2046,9 @@ soo_kqfilter(struct file *fp, struct knote *kn) { struct socket *so = kn->kn_fp->f_data; struct sockbuf *sb; + int s; - KERNEL_ASSERT_LOCKED(); - + s = solock(so); switch (kn->kn_filter) { case EVFILT_READ: if (so->so_options & SO_ACCEPTCONN) @@ -2062,10 +2066,12 @@ soo_kqfilter(struct file *fp, struct knote *kn) sb = &so->so_rcv; break; default: + sounlock(so, s); return (EINVAL); } klist_insert_locked(&sb->sb_sel.si_note, kn); + sounlock(so, s); return (0); } @@ -2075,9 +2081,7 @@ filt_sordetach(struct knote *kn) { struct socket *so = kn->kn_fp->f_data; - KERNEL_ASSERT_LOCKED(); - - klist_remove_locked(&so->so_rcv.sb_sel.si_note, kn); + klist_remove(&so->so_rcv.sb_sel.si_note, kn); } int @@ -2157,9 +2161,7 @@ filt_sowdetach(struct knote *kn) { struct socket *so = kn->kn_fp->f_data; - KERNEL_ASSERT_LOCKED(); - - klist_remove_locked(&so->so_snd.sb_sel.si_note, kn); + klist_remove(&so->so_snd.sb_sel.si_note, kn); } int @@ -2353,6 +2355,36 @@ filt_solistenprocess(struct knote *kn, struct kevent *kev) return (rv); } +void +klist_soassertlk(void *arg) +{ + struct socket *so = arg; + + soassertlocked(so); +} + +int +klist_solock(void *arg) +{ + struct socket *so = arg; + + return (solock(so)); +} + +void +klist_sounlock(void *arg, int ls) +{ + struct socket *so = arg; + + sounlock(so, ls); +} + +const struct klistops socket_klistops = { + .klo_assertlk = klist_soassertlk, + .klo_lock = klist_solock, + .klo_unlock = klist_sounlock, +}; + #ifdef DDB void sobuf_print(struct sockbuf *, diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index e387e4705f7..59229ef936d 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.113 2021/07/26 05:51:13 mpi Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.114 2021/10/24 07:02:47 visa Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -189,6 +189,8 @@ sonewconn(struct socket *head, int connstatus) so->so_rcv.sb_lowat = head->so_rcv.sb_lowat; so->so_rcv.sb_timeo_nsecs = head->so_rcv.sb_timeo_nsecs; + klist_init(&so->so_rcv.sb_sel.si_note, &socket_klistops, so); + klist_init(&so->so_snd.sb_sel.si_note, &socket_klistops, so); sigio_init(&so->so_sigio); sigio_copy(&so->so_sigio, &head->so_sigio); @@ -196,6 +198,8 @@ sonewconn(struct socket *head, int connstatus) if ((*so->so_proto->pr_attach)(so, 0)) { (void) soqremque(so, soqueue); sigio_free(&so->so_sigio); + klist_free(&so->so_rcv.sb_sel.si_note); + klist_free(&so->so_snd.sb_sel.si_note); pool_put(&socket_pool, so); return (NULL); } |