⬢ DragonFlyBSD Kernel Audit
DF-3984 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/disk/sbp/sbp.c
+++ b/sys/dev/disk/sbp/sbp.c
@@ -182,6 +182,9 @@
 	struct sbp_login_res *login;
 	struct callout login_callout;
 	struct sbp_ocb *ocb;
+	/* DF-3984: recently-completed mgm ORB address; a status replay must
+	 * not match the recycled command ORB that now owns this address. */
+	u_int32_t stale_orb_lo;
 	STAILQ_HEAD(, sbp_ocb) ocbs;
 	STAILQ_HEAD(, sbp_ocb) free_ocbs;
 	char vendor[32];
@@ -1599,6 +1602,7 @@
 			if (OCB_MATCH(ocb, sbp_status)) {
 				callout_stop(&target->mgm_ocb_timeout);
 				target->mgm_ocb_cur = NULL;
+				sdev->stale_orb_lo = ntohl(sbp_status->orb_lo);
 				break;
 			}
 		}
@@ -2583,6 +2587,18 @@
 END_DEBUG
 	for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) {
 		next = STAILQ_NEXT(ocb, ocb);
+		if (sdev->stale_orb_lo != 0 &&
+		    ntohl(sbp_status->orb_lo) == sdev->stale_orb_lo) {
+			/* replayed mgm status: matches only the recycled
+			 * command ORB that inherited the address (DF-3984) */
+			kprintf("sbp%d:%d: stale mgm status replay "
+			    "(orb 0x%08x) dropped\n",
+			    device_get_unit(sdev->target->sbp->fd.dev),
+			    sdev->lun_id, sdev->stale_orb_lo);
+			sdev->stale_orb_lo = 0;
+			crit_exit();
+			return (NULL);
+		}
 		if (OCB_MATCH(ocb, sbp_status)) {
 			/* found */
 			STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb);