DragonFlyBSD Kernel Audit
DF-2548 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -2911,6 +2911,43 @@
 		t = *tp;
 		if (t.t_dev)
 			t.t_dev = (cdev_t)(uintptr_t)devid_from_dev(t.t_dev);
+		/*
+		 * Zero every kernel-pointer-bearing field before copyout so we
+		 * do not leak kernel .text/.rodata/.heap addresses (KASLR
+		 * defeat + heap layout) to unprivileged readers of kern.ttys.
+		 * Only t_dev is rewritten (to a small devid) above; every other
+		 * pointer field is nulled here.  Mirrors the sanitized-export
+		 * pattern used by kinfo_file in kern_descrip.c.
+		 *
+		 * Fields cleared (see sys/sys/tty.h):
+		 *   - t_token       : lwkt_token { t_ref, t_desc }
+		 *   - t_rawq/t_canq/t_outq .c_data : clist data buffers
+		 *   - t_pgrp/t_session/t_sigio     : heap object pointers
+		 *   - t_rkq/t_wkq   : kqinfo { ki_note (klist ptr) }
+		 *   - t_oproc/t_stop/t_param/t_unhold : driver .text fn ptrs
+		 *   - t_sc/t_slsc   : driver softc / line-disc softc
+		 *   - t_list        : TAILQ_ENTRY linkage { tqe_next, tqe_prev }
+		 * The remaining exported fields (termios, winsize, watermarks,
+		 * state/flags, column, etc.) are pure scalars and are what
+		 * pstat(8) actually consumes.
+		 */
+		bzero(&t.t_token, sizeof(t.t_token));
+		t.t_rawq.c_data = NULL;
+		t.t_canq.c_data = NULL;
+		t.t_outq.c_data = NULL;
+		t.t_pgrp = NULL;
+		t.t_session = NULL;
+		t.t_sigio = NULL;
+		bzero(&t.t_rkq, sizeof(t.t_rkq));
+		bzero(&t.t_wkq, sizeof(t.t_wkq));
+		t.t_oproc = NULL;
+		t.t_stop = NULL;
+		t.t_param = NULL;
+		t.t_unhold = NULL;
+		t.t_sc = NULL;
+		t.t_slsc = NULL;
+		t.t_list.tqe_next = NULL;
+		t.t_list.tqe_prev = NULL;
 		error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t));
 		if (error)
 			break;