DF-2286 / fix.diff
--- 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); |