1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
#include "arch.h" // page_size
#include "ioctls.h"
#include "maps.h"
#include "random.h"
#include "sanitise.h"
#include "shm.h"
#include "utils.h" // ARRAY_SIZE
#ifndef SCSI_IOCTL_GET_PCI
#define SCSI_IOCTL_GET_PCI 0x5387
#endif
#ifndef SG_GET_ACCESS_COUNT
#define SG_GET_ACCESS_COUNT 0x2289
#endif
static const struct ioctl scsi_ioctls[] = {
IOCTL(SCSI_IOCTL_GET_IDLUN),
IOCTL(SCSI_IOCTL_TAGGED_ENABLE),
IOCTL(SCSI_IOCTL_TAGGED_DISABLE),
IOCTL(SCSI_IOCTL_PROBE_HOST),
IOCTL(SCSI_IOCTL_GET_BUS_NUMBER),
IOCTL(SCSI_IOCTL_GET_PCI),
IOCTL(SCSI_IOCTL_SEND_COMMAND),
IOCTL(SCSI_IOCTL_TEST_UNIT_READY),
IOCTL(SCSI_IOCTL_BENCHMARK_COMMAND),
IOCTL(SCSI_IOCTL_SYNC),
IOCTL(SCSI_IOCTL_START_UNIT),
IOCTL(SCSI_IOCTL_STOP_UNIT),
IOCTL(SCSI_IOCTL_DOORLOCK),
IOCTL(SCSI_IOCTL_DOORUNLOCK),
IOCTL(SG_EMULATED_HOST),
IOCTL(SG_SET_TRANSFORM),
IOCTL(SG_GET_TRANSFORM),
IOCTL(SG_SET_RESERVED_SIZE),
IOCTL(SG_GET_RESERVED_SIZE),
IOCTL(SG_GET_SCSI_ID),
IOCTL(SG_SET_FORCE_LOW_DMA),
IOCTL(SG_GET_LOW_DMA),
IOCTL(SG_SET_FORCE_PACK_ID),
IOCTL(SG_GET_PACK_ID),
IOCTL(SG_GET_NUM_WAITING),
IOCTL(SG_GET_SG_TABLESIZE),
IOCTL(SG_GET_VERSION_NUM),
IOCTL(SG_SCSI_RESET),
IOCTL(SG_IO),
IOCTL(SG_GET_REQUEST_TABLE),
IOCTL(SG_SET_KEEP_ORPHAN),
IOCTL(SG_GET_KEEP_ORPHAN),
IOCTL(SG_GET_ACCESS_COUNT),
IOCTL(SG_SET_TIMEOUT),
IOCTL(SG_GET_TIMEOUT),
IOCTL(SG_GET_COMMAND_Q),
IOCTL(SG_SET_COMMAND_Q),
IOCTL(SG_SET_DEBUG),
IOCTL(SG_NEXT_CMD_LEN),
};
static const char *const scsi_devs[] = {
"sd",
"sr",
};
struct sgio {
sg_io_hdr_t ioh;
unsigned char data[512];
unsigned char cmd[12];
unsigned char sense[252];
};
static void scsi_sg_io_sanitise(int childno)
{
struct sgio *sgio;
sgio = (struct sgio *) page_rand;
sgio->cmd[0] = 0x12;
sgio->cmd[3] = 0x2;
sgio->ioh.interface_id = 'S';
switch (rand() % 4) {
case 0: sgio->ioh.dxfer_direction = SG_DXFER_NONE; break;
case 1: sgio->ioh.dxfer_direction = SG_DXFER_TO_DEV; break;
case 2: sgio->ioh.dxfer_direction = SG_DXFER_FROM_DEV; break;
case 3: sgio->ioh.dxfer_direction = SG_DXFER_TO_FROM_DEV; break;
default: break;
}
sgio->ioh.dxferp = sgio->data;
switch (rand() % 3) {
case 0: sgio->ioh.dxfer_len = rand() % page_size; break;
case 1: sgio->ioh.dxfer_len = (unsigned int) rand32(); break;
case 2: sgio->ioh.dxfer_len = rand() % 512; break;
default: break;
}
sgio->ioh.cmdp = sgio->cmd;
sgio->ioh.cmd_len = 6;
sgio->ioh.mx_sb_len = sizeof(sgio->sense);
sgio->ioh.sbp = sgio->sense;
sgio->ioh.timeout = UINT_MAX;
sgio->ioh.usr_ptr = NULL;
sgio->ioh.flags |= SG_FLAG_DIRECT_IO;
shm->a3[childno] = (unsigned long) page_rand;
}
static void scsi_sanitise(const struct ioctl_group *grp, int childno)
{
pick_random_ioctl(grp, childno);
switch (shm->a2[childno]) {
case SG_IO:
scsi_sg_io_sanitise(childno);
break;
default:
break;
}
}
static const struct ioctl_group scsi_grp = {
.devtype = DEV_BLOCK,
.devs = scsi_devs,
.devs_cnt = ARRAY_SIZE(scsi_devs),
.sanitise = scsi_sanitise,
.ioctls = scsi_ioctls,
.ioctls_cnt = ARRAY_SIZE(scsi_ioctls),
};
REG_IOCTL_GROUP(scsi_grp)
|