From: Vitaliy Makkoveev Subject: sysctl(2): unlock ipip_sysctl() To: Alexander Bluhm , tech@openbsd.org Date: Tue, 20 Aug 2024 17:54:03 +0300 - IPIPCTL_ALLOW - atomically accessed integer; - IPIPCTL_STATS - per-CPU counters; ok? Index: sys/netinet/in_proto.c =================================================================== RCS file: /cvs/src/sys/netinet/in_proto.c,v diff -u -p -r1.110 in_proto.c --- sys/netinet/in_proto.c 20 Aug 2024 07:47:25 -0000 1.110 +++ sys/netinet/in_proto.c 20 Aug 2024 14:51:59 -0000 @@ -230,7 +230,7 @@ const struct protosw inetsw[] = { .pr_type = SOCK_RAW, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_IPV4, - .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSOCKET, + .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL, #if NGIF > 0 .pr_input = in_gif_input, #else Index: sys/netinet/ip_ipip.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ipip.c,v diff -u -p -r1.102 ip_ipip.c --- sys/netinet/ip_ipip.c 17 May 2024 20:44:36 -0000 1.102 +++ sys/netinet/ip_ipip.c 20 Aug 2024 14:51:59 -0000 @@ -72,6 +72,11 @@ #include #endif +/* + * Locks used to protect data: + * a atomic + */ + #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ @@ -87,7 +92,7 @@ * We can control the acceptance of IP4 packets by altering the sysctl * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. */ -int ipip_allow = 0; +int ipip_allow = 0; /* [a] */ struct cpumem *ipipcounters; @@ -106,7 +111,8 @@ ipip_input(struct mbuf **mp, int *offp, struct ifnet *ifp; /* If we do not accept IP-in-IP explicitly, drop. */ - if (!ipip_allow && ((*mp)->m_flags & (M_AUTH|M_CONF)) == 0) { + if (atomic_load_int(&ipip_allow) == 0 && + ((*mp)->m_flags & (M_AUTH|M_CONF)) == 0) { DPRINTF("dropped due to policy"); ipipstat_inc(ipips_pdrops); m_freemp(mp); @@ -271,7 +277,8 @@ ipip_input_if(struct mbuf **mp, int *off } /* Check for local address spoofing. */ - if (!(ifp->if_flags & IFF_LOOPBACK) && ipip_allow != 2) { + if (!(ifp->if_flags & IFF_LOOPBACK) && + atomic_load_int(&ipip_allow) != 2) { struct sockaddr_storage ss; struct rtentry *rt; @@ -584,19 +591,14 @@ int ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - int error; - /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IPIPCTL_ALLOW: - NET_LOCK(); - error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, - &ipip_allow, 0, 2); - NET_UNLOCK(); - return (error); + return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, + &ipip_allow, 0, 2)); case IPIPCTL_STATS: return (ipip_sysctl_ipipstat(oldp, oldlenp, newp)); default: