From: Vitaliy Makkoveev Subject: sysctl(2): push kernel lock down to net_sysctl() To: Alexander Bluhm , tech@openbsd.org Date: Mon, 12 Aug 2024 21:30:59 +0300 All except PF_MPLS paths are mp-safe: - net_link_sysctl() and following net_ifiq_sysctl() only returns EOPNOTSUPP; - uipc_sysctl() - mp-safe atomic access to integers; - bpf_sysctl() - mp-safe atomic access to integers; - pflow_sysctl() - returns statistics from per-CPU counters; - pipex_sysctl() - mp-safe atomic access to integer; Kernel lock pushed down to mpls_sysctl(). sysctl_int_bounded() do copying with local variable, so context switch is safe. No need to wire memory or take `sysctl_lock' rwlock(9). mpls_sysctl() could be easily converted in the way of uipc_sysctl() or bpf_sysctl(), so if you want to test the diff please contact me. Protocols are still locked as they was include pages wiring, so existing copying will not sleep. No slowdown while doing it with net lock held. Index: sys/kern/kern_sysctl.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sysctl.c,v diff -u -p -r1.437 kern_sysctl.c --- sys/kern/kern_sysctl.c 11 Aug 2024 15:10:53 -0000 1.437 +++ sys/kern/kern_sysctl.c 12 Aug 2024 18:09:22 -0000 @@ -252,6 +252,7 @@ sys_sysctl(struct proc *p, void *v, regi fn = uvm_sysctl; break; case CTL_NET: + dolock = 0; fn = net_sysctl; break; case CTL_FS: Index: sys/kern/uipc_domain.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_domain.c,v diff -u -p -r1.66 uipc_domain.c --- sys/kern/uipc_domain.c 12 Aug 2024 11:25:27 -0000 1.66 +++ sys/kern/uipc_domain.c 12 Aug 2024 18:09:22 -0000 @@ -236,9 +236,18 @@ net_sysctl(int *name, u_int namelen, voi return (EISDIR); /* overloaded */ protocol = name[1]; for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) - if (pr->pr_protocol == protocol && pr->pr_sysctl) - return ((*pr->pr_sysctl)(name + 2, namelen - 2, - oldp, oldlenp, newp, newlen)); + if (pr->pr_protocol == protocol && pr->pr_sysctl) { + size_t savelen = *oldlenp; + int error; + + if ((error = sysctl_vslock(oldp, savelen))) + return (error); + error = (*pr->pr_sysctl)(name + 2, namelen - 2, + oldp, oldlenp, newp, newlen); + sysctl_vsunlock(oldp, savelen); + + return (error); + } return (ENOPROTOOPT); } Index: sys/netmpls/mpls_raw.c =================================================================== RCS file: /cvs/src/sys/netmpls/mpls_raw.c,v diff -u -p -r1.20 mpls_raw.c --- sys/netmpls/mpls_raw.c 29 Apr 2024 00:29:48 -0000 1.20 +++ sys/netmpls/mpls_raw.c 12 Aug 2024 18:09:22 -0000 @@ -58,6 +58,12 @@ int mpls_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - return sysctl_bounded_arr(mplsctl_vars, nitems(mplsctl_vars), + int error; + + KERNEL_LOCK(); + error = sysctl_bounded_arr(mplsctl_vars, nitems(mplsctl_vars), name, namelen, oldp, oldlenp, newp, newlen); + KERNEL_UNLOCK(); + + return error; }