Module Name: src Committed By: ozaki-r Date: Thu Mar 2 05:29:31 UTC 2017
Modified Files: src/sys/netinet: in_pcb.c in_pcb.h ip_output.c Log Message: Make sure imo_membership is protected by inp's lock (solock) To generate a diff of this commit: cvs rdiff -u -r1.175 -r1.176 src/sys/netinet/in_pcb.c cvs rdiff -u -r1.62 -r1.63 src/sys/netinet/in_pcb.h cvs rdiff -u -r1.273 -r1.274 src/sys/netinet/ip_output.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet/in_pcb.c diff -u src/sys/netinet/in_pcb.c:1.175 src/sys/netinet/in_pcb.c:1.176 --- src/sys/netinet/in_pcb.c:1.175 Mon Feb 13 04:05:58 2017 +++ src/sys/netinet/in_pcb.c Thu Mar 2 05:29:31 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.c,v 1.175 2017/02/13 04:05:58 ozaki-r Exp $ */ +/* $NetBSD: in_pcb.c,v 1.176 2017/03/02 05:29:31 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -93,7 +93,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.175 2017/02/13 04:05:58 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.176 2017/03/02 05:29:31 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -722,6 +722,7 @@ in_purgeifmcast(struct ip_moptions *imo, { int i, gap; + /* The owner of imo should be protected by solock */ KASSERT(ifp != NULL); if (imo == NULL) @@ -755,9 +756,21 @@ in_pcbpurgeif0(struct inpcbtable *table, TAILQ_FOREACH_SAFE(inph, &table->inpt_queue, inph_queue, ninph) { struct inpcb *inp = (struct inpcb *)inph; + bool need_unlock = false; + if (inp->inp_af != AF_INET) continue; + + /* The caller holds either one of inps' lock */ + if (!inp_locked(inp)) { + inp_lock(inp); + need_unlock = true; + } + in_purgeifmcast(inp->inp_moptions, ifp); + + if (need_unlock) + inp_unlock(inp); } } Index: src/sys/netinet/in_pcb.h diff -u src/sys/netinet/in_pcb.h:1.62 src/sys/netinet/in_pcb.h:1.63 --- src/sys/netinet/in_pcb.h:1.62 Wed Feb 22 07:05:04 2017 +++ src/sys/netinet/in_pcb.h Thu Mar 2 05:29:31 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.h,v 1.62 2017/02/22 07:05:04 ozaki-r Exp $ */ +/* $NetBSD: in_pcb.h,v 1.63 2017/03/02 05:29:31 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -128,7 +128,9 @@ struct inpcb { INP_PKTINFO) #define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) -#define inplocked(inp) solocked((inp)->inp_socket) +#define inp_lock(inp) solock((inp)->inp_socket) +#define inp_unlock(inp) sounlock((inp)->inp_socket) +#define inp_locked(inp) solocked((inp)->inp_socket) #ifdef _KERNEL void in_losing(struct inpcb *); Index: src/sys/netinet/ip_output.c diff -u src/sys/netinet/ip_output.c:1.273 src/sys/netinet/ip_output.c:1.274 --- src/sys/netinet/ip_output.c:1.273 Thu Mar 2 05:24:23 2017 +++ src/sys/netinet/ip_output.c Thu Mar 2 05:29:31 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_output.c,v 1.273 2017/03/02 05:24:23 ozaki-r Exp $ */ +/* $NetBSD: ip_output.c,v 1.274 2017/03/02 05:29:31 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.273 2017/03/02 05:24:23 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.274 2017/03/02 05:29:31 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1337,7 +1337,7 @@ ip_pcbopts(struct inpcb *inp, const stru u_char *dp; int cnt; - KASSERT(inplocked(inp)); + KASSERT(inp_locked(inp)); /* Turn off any old options. */ if (inp->inp_options) { @@ -1587,6 +1587,8 @@ ip_add_membership(struct ip_moptions *im int i, error, bound; struct psref psref; + /* imo is protected by solock or referenced only by the caller */ + bound = curlwp_bind(); if (sopt->sopt_size == sizeof(struct ip_mreq)) error = ip_get_membership(sopt, &ifp, &psref, &ia, true); @@ -1718,6 +1720,8 @@ ip_setmoptions(struct ip_moptions **pimo struct ifnet *ifp; int ifindex, error = 0; + /* The passed imo isn't NULL, it should be protected by solock */ + if (!imo) { /* * No multicast option buffer attached to the pcb; @@ -1880,6 +1884,8 @@ ip_freemoptions(struct ip_moptions *imo) { int i; + /* The owner of imo (inp) should be protected by solock */ + if (imo != NULL) { for (i = 0; i < imo->imo_num_memberships; ++i) in_delmulti(imo->imo_membership[i]);