Make most BPF ioctls() SMP-safe.
Approved by: kib(mentor) MFC in: 4 weeks
This commit is contained in:
parent
e5f61c6580
commit
e145f3abac
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user