From 8e156a1d42b515fc5dabbc32b7b65838ef5e3ba1 Mon Sep 17 00:00:00 2001 From: visa Date: Sun, 24 Oct 2021 07:02:47 +0000 Subject: [PATCH] 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@ --- sys/kern/uipc_socket.c | 58 ++++++++++++++++++++++++++-------- sys/kern/uipc_socket2.c | 6 +++- sys/miscfs/fifofs/fifo_vnops.c | 12 +++---- sys/sys/event.h | 3 +- 4 files changed, 58 insertions(+), 21 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); } diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c index 6aa0c3284e2..d6fc18692e6 100644 --- a/sys/miscfs/fifofs/fifo_vnops.c +++ b/sys/miscfs/fifofs/fifo_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fifo_vnops.c,v 1.83 2021/10/22 15:11:32 mpi Exp $ */ +/* $OpenBSD: fifo_vnops.c,v 1.84 2021/10/24 07:02:47 visa Exp $ */ /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ /* @@ -118,7 +118,7 @@ int filt_fifoexceptprocess(struct knote *kn, struct kevent *kev); int filt_fifoexcept_common(struct knote *kn, struct socket *so); const struct filterops fiforead_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_fifordetach, .f_event = filt_fiforead, @@ -127,7 +127,7 @@ const struct filterops fiforead_filtops = { }; const struct filterops fifowrite_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_fifowdetach, .f_event = filt_fifowrite, @@ -546,7 +546,7 @@ fifo_kqfilter(void *v) ap->a_kn->kn_hook = so; - klist_insert_locked(&sb->sb_sel.si_note, ap->a_kn); + klist_insert(&sb->sb_sel.si_note, ap->a_kn); return (0); } @@ -556,7 +556,7 @@ filt_fifordetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_hook; - klist_remove_locked(&so->so_rcv.sb_sel.si_note, kn); + klist_remove(&so->so_rcv.sb_sel.si_note, kn); } int @@ -627,7 +627,7 @@ filt_fifowdetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_hook; - klist_remove_locked(&so->so_snd.sb_sel.si_note, kn); + klist_remove(&so->so_snd.sb_sel.si_note, kn); } int diff --git a/sys/sys/event.h b/sys/sys/event.h index 4df0d934ed0..fe4b9f1560e 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: event.h,v 1.56 2021/06/16 14:26:30 visa Exp $ */ +/* $OpenBSD: event.h,v 1.57 2021/10/24 07:02:47 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon @@ -285,6 +285,7 @@ struct timespec; extern const struct filterops sig_filtops; extern const struct filterops dead_filtops; +extern const struct klistops socket_klistops; extern void kqpoll_init(void); extern void kqpoll_exit(void); -- 2.20.1