diff options
author | bz <bz@FreeBSD.org> | 2010-03-17 18:28:27 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2010-03-17 18:28:27 +0000 |
commit | d9875d4fd4c45bebc4c347f0d1fcb22099193183 (patch) | |
tree | 85c73f9269f770d5fe3c30e96a831d1f2aa866c2 /sys/netinet/udp_usrreq.c | |
parent | 4b084f1d29afadefc6441a3d8791aa1fac66a125 (diff) | |
download | FreeBSD-src-d9875d4fd4c45bebc4c347f0d1fcb22099193183.zip FreeBSD-src-d9875d4fd4c45bebc4c347f0d1fcb22099193183.tar.gz |
Add pcb reference counting to the pcblist sysctl handler functions
to ensure type stability while caching the pcb pointers for the
copyout.
Reviewed by: rwatson
MFC after: 7 days
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r-- | sys/netinet/udp_usrreq.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index e0189d3..0d8e04d 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -746,11 +746,13 @@ udp_pcblist(SYSCTL_HANDLER_ARGS) INP_INFO_RLOCK(&V_udbinfo); for (inp = LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; inp && i < n; inp = LIST_NEXT(inp, inp_list)) { - INP_RLOCK(inp); + INP_WLOCK(inp); if (inp->inp_gencnt <= gencnt && - cr_canseeinpcb(req->td->td_ucred, inp) == 0) + cr_canseeinpcb(req->td->td_ucred, inp) == 0) { + in_pcbref(inp); inp_list[i++] = inp; - INP_RUNLOCK(inp); + } + INP_WUNLOCK(inp); } INP_INFO_RUNLOCK(&V_udbinfo); n = i; @@ -761,6 +763,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS) INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; + bzero(&xi, sizeof(xi)); xi.xi_len = sizeof xi; /* XXX should avoid extra copy */ @@ -773,6 +776,15 @@ udp_pcblist(SYSCTL_HANDLER_ARGS) } else INP_RUNLOCK(inp); } + INP_INFO_WLOCK(&V_udbinfo); + for (i = 0; i < n; i++) { + inp = inp_list[i]; + INP_WLOCK(inp); + if (!in_pcbrele(inp)) + INP_WUNLOCK(inp); + } + INP_INFO_WUNLOCK(&V_udbinfo); + if (!error) { /* * Give the user an updated idea of our state. If the |