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
This commit is contained in:
Bjoern A. Zeeb 2010-03-17 18:28:27 +00:00
parent 4392b6f9b6
commit d0e157f6aa
4 changed files with 55 additions and 13 deletions

@ -628,11 +628,13 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_RLOCK(&V_divcbinfo); INP_INFO_RLOCK(&V_divcbinfo);
for (inp = LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; inp && i < n; for (inp = LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; inp && i < n;
inp = LIST_NEXT(inp, inp_list)) { inp = LIST_NEXT(inp, inp_list)) {
INP_RLOCK(inp); INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt && 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_list[i++] = inp;
INP_RUNLOCK(inp); }
INP_WUNLOCK(inp);
} }
INP_INFO_RUNLOCK(&V_divcbinfo); INP_INFO_RUNLOCK(&V_divcbinfo);
n = i; n = i;
@ -654,6 +656,15 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
} else } else
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
} }
INP_INFO_WLOCK(&V_divcbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
INP_WLOCK(inp);
if (!in_pcbrele(inp))
INP_WUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_divcbinfo);
if (!error) { if (!error) {
/* /*
* Give the user an updated idea of our state. * Give the user an updated idea of our state.

@ -1011,13 +1011,13 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_RLOCK(&V_ripcbinfo); INP_INFO_RLOCK(&V_ripcbinfo);
for (inp = LIST_FIRST(V_ripcbinfo.ipi_listhead), i = 0; inp && i < n; for (inp = LIST_FIRST(V_ripcbinfo.ipi_listhead), i = 0; inp && i < n;
inp = LIST_NEXT(inp, inp_list)) { inp = LIST_NEXT(inp, inp_list)) {
INP_RLOCK(inp); INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt && if (inp->inp_gencnt <= gencnt &&
cr_canseeinpcb(req->td->td_ucred, inp) == 0) { cr_canseeinpcb(req->td->td_ucred, inp) == 0) {
/* XXX held references? */ in_pcbref(inp);
inp_list[i++] = inp; inp_list[i++] = inp;
} }
INP_RUNLOCK(inp); INP_WUNLOCK(inp);
} }
INP_INFO_RUNLOCK(&V_ripcbinfo); INP_INFO_RUNLOCK(&V_ripcbinfo);
n = i; n = i;
@ -1040,6 +1040,15 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
} else } else
INP_RUNLOCK(inp); 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) { if (!error) {
/* /*
* Give the user an updated idea of our state. If the * Give the user an updated idea of our state. If the

@ -1108,7 +1108,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_RLOCK(&V_tcbinfo); INP_INFO_RLOCK(&V_tcbinfo);
for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0; for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0;
inp != NULL && i < n; inp = LIST_NEXT(inp, inp_list)) { inp != NULL && i < n; inp = LIST_NEXT(inp, inp_list)) {
INP_RLOCK(inp); INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt) { if (inp->inp_gencnt <= gencnt) {
/* /*
* XXX: This use of cr_cansee(), introduced with * XXX: This use of cr_cansee(), introduced with
@ -1123,10 +1123,12 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
error = EINVAL; /* Skip this inp. */ error = EINVAL; /* Skip this inp. */
} else } else
error = cr_canseeinpcb(req->td->td_ucred, inp); error = cr_canseeinpcb(req->td->td_ucred, inp);
if (error == 0) if (error == 0) {
in_pcbref(inp);
inp_list[i++] = inp; inp_list[i++] = inp;
} }
INP_RUNLOCK(inp); }
INP_WUNLOCK(inp);
} }
INP_INFO_RUNLOCK(&V_tcbinfo); INP_INFO_RUNLOCK(&V_tcbinfo);
n = i; n = i;
@ -1165,8 +1167,16 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, &xt, sizeof xt); error = SYSCTL_OUT(req, &xt, sizeof xt);
} else } else
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
} }
INP_INFO_WLOCK(&V_tcbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
INP_WLOCK(inp);
if (!in_pcbrele(inp))
INP_WUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_tcbinfo);
if (!error) { if (!error) {
/* /*
* Give the user an updated idea of our state. * Give the user an updated idea of our state.

@ -746,11 +746,13 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_RLOCK(&V_udbinfo); INP_INFO_RLOCK(&V_udbinfo);
for (inp = LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; inp && i < n; for (inp = LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; inp && i < n;
inp = LIST_NEXT(inp, inp_list)) { inp = LIST_NEXT(inp, inp_list)) {
INP_RLOCK(inp); INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt && 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_list[i++] = inp;
INP_RUNLOCK(inp); }
INP_WUNLOCK(inp);
} }
INP_INFO_RUNLOCK(&V_udbinfo); INP_INFO_RUNLOCK(&V_udbinfo);
n = i; n = i;
@ -761,6 +763,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
INP_RLOCK(inp); INP_RLOCK(inp);
if (inp->inp_gencnt <= gencnt) { if (inp->inp_gencnt <= gencnt) {
struct xinpcb xi; struct xinpcb xi;
bzero(&xi, sizeof(xi)); bzero(&xi, sizeof(xi));
xi.xi_len = sizeof xi; xi.xi_len = sizeof xi;
/* XXX should avoid extra copy */ /* XXX should avoid extra copy */
@ -773,6 +776,15 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
} else } else
INP_RUNLOCK(inp); 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) { if (!error) {
/* /*
* Give the user an updated idea of our state. If the * Give the user an updated idea of our state. If the