DF-2499 / fix.diff
diff --git a/sys/dev/disk/nata/atapi-cam.c b/sys/dev/disk/nata/atapi-cam.c --- a/sys/dev/disk/nata/atapi-cam.c +++ b/sys/dev/disk/nata/atapi-cam.c @@ -881,8 +881,14 @@ struct atapi_hcb *hcb; if (scp != NULL) { + struct atapi_hcb *hcb_tmp; + lockmgr(&scp->state_lock, LK_EXCLUSIVE); - TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) { + /* free_hcb() kfree()s each hcb inside the loop body; the plain + * TAILQ_FOREACH macro would then dereference the freed element's + * tqe_next pointer (UAF read). Use the _MUTABLE variant which caches + * the next pointer before the body runs. See DF-2499. */ + TAILQ_FOREACH_MUTABLE(hcb, &scp->pending_hcbs, chain, hcb_tmp) { free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR); } lockmgr(&scp->state_lock, LK_RELEASE); |