PR/49386: Ryota Ozaki: Add a mutex for bpf creation/removal to avoid races.
Add M_CANFAIL to malloc.
This commit is contained in:
parent
96e2a4cea0
commit
d522fec9f5
@ -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, void *addr)
|
||||
* 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, void *addr)
|
||||
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 *ifr)
|
||||
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, u_int hdrlen, struct bpf_if **driverp)
|
||||
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, u_int hdrlen, struct bpf_if **driverp)
|
||||
*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;
|
||||
|
Loading…
Reference in New Issue
Block a user