Add missing kernel lock around (*if_ioctl)() call within
authormvs <mvs@openbsd.org>
Tue, 6 Dec 2022 22:19:39 +0000 (22:19 +0000)
committermvs <mvs@openbsd.org>
Tue, 6 Dec 2022 22:19:39 +0000 (22:19 +0000)
in{,6}_addmulti(). Since kernel lock is no more taken while following
setsockopt() path, it should be taken in this place. Corresponding
in{,6}_delmulti() already acquire kernel lock around (*if_ioctl)().

Problem reported and diff tested by weerd@

ok kn@ bluhm@

sys/netinet/in.c
sys/netinet6/in6.c

index 0a59d70..fa778ef 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in.c,v 1.178 2022/11/19 14:26:40 kn Exp $     */
+/*     $OpenBSD: in.c,v 1.179 2022/12/06 22:19:39 mvs Exp $    */
 /*     $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
 
 /*
@@ -885,10 +885,13 @@ in_addmulti(struct in_addr *ap, struct ifnet *ifp)
                 */
                memset(&ifr, 0, sizeof(ifr));
                memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin));
+               KERNEL_LOCK();
                if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
+                       KERNEL_UNLOCK();
                        free(inm, M_IPMADDR, sizeof(*inm));
                        return (NULL);
                }
+               KERNEL_UNLOCK();
 
                TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma,
                    ifma_list);
index 10f7610..a6b9bb7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6.c,v 1.258 2022/12/02 12:56:51 kn Exp $    */
+/*     $OpenBSD: in6.c,v 1.259 2022/12/06 22:19:39 mvs Exp $   */
 /*     $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $   */
 
 /*
@@ -1063,7 +1063,9 @@ in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp, int *errorp)
                 * filter appropriately for the new address.
                 */
                memcpy(&ifr.ifr_addr, &in6m->in6m_sin, sizeof(in6m->in6m_sin));
+               KERNEL_LOCK();
                *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
+               KERNEL_UNLOCK();
                if (*errorp) {
                        free(in6m, M_IPMADDR, sizeof(*in6m));
                        return (NULL);