Make most BPF ioctls() SMP-safe.

Approved by:      kib(mentor)
MFC in:            4 weeks
This commit is contained in:
melifaro 2012-05-21 22:21:00 +00:00
parent e5f61c6580
commit e145f3abac

View File

@ -1229,7 +1229,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BIOCGDLTLIST32: case BIOCGDLTLIST32:
case BIOCGRTIMEOUT32: case BIOCGRTIMEOUT32:
case BIOCSRTIMEOUT32: case BIOCSRTIMEOUT32:
BPFD_LOCK(d);
d->bd_compat32 = 1; d->bd_compat32 = 1;
BPFD_UNLOCK(d);
} }
#endif #endif
@ -1274,7 +1276,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get buffer len [for read()]. * Get buffer len [for read()].
*/ */
case BIOCGBLEN: case BIOCGBLEN:
BPFD_LOCK(d);
*(u_int *)addr = d->bd_bufsize; *(u_int *)addr = d->bd_bufsize;
BPFD_UNLOCK(d);
break; break;
/* /*
@ -1329,10 +1333,12 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get current data link type. * Get current data link type.
*/ */
case BIOCGDLT: case BIOCGDLT:
BPF_LOCK();
if (d->bd_bif == NULL) if (d->bd_bif == NULL)
error = EINVAL; error = EINVAL;
else else
*(u_int *)addr = d->bd_bif->bif_dlt; *(u_int *)addr = d->bd_bif->bif_dlt;
BPF_UNLOCK();
break; break;
/* /*
@ -1347,6 +1353,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
list32 = (struct bpf_dltlist32 *)addr; list32 = (struct bpf_dltlist32 *)addr;
dltlist.bfl_len = list32->bfl_len; dltlist.bfl_len = list32->bfl_len;
dltlist.bfl_list = PTRIN(list32->bfl_list); dltlist.bfl_list = PTRIN(list32->bfl_list);
BPF_LOCK();
if (d->bd_bif == NULL) if (d->bd_bif == NULL)
error = EINVAL; error = EINVAL;
else { else {
@ -1354,15 +1361,18 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
if (error == 0) if (error == 0)
list32->bfl_len = dltlist.bfl_len; list32->bfl_len = dltlist.bfl_len;
} }
BPF_UNLOCK();
break; break;
} }
#endif #endif
case BIOCGDLTLIST: case BIOCGDLTLIST:
BPF_LOCK();
if (d->bd_bif == NULL) if (d->bd_bif == NULL)
error = EINVAL; error = EINVAL;
else else
error = bpf_getdltlist(d, (struct bpf_dltlist *)addr); error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
BPF_UNLOCK();
break; break;
/* /*
@ -1381,6 +1391,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get interface name. * Get interface name.
*/ */
case BIOCGETIF: case BIOCGETIF:
BPF_LOCK();
if (d->bd_bif == NULL) if (d->bd_bif == NULL)
error = EINVAL; error = EINVAL;
else { else {
@ -1390,6 +1401,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
strlcpy(ifr->ifr_name, ifp->if_xname, strlcpy(ifr->ifr_name, ifp->if_xname,
sizeof(ifr->ifr_name)); sizeof(ifr->ifr_name));
} }
BPF_UNLOCK();
break; break;
/* /*
@ -1481,7 +1493,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Set immediate mode. * Set immediate mode.
*/ */
case BIOCIMMEDIATE: case BIOCIMMEDIATE:
BPFD_LOCK(d);
d->bd_immediate = *(u_int *)addr; d->bd_immediate = *(u_int *)addr;
BPFD_UNLOCK(d);
break; break;
case BIOCVERSION: case BIOCVERSION:
@ -1497,21 +1511,27 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get "header already complete" flag * Get "header already complete" flag
*/ */
case BIOCGHDRCMPLT: case BIOCGHDRCMPLT:
BPFD_LOCK(d);
*(u_int *)addr = d->bd_hdrcmplt; *(u_int *)addr = d->bd_hdrcmplt;
BPFD_UNLOCK(d);
break; break;
/* /*
* Set "header already complete" flag * Set "header already complete" flag
*/ */
case BIOCSHDRCMPLT: case BIOCSHDRCMPLT:
BPFD_LOCK(d);
d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0; d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
BPFD_UNLOCK(d);
break; break;
/* /*
* Get packet direction flag * Get packet direction flag
*/ */
case BIOCGDIRECTION: case BIOCGDIRECTION:
BPFD_LOCK(d);
*(u_int *)addr = d->bd_direction; *(u_int *)addr = d->bd_direction;
BPFD_UNLOCK(d);
break; break;
/* /*
@ -1526,7 +1546,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BPF_D_IN: case BPF_D_IN:
case BPF_D_INOUT: case BPF_D_INOUT:
case BPF_D_OUT: case BPF_D_OUT:
BPFD_LOCK(d);
d->bd_direction = direction; d->bd_direction = direction;
BPFD_UNLOCK(d);
break; break;
default: default:
error = EINVAL; error = EINVAL;
@ -1538,7 +1560,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get packet timestamp format and resolution. * Get packet timestamp format and resolution.
*/ */
case BIOCGTSTAMP: case BIOCGTSTAMP:
BPFD_LOCK(d);
*(u_int *)addr = d->bd_tstamp; *(u_int *)addr = d->bd_tstamp;
BPFD_UNLOCK(d);
break; break;
/* /*
@ -1557,26 +1581,38 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
break; break;
case BIOCFEEDBACK: case BIOCFEEDBACK:
BPFD_LOCK(d);
d->bd_feedback = *(u_int *)addr; d->bd_feedback = *(u_int *)addr;
BPFD_UNLOCK(d);
break; break;
case BIOCLOCK: case BIOCLOCK:
BPFD_LOCK(d);
d->bd_locked = 1; d->bd_locked = 1;
BPFD_UNLOCK(d);
break; break;
case FIONBIO: /* Non-blocking I/O */ case FIONBIO: /* Non-blocking I/O */
break; break;
case FIOASYNC: /* Send signal on receive packets */ case FIOASYNC: /* Send signal on receive packets */
BPFD_LOCK(d);
d->bd_async = *(int *)addr; d->bd_async = *(int *)addr;
BPFD_UNLOCK(d);
break; break;
case FIOSETOWN: case FIOSETOWN:
/*
* XXX: Add some sort of locking here?
* fsetown() can sleep.
*/
error = fsetown(*(int *)addr, &d->bd_sigio); error = fsetown(*(int *)addr, &d->bd_sigio);
break; break;
case FIOGETOWN: case FIOGETOWN:
BPFD_LOCK(d);
*(int *)addr = fgetown(&d->bd_sigio); *(int *)addr = fgetown(&d->bd_sigio);
BPFD_UNLOCK(d);
break; break;
/* This is deprecated, FIOSETOWN should be used instead. */ /* This is deprecated, FIOSETOWN should be used instead. */
@ -1597,16 +1633,23 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
if (sig >= NSIG) if (sig >= NSIG)
error = EINVAL; error = EINVAL;
else else {
BPFD_LOCK(d);
d->bd_sig = sig; d->bd_sig = sig;
BPFD_UNLOCK(d);
}
break; break;
} }
case BIOCGRSIG: case BIOCGRSIG:
BPFD_LOCK(d);
*(u_int *)addr = d->bd_sig; *(u_int *)addr = d->bd_sig;
BPFD_UNLOCK(d);
break; break;
case BIOCGETBUFMODE: case BIOCGETBUFMODE:
BPFD_LOCK(d);
*(u_int *)addr = d->bd_bufmode; *(u_int *)addr = d->bd_bufmode;
BPFD_UNLOCK(d);
break; break;
case BIOCSETBUFMODE: case BIOCSETBUFMODE:
@ -2544,24 +2587,22 @@ bpf_getdltlist(struct bpf_d *d, struct bpf_dltlist *bfl)
struct ifnet *ifp; struct ifnet *ifp;
struct bpf_if *bp; struct bpf_if *bp;
BPF_LOCK_ASSERT();
ifp = d->bd_bif->bif_ifp; ifp = d->bd_bif->bif_ifp;
n = 0; n = 0;
error = 0; error = 0;
BPF_LOCK();
LIST_FOREACH(bp, &bpf_iflist, bif_next) { LIST_FOREACH(bp, &bpf_iflist, bif_next) {
if (bp->bif_ifp != ifp) if (bp->bif_ifp != ifp)
continue; continue;
if (bfl->bfl_list != NULL) { if (bfl->bfl_list != NULL) {
if (n >= bfl->bfl_len) { if (n >= bfl->bfl_len)
BPF_UNLOCK();
return (ENOMEM); return (ENOMEM);
}
error = copyout(&bp->bif_dlt, error = copyout(&bp->bif_dlt,
bfl->bfl_list + n, sizeof(u_int)); bfl->bfl_list + n, sizeof(u_int));
} }
n++; n++;
} }
BPF_UNLOCK();
bfl->bfl_len = n; bfl->bfl_len = n;
return (error); return (error);
} }