Module Name:    src
Committed By:   christos
Date:           Wed Oct 14 19:40:09 UTC 2015

Modified Files:
        src/sys/net: bpf.c

Log Message:
PR/49386: Ryota Ozaki: Add a mutex for bpf creation/removal to avoid races.
Add M_CANFAIL to malloc.


To generate a diff of this commit:
cvs rdiff -u -r1.191 -r1.192 src/sys/net/bpf.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/net/bpf.c
diff -u src/sys/net/bpf.c:1.191 src/sys/net/bpf.c:1.192
--- src/sys/net/bpf.c:1.191	Sat May 30 15:14:46 2015
+++ src/sys/net/bpf.c	Wed Oct 14 15:40:09 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: bpf.c,v 1.191 2015/05/30 19:14:46 joerg Exp $	*/
+/*	$NetBSD: bpf.c,v 1.192 2015/10/14 19:40:09 christos Exp $	*/
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.191 2015/05/30 19:14:46 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.192 2015/10/14 19:40:09 christos Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_bpf.h"
@@ -340,6 +340,7 @@ bad:
 static void
 bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
 {
+	KASSERT(mutex_owned(&bpf_mtx));
 	/*
 	 * Point d at bp, and add d to the interface's list of listeners.
 	 * Finally, point the driver's bpf cookie at the interface so
@@ -361,6 +362,8 @@ bpf_detachd(struct bpf_d *d)
 	struct bpf_d **p;
 	struct bpf_if *bp;
 
+	KASSERT(mutex_owned(&bpf_mtx));
+
 	bp = d->bd_bif;
 	/*
 	 * Check if this descriptor had requested promiscuous mode.
@@ -476,6 +479,7 @@ bpf_close(struct file *fp)
 	int s;
 
 	KERNEL_LOCK(1, NULL);
+	mutex_enter(&bpf_mtx);
 
 	/*
 	 * Refresh the PID associated with this bpf file.
@@ -490,15 +494,14 @@ bpf_close(struct file *fp)
 		bpf_detachd(d);
 	splx(s);
 	bpf_freed(d);
-	mutex_enter(&bpf_mtx);
 	LIST_REMOVE(d, bd_list);
-	mutex_exit(&bpf_mtx);
 	callout_destroy(&d->bd_callout);
 	seldestroy(&d->bd_sel);
 	softint_disestablish(d->bd_sih);
 	free(d, M_DEVBUF);
 	fp->f_bpf = NULL;
 
+	mutex_exit(&bpf_mtx);
 	KERNEL_UNLOCK_ONE(NULL);
 
 	return (0);
@@ -900,10 +903,12 @@ bpf_ioctl(struct file *fp, u_long cmd, v
 	 * Set device parameters.
 	 */
 	case BIOCSDLT:
+		mutex_enter(&bpf_mtx);
 		if (d->bd_bif == NULL)
 			error = EINVAL;
 		else
 			error = bpf_setdlt(d, *(u_int *)addr);
+		mutex_exit(&bpf_mtx);
 		break;
 
 	/*
@@ -926,7 +931,9 @@ bpf_ioctl(struct file *fp, u_long cmd, v
 	case OBIOCSETIF:
 #endif
 	case BIOCSETIF:
+		mutex_enter(&bpf_mtx);
 		error = bpf_setif(d, addr);
+		mutex_exit(&bpf_mtx);
 		break;
 
 	/*
@@ -1152,6 +1159,7 @@ bpf_setif(struct bpf_d *d, struct ifreq 
 	char *cp;
 	int unit_seen, i, s, error;
 
+	KASSERT(mutex_owned(&bpf_mtx));
 	/*
 	 * Make sure the provided name has a unit number, and default
 	 * it to '0' if not specified.
@@ -1717,10 +1725,10 @@ static int
 bpf_allocbufs(struct bpf_d *d)
 {
 
-	d->bd_fbuf = malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK | M_CANFAIL);
+	d->bd_fbuf = malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT);
 	if (!d->bd_fbuf)
 		return (ENOBUFS);
-	d->bd_sbuf = malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK | M_CANFAIL);
+	d->bd_sbuf = malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT);
 	if (!d->bd_sbuf) {
 		free(d->bd_fbuf, M_DEVBUF);
 		return (ENOBUFS);
@@ -1770,6 +1778,7 @@ _bpfattach(struct ifnet *ifp, u_int dlt,
 	if (bp == NULL)
 		panic("bpfattach");
 
+	mutex_enter(&bpf_mtx);
 	bp->bif_dlist = NULL;
 	bp->bif_driverp = driverp;
 	bp->bif_ifp = ifp;
@@ -1781,6 +1790,7 @@ _bpfattach(struct ifnet *ifp, u_int dlt,
 	*bp->bif_driverp = NULL;
 
 	bp->bif_hdrlen = hdrlen;
+	mutex_exit(&bpf_mtx);
 #if 0
 	printf("bpf: %s attached\n", ifp->if_xname);
 #endif
@@ -1796,6 +1806,7 @@ _bpfdetach(struct ifnet *ifp)
 	struct bpf_d *d;
 	int s;
 
+	mutex_enter(&bpf_mtx);
 	/* Nuke the vnodes for any open instances */
 	LIST_FOREACH(d, &bpf_list, bd_list) {
 		if (d->bd_bif != NULL && d->bd_bif->bif_ifp == ifp) {
@@ -1819,6 +1830,7 @@ _bpfdetach(struct ifnet *ifp)
 			goto again;
 		}
 	}
+	mutex_exit(&bpf_mtx);
 }
 
 /*
@@ -1879,6 +1891,8 @@ bpf_setdlt(struct bpf_d *d, u_int dlt)
 	struct ifnet *ifp;
 	struct bpf_if *bp;
 
+	KASSERT(mutex_owned(&bpf_mtx));
+
 	if (d->bd_bif->bif_dlt == dlt)
 		return 0;
 	ifp = d->bd_bif->bif_ifp;

Reply via email to