From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:35599) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjZZs-0003mx-9y for qemu-devel@nongnu.org; Wed, 20 Jul 2011 12:24:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QjZZj-0008Sa-Ce for qemu-devel@nongnu.org; Wed, 20 Jul 2011 12:24:52 -0400 Received: from oxygen.pond.sub.org ([78.46.104.156]:55561) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjZZd-0008Og-Us for qemu-devel@nongnu.org; Wed, 20 Jul 2011 12:24:38 -0400 From: Markus Armbruster Date: Wed, 20 Jul 2011 18:23:52 +0200 Message-Id: <1311179069-27882-19-git-send-email-armbru@redhat.com> In-Reply-To: <1311179069-27882-1-git-send-email-armbru@redhat.com> References: <1311179069-27882-1-git-send-email-armbru@redhat.com> Subject: [Qemu-devel] [PATCH 18/55] scsi-disk: Reject CD-specific SCSI commands to disks List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, quintela@redhat.com, dbaryshkov@gmail.com, stefano.stabellini@eu.citrix.com, lcapitulino@redhat.com, amit.shah@redhat.com Use a table to declare which drive kinds accept each command. Limit READ_CAPACITY, READ_TOC, GET_CONFIGURATION to SCSI_CD, as per SPC-4. It would be nice to have handler functions in the table, like commit e1a064f9 did for ATAPI. Left for another day. Signed-off-by: Markus Armbruster --- hw/scsi-disk.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 62 insertions(+), 1 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index a8c7372..c4643d0 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -991,6 +991,59 @@ illegal_request: return -1; } +#define HD_OK (1u << SCSI_HD) +#define CD_OK (1u << SCSI_CD) +#define ALL_OK (HD_OK | CD_OK) + +/* See SPC-4 T10/1731-D Table D.2 Operation codes */ +uint8_t scsi_cmd_table[0x100] = { + [TEST_UNIT_READY] = ALL_OK, + [REZERO_UNIT] = ALL_OK, + [REQUEST_SENSE] = ALL_OK, + /* FORMAT_UNIT not implemented, SPC-4 mandatory for HD */ + [READ_6] = ALL_OK, + [WRITE_6] = ALL_OK, + [SEEK_6] = ALL_OK, + [INQUIRY] = ALL_OK, + [MODE_SELECT] = ALL_OK, + [RESERVE] = ALL_OK, + [RELEASE] = ALL_OK, + [MODE_SENSE] = ALL_OK, + [START_STOP] = ALL_OK, + /* SEND DIAGNOSTIC not implemented, SPC-4 mandatory for HD */ + [ALLOW_MEDIUM_REMOVAL] = ALL_OK, + [READ_CAPACITY] = CD_OK, + [READ_10] = ALL_OK, + [WRITE_10] = ALL_OK, + [SEEK_10] = ALL_OK, + [WRITE_VERIFY] = ALL_OK, + [VERIFY] = ALL_OK, + [SYNCHRONIZE_CACHE] = ALL_OK, + [READ_TOC] = CD_OK, + [GET_CONFIGURATION] = CD_OK, + /* GET EVENT STATUS NOTIFICATION not implemented, SPC-4 mandatory for CD */ + [MODE_SELECT_10] = ALL_OK, + [RESERVE_10] = ALL_OK, + [RELEASE_10] = ALL_OK, + [MODE_SENSE_10] = ALL_OK, + [READ_16] = ALL_OK, + [WRITE_16] = ALL_OK, + [WRITE_VERIFY_16] = ALL_OK, + /* VERIFY(16) not implemented, WRITE_VERIFY(16) is, odd */ + [WRITE_SAME_16] = ALL_OK, + [SERVICE_ACTION_IN] = ALL_OK, + [REPORT_LUNS] = ALL_OK, + [READ_12] = ALL_OK, + [WRITE_12] = ALL_OK, + [WRITE_VERIFY_12] = ALL_OK, + /* VERIFY(12) not implemented, WRITE_VERIFY(12) is, odd */ +}; + +static bool scsi_cmd_permitted(SCSIDiskState *s, uint8_t cmd) +{ + return scsi_cmd_table[cmd] & (1u << s->drive_kind); +} + /* Execute a scsi command. Returns the length of the data expected by the command. This will be Positive for data transfers from the device (eg. disk reads), negative for transfers to the device (eg. disk writes), @@ -1033,6 +1086,13 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) return 0; } } + + if (!scsi_cmd_permitted(s, command)) { + DPRINTF("SCSI command (%2.2x) not valid for device\n", command); + scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE)); + return 0; + } + switch (command) { case TEST_UNIT_READY: case REQUEST_SENSE: @@ -1137,7 +1197,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) break; default: - DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]); + /* should not be reachable */ + BADF("Unknown SCSI command (%2.2x)\n", buf[0]); scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE)); return 0; fail: -- 1.7.2.3