⬢ DragonFlyBSD Kernel Audit
DF-2286 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/cam/scsi/scsi_target.c
+++ b/sys/bus/cam/scsi/scsi_target.c
@@ -963,10 +963,26 @@
 	descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
 	u_ccbh = &descr->user_ccb->ccb_h;
 
-	/* Copy out the central portion of the ccb_hdr */
-	copyout(&ccb->ccb_h.retry_count, &u_ccbh->retry_count,
-		offsetof(struct ccb_hdr, periph_priv) -
-		offsetof(struct ccb_hdr, retry_count));
+	/*
+	 * DF-2286: the [retry_count, periph_priv) slice includes the
+	 * kernel-only fields cbfcnp (= &targdone, kernel text) and path
+	 * (kernel heap cam_path).  Stage the copy and NULL both -- the
+	 * same sanitization scsi_pass.c:610 applies before handing a CCB
+	 * back to userland -- so the daemon cannot defeat KASLR with them.
+	 */
+	{
+		struct ccb_hdr kh;
+
+		bzero(&kh, sizeof(kh));
+		bcopy(&ccb->ccb_h.retry_count, &kh.retry_count,
+		    offsetof(struct ccb_hdr, periph_priv) -
+		    offsetof(struct ccb_hdr, retry_count));
+		kh.cbfcnp = NULL;
+		kh.path = NULL;
+		copyout(&kh.retry_count, &u_ccbh->retry_count,
+		    offsetof(struct ccb_hdr, periph_priv) -
+		    offsetof(struct ccb_hdr, retry_count));
+	}
 
 	/* Copy out the rest of the ccb (after the ccb_hdr) */
 	ccb_len = targccblen(ccb->ccb_h.func_code) - sizeof(struct ccb_hdr);