DragonFlyBSD Kernel Audit
DF-0337 / fix.diff
← back to finding ↓ download raw
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;