mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ata: libata-scsi: reject to-device transfers for simulated commands
@ 2026-10-27  9:08 Zhao Gongyi
  2026-10-27 21:22 ` Niklas Cassel
  0 siblings, 1 reply; 2+ messages in thread
From: Zhao Gongyi @ 2026-10-27  9:08 UTC (permalink / raw)
  To: dlemoal, cassel; +Cc: linux-ide, linux-kernel, Zhao Gongyi

ata_scsi_rbuf_fill() emulates commands that only return data to the
initiator (INQUIRY, MODE SENSE, READ CAPACITY, REPORT LUNS and
MAINTENANCE IN).  It builds the reply in a kernel buffer and then copies
it into the request's scatterlist without looking at the transfer
direction.

The scatterlist is built from the user buffer by the passthrough paths
(bsg/SG_IO), which derive the data direction from the transfer lengths
supplied by userspace.  A request can therefore carry a data-in command
while declaring a to-device transfer.  The buffer is then pinned for
reading only.  In the observed crash, an anonymous VMA covered the
buffer address, but its page was not populated; the read-only pin
resolved to the shared zero page.  Copying the reply into that
scatterlist attempted to write to a read-only kernel page:

  BUG: unable to handle page fault for address: ffff888005140038
  #PF: supervisor write access in kernel mode
  #PF: error_code(0x0003) - permissions violation
  PGD 7d00067 P4D 7d00067 PUD 7d01067 PMD 80000000050001a1
  RIP: 0010:memcpy_orig+0x68/0x140
  Call Trace:
   sg_copy_buffer+0x1e2/0x250
   ata_scsi_rbuf_fill+0xe6/0x280
   __ata_scsi_queuecmd+0x12e4/0x1580
   scsi_queue_rq+0x1ff7/0x33d0
   blk_execute_rq+0x1c5/0x390
   scsi_bsg_sg_io_fn+0x3bc/0xb00
   bsg_ioctl+0x3ef/0x550

The faulting address falls inside the kernel rodata mapping and matches
empty_zero_page (Kernel rodata 05000000-05dc2fff, empty_zero_page at
physical 0x5140000), which confirms the reply copy attempted to write
to the shared read-only zero page.

Even when the pinned page happens to be writable the reply silently
corrupts the user buffer, since it was not mapped for writing.  Reject
to-device transfers for these commands with an ILLEGAL REQUEST sense
instead of copying the reply into them.  This is the same class of
problem as commit 5da5231bb478 ("libata: if T_LENGTH is zero, dma
direction should be DMA_NONE"), which rejects inconsistent data
directions for ATA pass-through commands.

Reproduced on 7.3.0-rc6 with the syzkaller C reproducer against an
ata_piix disk (/dev/bsg/0:0:0:0): the unpatched kernel panics on every
attempt (4/4), while with this change the request completes with CHECK
CONDITION and the reproducer survives 5/5 runs.

Standard-length CDBs behave the same way.  A correctly directed 6-byte
INQUIRY still completes normally, while a 6-byte INQUIRY and a 10-byte
READ CAPACITY(10) declared as to-device are rejected with CHECK
CONDITION; on the unpatched kernel those same requests silently write
the reply into the caller's page (the transfer has to be page aligned to
take the zero-copy mapping path, otherwise it bounces through a kernel
buffer and nothing is visible to the caller).

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Zhao Gongyi <zhaogongyi@bytedance.com>
---
 drivers/ata/libata-scsi.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b3666519b..8b65b896e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2009,6 +2009,12 @@ static void ata_scsi_rbuf_fill(struct ata_device *dev, struct scsi_cmnd *cmd,
 	unsigned long flags;
 	unsigned int len;
 
+	/* A data-out request may contain pages pinned without write access. */
+	if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+		ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+		return;
+	}
+
 	spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
 
 	memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
-- 
2.39.5 (Apple Git-154)

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-27 21:22 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-27  9:08 [PATCH] ata: libata-scsi: reject to-device transfers for simulated commands Zhao Gongyi
2026-10-27 21:22 ` Niklas Cassel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®