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/raw_ip.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/raw_ip.c')
-rw-r--r-- | sys/netinet/raw_ip.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 88c1e61..1db3774 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1011,13 +1011,13 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) INP_INFO_RLOCK(&V_ripcbinfo); for (inp = LIST_FIRST(V_ripcbinfo.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) { - /* XXX held references? */ + in_pcbref(inp); inp_list[i++] = inp; } - INP_RUNLOCK(inp); + INP_WUNLOCK(inp); } INP_INFO_RUNLOCK(&V_ripcbinfo); n = i; @@ -1040,6 +1040,15 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) } else INP_RUNLOCK(inp); } + INP_INFO_WLOCK(&V_ripcbinfo); + for (i = 0; i < n; i++) { + inp = inp_list[i]; + INP_WLOCK(inp); + if (!in_pcbrele(inp)) + INP_WUNLOCK(inp); + } + INP_INFO_WUNLOCK(&V_ripcbinfo); + if (!error) { /* * Give the user an updated idea of our state. If the |