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]);