aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-07-14 18:14:12 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-07-14 18:14:12 +0100
commit285f64fcbf86dac2be6dbd0a8a32872bcff3cacb (patch)
tree1a30f398cbd4007b5ce8d955e24890eec84c90a6 /hw
parent8482ab545e52f50facacfe1118b22b97462724ab (diff)
parentc0b3607d5938f5ee7fd16ff1e102afe938fd4b39 (diff)
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* SCSI fuzzing fix (Mauro) * pre-install data files in the build directory (Akihiko) * SCSI fixes for Mac OS (Mark) # gpg: Signature made Wed 13 Jul 2022 15:59:00 BST # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: pc-bios/s390-ccw: add -Wno-array-bounds q800: add default vendor and product information for scsi-cd devices q800: add default vendor and product information for scsi-hd devices scsi-disk: allow MODE SELECT block descriptor to set the block size scsi-disk: allow the MODE_PAGE_R_W_ERROR AWRE bit to be changeable for CDROM drives q800: implement compat_props to enable quirk_mode_page_truncated for scsi-cd devices scsi-disk: add SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED quirk for Macintosh scsi-disk: add FORMAT UNIT command q800: implement compat_props to enable quirk_mode_page_vendor_specific_apple for scsi devices scsi-disk: add SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE quirk for Macintosh q800: implement compat_props to enable quirk_mode_sense_rom_use_dbd for scsi-cd devices scsi-disk: add SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD quirk for Macintosh q800: implement compat_props to enable quirk_mode_page_apple_vendor for scsi-cd devices scsi-disk: add MODE_PAGE_APPLE_VENDOR quirk for Macintosh scsi-disk: add new quirks bitmap to SCSIDiskState meson: Prefix each element of firmware path module: Use bundle mechanism datadir: Use bundle mechanism cutils: Introduce bundle mechanism scsi/lsi53c895a: really fix use-after-free in lsi_do_msgout (CVE-2022-0216) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/m68k/q800.c16
-rw-r--r--hw/scsi/lsi53c895a.c3
-rw-r--r--hw/scsi/scsi-disk.c96
-rw-r--r--hw/scsi/trace-events3
4 files changed, 110 insertions, 8 deletions
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 099a758c6f..101ab0f803 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -686,6 +686,21 @@ static void q800_init(MachineState *machine)
}
}
+static GlobalProperty hw_compat_q800[] = {
+ { "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on"},
+ { "scsi-hd", "vendor", " SEAGATE" },
+ { "scsi-hd", "product", " ST225N" },
+ { "scsi-hd", "ver", "1.0 " },
+ { "scsi-cd", "quirk_mode_page_apple_vendor", "on"},
+ { "scsi-cd", "quirk_mode_sense_rom_use_dbd", "on"},
+ { "scsi-cd", "quirk_mode_page_vendor_specific_apple", "on"},
+ { "scsi-cd", "quirk_mode_page_truncated", "on"},
+ { "scsi-cd", "vendor", "MATSHITA" },
+ { "scsi-cd", "product", "CD-ROM CR-8005" },
+ { "scsi-cd", "ver", "1.0k" },
+};
+static const size_t hw_compat_q800_len = G_N_ELEMENTS(hw_compat_q800);
+
static void q800_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -695,6 +710,7 @@ static void q800_machine_class_init(ObjectClass *oc, void *data)
mc->max_cpus = 1;
mc->block_default_type = IF_SCSI;
mc->default_ram_id = "m68k_mac.ram";
+ compat_props_add(mc->compat_props, hw_compat_q800, hw_compat_q800_len);
}
static const TypeInfo q800_machine_typeinfo = {
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 99ea42d49b..ad5f5e5f39 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -1030,7 +1030,7 @@ static void lsi_do_msgout(LSIState *s)
trace_lsi_do_msgout_abort(current_tag);
if (current_req && current_req->req) {
scsi_req_cancel(current_req->req);
- current_req->req = NULL;
+ current_req = NULL;
}
lsi_disconnect(s);
break;
@@ -1056,6 +1056,7 @@ static void lsi_do_msgout(LSIState *s)
/* clear the current I/O process */
if (s->current) {
scsi_req_cancel(s->current->req);
+ current_req = NULL;
}
/* As the current implemented devices scsi_disk and scsi_generic
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 91acb5c0ce..f5cdb9ad4b 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -94,6 +94,7 @@ struct SCSIDiskState {
uint16_t port_index;
uint64_t max_unmap_size;
uint64_t max_io_size;
+ uint32_t quirks;
QEMUBH *bh;
char *version;
char *serial;
@@ -1078,12 +1079,14 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
int page_control)
{
static const int mode_sense_valid[0x3f] = {
+ [MODE_PAGE_VENDOR_SPECIFIC] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
[MODE_PAGE_HD_GEOMETRY] = (1 << TYPE_DISK),
[MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
[MODE_PAGE_CACHING] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
[MODE_PAGE_R_W_ERROR] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
[MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM),
[MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM),
+ [MODE_PAGE_APPLE_VENDOR] = (1 << TYPE_ROM),
};
uint8_t *p = *p_outbuf + 2;
@@ -1185,6 +1188,10 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
case MODE_PAGE_R_W_ERROR:
length = 10;
if (page_control == 1) { /* Changeable Values */
+ if (s->qdev.type == TYPE_ROM) {
+ /* Automatic Write Reallocation Enabled */
+ p[0] = 0x80;
+ }
break;
}
p[0] = 0x80; /* Automatic Write Reallocation Enabled */
@@ -1228,6 +1235,36 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
p[19] = (16 * 176) & 0xff;
break;
+ case MODE_PAGE_APPLE_VENDOR:
+ if (s->quirks & (1 << SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR)) {
+ length = 0x1e;
+ if (page_control == 1) { /* Changeable Values */
+ break;
+ }
+
+ memset(p, 0, length);
+ strcpy((char *)p + 8, "APPLE COMPUTER, INC ");
+ break;
+ } else {
+ return -1;
+ }
+
+ case MODE_PAGE_VENDOR_SPECIFIC:
+ if (s->qdev.type == TYPE_DISK && (s->quirks &
+ (1 << SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE))) {
+ length = 0x2;
+ if (page_control == 1) { /* Changeable Values */
+ p[0] = 0xff;
+ p[1] = 0xff;
+ break;
+ }
+ p[0] = 0;
+ p[1] = 0;
+ break;
+ } else {
+ return -1;
+ }
+
default:
return -1;
}
@@ -1263,10 +1300,27 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
dev_specific_param |= 0x80; /* Readonly. */
}
} else {
- /* MMC prescribes that CD/DVD drives have no block descriptors,
- * and defines no device-specific parameter. */
- dev_specific_param = 0x00;
- dbd = true;
+ if (s->quirks & (1 << SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD)) {
+ /* Use DBD from the request... */
+ dev_specific_param = 0x00;
+
+ /*
+ * ... unless we receive a request for MODE_PAGE_APPLE_VENDOR
+ * which should never return a block descriptor even though DBD is
+ * not set, otherwise CDROM detection fails in MacOS
+ */
+ if (s->quirks & (1 << SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR) &&
+ page == MODE_PAGE_APPLE_VENDOR) {
+ dbd = true;
+ }
+ } else {
+ /*
+ * MMC prescribes that CD/DVD drives have no block descriptors,
+ * and defines no device-specific parameter.
+ */
+ dev_specific_param = 0x00;
+ dbd = true;
+ }
}
if (r->req.cmd.buf[0] == MODE_SENSE) {
@@ -1502,7 +1556,10 @@ static int mode_select_pages(SCSIDiskReq *r, uint8_t *p, int len, bool change)
goto invalid_param;
}
if (page_len > len) {
- goto invalid_param_len;
+ if (!(s->quirks & SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED)) {
+ goto invalid_param_len;
+ }
+ trace_scsi_disk_mode_select_page_truncated(page, page_len, len);
}
if (!change) {
@@ -1537,9 +1594,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
int bd_len;
int pass;
- /* We only support PF=1, SP=0. */
if ((r->req.cmd.buf[1] & 0x11) != 0x10) {
- goto invalid_field;
+ if (!(s->quirks &
+ (1 << SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE))) {
+ /* We only support PF=1, SP=0. */
+ goto invalid_field;
+ }
}
if (len < hdr_len) {
@@ -1556,6 +1616,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
goto invalid_param;
}
+ /* Allow changing the block size */
+ if (bd_len && p[6] != (s->qdev.blocksize >> 8)) {
+ s->qdev.blocksize = p[6] << 8;
+ trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
+ }
+
len -= bd_len;
p += bd_len;
@@ -2127,6 +2193,9 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
trace_scsi_disk_emulate_command_WRITE_SAME(
req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16, r->req.cmd.xfer);
break;
+ case FORMAT_UNIT:
+ trace_scsi_disk_emulate_command_FORMAT_UNIT(r->req.cmd.xfer);
+ break;
default:
trace_scsi_disk_emulate_command_UNKNOWN(buf[0],
scsi_command_name(buf[0]));
@@ -2532,6 +2601,7 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
[VERIFY_10] = &scsi_disk_emulate_reqops,
[VERIFY_12] = &scsi_disk_emulate_reqops,
[VERIFY_16] = &scsi_disk_emulate_reqops,
+ [FORMAT_UNIT] = &scsi_disk_emulate_reqops,
[READ_6] = &scsi_disk_dma_reqops,
[READ_10] = &scsi_disk_dma_reqops,
@@ -3036,6 +3106,9 @@ static Property scsi_hd_properties[] = {
DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0),
DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
5),
+ DEFINE_PROP_BIT("quirk_mode_page_vendor_specific_apple", SCSIDiskState,
+ quirks, SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE,
+ 0),
DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -3084,6 +3157,15 @@ static Property scsi_cd_properties[] = {
DEFAULT_MAX_IO_SIZE),
DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
5),
+ DEFINE_PROP_BIT("quirk_mode_page_apple_vendor", SCSIDiskState, quirks,
+ SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR, 0),
+ DEFINE_PROP_BIT("quirk_mode_sense_rom_use_dbd", SCSIDiskState, quirks,
+ SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD, 0),
+ DEFINE_PROP_BIT("quirk_mode_page_vendor_specific_apple", SCSIDiskState,
+ quirks, SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE,
+ 0),
+ DEFINE_PROP_BIT("quirk_mode_page_truncated", SCSIDiskState, quirks,
+ SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED, 0),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
index 20fb0dc162..ab238293f0 100644
--- a/hw/scsi/trace-events
+++ b/hw/scsi/trace-events
@@ -334,10 +334,13 @@ scsi_disk_emulate_command_UNMAP(size_t xfer) "Unmap (len %zd)"
scsi_disk_emulate_command_VERIFY(int bytchk) "Verify (bytchk %d)"
scsi_disk_emulate_command_WRITE_SAME(int cmd, size_t xfer) "WRITE SAME %d (len %zd)"
scsi_disk_emulate_command_UNKNOWN(int cmd, const char *name) "Unknown SCSI command (0x%2.2x=%s)"
+scsi_disk_emulate_command_FORMAT_UNIT(size_t xfer) "Format Unit (len %zu)"
scsi_disk_dma_command_READ(uint64_t lba, uint32_t len) "Read (sector %" PRId64 ", count %u)"
scsi_disk_dma_command_WRITE(const char *cmd, uint64_t lba, int len) "Write %s(sector %" PRId64 ", count %u)"
scsi_disk_new_request(uint32_t lun, uint32_t tag, const char *line) "Command: lun=%d tag=0x%x data=%s"
scsi_disk_aio_sgio_command(uint32_t tag, uint8_t cmd, uint64_t lba, int len, uint32_t timeout) "disk aio sgio: tag=0x%x cmd=0x%x (sector %" PRId64 ", count %d) timeout=%u"
+scsi_disk_mode_select_page_truncated(int page, int len, int page_len) "page %d expected length %d but received length %d"
+scsi_disk_mode_select_set_blocksize(int blocksize) "set block size to %d"
# scsi-generic.c
scsi_generic_command_complete_noio(void *req, uint32_t tag, int statuc) "Command complete %p tag=0x%x status=%d"