From: Damien Le Moal <dlemoal@kernel.org>
To: Zhao Gongyi <zhaogongyi@bytedance.com>,
Niklas Cassel <cassel@kernel.org>
Cc: linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH v2] ata: libata-scsi: reject data-in commands with a data-out buffer
Date: Wed, 28 Oct 2026 20:59:53 +0700 [thread overview]
Message-ID: <8ec9e401-4c00-42fe-b997-228e05ed9c2a@kernel.org> (raw)
In-Reply-To: <20261028113903.19569-1-zhaogongyi@bytedance.com>
On 2026/10/28 18:39, Zhao Gongyi wrote:
> ata_scsi_rbuf_fill() copies simulated data-in replies to the SCSI
> scatterlist without checking the request direction. SG_IO can supply a
> data-in CDB with DMA_TO_DEVICE, in which case the pages may have been
> pinned without write access. In the reported case, copying the reply
> into the shared zero page caused a kernel page fault.
Sure that can happen if the user sets up the SG_IO incorrectly.
> Translated commands can reach the same kind of mismatch. In particular,
No they cannot, as long as the kernel is correct for internally issued commands.
But t is not clear here if you are still talking about commands passed through
SG_IO.
> the ZBC IN and GET PHYSICAL ELEMENT STATUS completion handlers rewrite
> the receive buffer, including when the device aborts the command.
> Checking the direction only in ata_scsi_rbuf_fill() leaves those paths
> unprotected.
>
> Reject DMA_TO_DEVICE requests in the simulated-command path. After
> translation, reject a DMA_TO_DEVICE request whose ATA taskfile performs
> a data-in transfer, before issuing it to the device. Return ILLEGAL
> REQUEST / INVALID FIELD IN CDB for both cases.
Why is this being checked here and not in the SCSI layer (sg driver and bsg)? It
seems sensible to check this there.
> The original reproducer panicked in ata_scsi_rbuf_fill() on all four
> runs with the unpatched kernel. With this patch applied, it completed
> without a crash. A diagnostic run confirmed CHECK CONDITION with
> ILLEGAL REQUEST / INVALID FIELD IN CDB.
>
> Built an x86_64 defconfig kernel from the current Linus tree and booted it
> in QEMU with an ata_piix disk. Normal INQUIRY and READ(10) SG_IO requests
> succeeded. Each command declared as SG_DXFER_TO_DEV returned CHECK
> CONDITION with ILLEGAL REQUEST / INVALID FIELD IN CDB. No kernel
> warnings or oopses appeared. ZBC IN and GET PHYSICAL ELEMENT STATUS
> were checked by code inspection; the test disk does not support them.
Test details are not needed in the commit message.
>
> Suggested-by: Niklas Cassel <cassel@kernel.org>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Link: https://lore.kernel.org/r/20261027090809.94126-1-zhaogongyi@bytedance.com
> Cc: stable@vger.kernel.org
> Signed-off-by: Zhao Gongyi <zhaogongyi@bytedance.com>
> ---
> Changes since v1:
> - Rebase on Linus' tree and use INVALID_FIELD_IN_CDB with the current
> ata_scsi_set_sense() signature.
> - Reject mismatched translated data-in commands before issuing them,
> as suggested by Niklas Cassel.
> - Remove the deprecated Assisted-by trailer.
>
> drivers/ata/libata-scsi.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index a61fb0331..a5170a36a 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -2048,6 +2048,19 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
> if (xlat_func(qc))
> goto done;
>
> + /*
> + * A data-out request may contain pages pinned without write access.
> + * Reject a translated data-in command before issuing it, since its
> + * completion handler may write to the buffer even if the device fails.
> + */
> + if (unlikely(cmd->sc_data_direction == DMA_TO_DEVICE &&
> + ata_is_data(qc->tf.protocol) &&
> + !(qc->tf.flags & ATA_TFLAG_WRITE))) {
> + ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST,
> + INVALID_FIELD_IN_CDB);
The CDB may be perfectly correct. The error is in the SG_IO descriptor setup,
NOT in the CDB. So returning invalid field in CDB seems very misleading.
This is not something that SAT defines as far as I know, so we need to find a
sense code that is more informative. Please have a loo at
include/scsi/scsi_sense.h to see if something better exist.
> + goto done;
> + }
> +
> return ata_scsi_qc_issue(ap, qc);
>
> done:
> @@ -2079,6 +2092,13 @@ 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,
> + INVALID_FIELD_IN_CDB);
> + return;
> + }
> +
> spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
>
> memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
--
Damien Le Moal
Western Digital Research
next prev parent reply other threads:[~2026-10-28 13:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
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
2026-10-28 11:39 ` [PATCH v2] ata: libata-scsi: reject data-in commands with a data-out buffer Zhao Gongyi
2026-10-28 11:53 ` sashiko-bot
2026-10-28 13:16 ` Niklas Cassel
2026-10-28 13:59 ` Damien Le Moal [this message]
2026-10-29 4:37 ` Zhao Gongyi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8ec9e401-4c00-42fe-b997-228e05ed9c2a@kernel.org \
--to=dlemoal@kernel.org \
--cc=cassel@kernel.org \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=zhaogongyi@bytedance.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.