Make sure imo_membership is protected by inp's lock (solock)

This commit is contained in:
ozaki-r 2017-03-02 05:29:31 +00:00
parent 549f799fbf
commit d0c11d0872
3 changed files with 28 additions and 7 deletions

View File

@ -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, struct ifnet *ifp)
{
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, struct ifnet *ifp)
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);
}
}

View File

@ -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 *);

View File

@ -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 struct sockopt *sopt)
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 *imo, const struct sockopt *sopt)
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, const struct sockopt *sopt)
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]);