DF-0337 / fix.diff
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1281,6 +1281,7 @@ if (prison_xinpcb(req->td, inp)) continue; + bzero(&xt, sizeof xt); xt.xt_len = sizeof xt; bcopy(inp, &xt.xt_inp, sizeof *inp); inp_ppcb = inp->inp_ppcb; @@ -1288,8 +1289,61 @@ bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp); else bzero(&xt.xt_tp, sizeof xt.xt_tp); + /* + * Sanitize kernel pointers: the raw bcopy above + * leaks ~30 kernel addresses (hash/list links, + * inp_ppcb, inp_pcbinfo, inp_socket, inp_route, + * inp_*_options/moptions, all tcpcb callouts, + * t_inpcb, scoreboard pointers, t_outputq links, + * and stack-residue in xt_alignment_hack). Zero + * them so only the safe metadata fields remain. + * xt_socket is rebuilt from sotoxsocket() below. + */ + xt.xt_inp.inp_hash.le_next = NULL; + xt.xt_inp.inp_hash.le_prev = NULL; + xt.xt_inp.inp_list.le_next = NULL; + xt.xt_inp.inp_list.le_prev = NULL; + xt.xt_inp.inp_ppcb = NULL; + xt.xt_inp.inp_pcbinfo = NULL; + xt.xt_inp.inp_socket = NULL; + xt.xt_inp.inp_route.ro_rt = NULL; + xt.xt_inp.inp_depend4.inp4_options = NULL; + xt.xt_inp.inp_depend4.inp4_moptions = NULL; + xt.xt_inp.inp_depend6.inp6_options = NULL; + xt.xt_inp.inp_depend6.inp6_outputopts = NULL; + xt.xt_inp.inp_depend6.inp6_moptions = NULL; + xt.xt_inp.inp_depend6.inp6_icmp6filt = NULL; + xt.xt_inp.inp_portlist.le_next = NULL; + xt.xt_inp.inp_portlist.le_prev = NULL; + xt.xt_inp.inp_porthash = NULL; + xt.xt_inp.inp_phd = NULL; + xt.xt_inp.inp_pf_sk = NULL; + xt.xt_tp.t_segq.tqh_first = NULL; + xt.xt_tp.t_segq.tqh_last = NULL; + xt.xt_tp.t_pcbport = NULL; + xt.xt_tp.tt_rexmt = NULL; + xt.xt_tp.tt_persist = NULL; + xt.xt_tp.tt_keep = NULL; + xt.xt_tp.tt_2msl = NULL; + xt.xt_tp.tt_delack = NULL; + xt.xt_tp.tt_msg = NULL; + xt.xt_tp.tt_sndmore = NULL; + xt.xt_tp.t_inpcb = NULL; + xt.xt_tp.scb.sackblocks.tqh_first = NULL; + xt.xt_tp.scb.sackblocks.tqh_last = NULL; + xt.xt_tp.scb.lastfound = NULL; + xt.xt_tp.scb.freecache = NULL; + xt.xt_tp.t_outputq.tqe_next = NULL; + xt.xt_tp.t_outputq.tqe_prev = NULL; if (inp->inp_socket) sotoxsocket(inp->inp_socket, &xt.xt_socket); + /* + * sotoxsocket() deliberately copies xso_so and + * so_pcb kernel pointers as "convenience handles"; + * zero them to finish the sanitization. + */ + xt.xt_socket.xso_so = NULL; + xt.xt_socket.so_pcb = NULL; if ((error = SYSCTL_OUT(req, &xt, sizeof xt)) != 0) break; ++i; |