Rather than hold a mutex over calls to SYSCTL_OUT allocate a

temporary buffer then pass the array to user-space once we have
dropped the lock.

While we are here, drop an assertion which could result in a
kernel panic under certain race conditions.

Pointed out by:	rwatson
This commit is contained in:
Christian S.J. Peron 2005-07-26 17:21:56 +00:00
parent d6bb0cb7eb
commit 422a63da6e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=148418

View File

@ -1670,8 +1670,8 @@ bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
static int
bpf_stats_sysctl(SYSCTL_HANDLER_ARGS)
{
struct xbpf_d xbd;
int error;
struct xbpf_d *xbdbuf, *xbd;
int index, error;
struct bpf_if *bp;
struct bpf_d *bd;
@ -1685,26 +1685,28 @@ bpf_stats_sysctl(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
if (req->oldptr == NULL)
return (SYSCTL_OUT(req, 0, bpf_bpfd_cnt * sizeof(xbd)));
if (req->oldlen < bpf_bpfd_cnt * sizeof(xbd))
return (ENOMEM);
return (SYSCTL_OUT(req, 0, bpf_bpfd_cnt * sizeof(*xbd)));
if (bpf_bpfd_cnt == 0)
return (SYSCTL_OUT(req, 0, 0));
xbdbuf = malloc(req->oldlen, M_BPF, M_WAITOK);
mtx_lock(&bpf_mtx);
KASSERT(bpf_bpfd_cnt != 0, ("zero bpf descriptors present"));
if (req->oldlen < (bpf_bpfd_cnt * sizeof(*xbd))) {
mtx_unlock(&bpf_mtx);
free(xbdbuf, M_BPF);
return (ENOMEM);
}
index = 0;
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
LIST_FOREACH(bd, &bp->bif_dlist, bd_next) {
xbd = &xbdbuf[index++];
BPFD_LOCK(bd);
bpfstats_fill_xbpf(&xbd, bd);
bpfstats_fill_xbpf(xbd, bd);
BPFD_UNLOCK(bd);
error = SYSCTL_OUT(req, &xbd, sizeof(xbd));
if (error != 0) {
mtx_unlock(&bpf_mtx);
return (error);
}
}
}
mtx_unlock(&bpf_mtx);
error = SYSCTL_OUT(req, xbdbuf, index * sizeof(*xbd));
free(xbdbuf, M_BPF);
return (error);
}