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;