cam: Fix the mmc_data mapping length for XPT_MMC_IO

cam_periph_mapmem() and cam_periph_unmapmem() map the user-provided
struct mmc_data for XPT_MMC_IO CCBs, but use sizeof(struct mmc_data *)
instead of sizeof(struct mmc_data) as the length.  Only the pages
covering a pointer are mapped, so accessing a field past the first
pointer-sized region (for instance cmd->data->flags) faults if the
structure happens to straddle a page boundary and the following page is
not mapped.

The failure is intermittent because it depends on where the caller places
the struct mmc_data.  Issuing a CMD53 CCB through pass(4) to an MMCCAM
SDIO card whose struct mmc_data lands at the end of a page panics with
"data abort in critical section or under mutex" in the host driver.

Map the whole structure in both the map and unmap paths.

MFC after:	1 week
Reviewed by:	imp
Differential Revision:	https://reviews.freebsd.org/D61022
This commit is contained in:
Emmanuel Vadot committed 2026-11-05 15:51:31 +01:00
1 parent 49204732f6
commit bf99b74302
1 file changed
+2 -2
+2 -2
View File
@@ -897,7 +897,7 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo,
return(0);
/* Two mappings: one for cmd->data and one for cmd->data->data */
data_ptrs[0] = (unsigned char **)&ccb->mmcio.cmd.data;
lengths[0] = sizeof(struct mmc_data *);
lengths[0] = sizeof(struct mmc_data);
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
data_ptrs[1] = (unsigned char **)&ccb->mmcio.cmd.data->data;
lengths[1] = ccb->mmcio.cmd.data->len;
@@ -1076,7 +1076,7 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
break;
case XPT_MMC_IO:
data_ptrs[0] = (uint8_t **)&ccb->mmcio.cmd.data;
lengths[0] = sizeof(struct mmc_data *);
lengths[0] = sizeof(struct mmc_data);
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
data_ptrs[1] = (uint8_t **)&ccb->mmcio.cmd.data->data;
lengths[1] = ccb->mmcio.cmd.data->len;