Commit 0f410adf6b for qemu.org
commit 0f410adf6b0dead1f09938054da639954bda3bc1
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed Aug 26 19:53:31 2026 +0200
scsi: hide MODE SELECT block size change behind a quirk
This is a dangerous operation in that the block size is not
protected by a lock, but it can be written concurrently if
you have a multi-queue virtio-scsi HBA. Put it behind a quirk
that is only enabled by the Q800 machine, since the MODE
SELECT feature was added for A/UX.
Cc: qemu-stable@nongnu.org
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index ab64250c47..1ad3f93b29 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -710,12 +710,14 @@ static void q800_init(Object *obj)
static GlobalProperty hw_compat_q800[] = {
{ "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on" },
+ { "scsi-hd", "quirk_mode_page_set_block_size", "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_set_block_size", "on" },
{ "scsi-cd", "quirk_mode_page_truncated", "on" },
{ "scsi-cd", "vendor", "MATSHITA" },
{ "scsi-cd", "product", "CD-ROM CR-8005" },
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 5bb7a974d6..a42f7d8e77 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1673,8 +1673,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
goto invalid_param;
}
- /* Allow changing the block size */
- if (bd_len) {
+ /*
+ * Allow changing the block size only if the quirk is enabled for it.
+ * Writing s->qdev.blocksize is not thread safe!
+ */
+ if (bd_len && (s->quirks &
+ (1 << SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE))) {
bs = p[5] << 16 | p[6] << 8 | p[7];
/*
@@ -3247,6 +3251,8 @@ static const Property scsi_hd_properties[] = {
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_set_block_size", SCSIDiskState,
+ quirks, SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE, 0),
DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
};
@@ -3352,6 +3358,8 @@ static const Property scsi_cd_properties[] = {
0),
DEFINE_PROP_BIT("quirk_mode_page_truncated", SCSIDiskState, quirks,
SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED, 0),
+ DEFINE_PROP_BIT("quirk_mode_page_set_block_size", SCSIDiskState,
+ quirks, SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE, 0),
};
static void scsi_cd_class_initfn(ObjectClass *klass, const void *data)
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index c60c6e8810..3eab339b0d 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -262,5 +262,6 @@ bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp);
#define SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD 1
#define SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE 2
#define SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED 3
+#define SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE 4
#endif