Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH v3 0/4] ata: libata-scsi: fix ATA PASS-THROUGH(32) handling
@ 2026-11-12 14:01 shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru shao.mingyin
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: shao.mingyin @ 2026-11-12 14:01 UTC (permalink / raw)
  To: dlemoal, cassel, linux-ide; +Cc: linux-kernel, stable

ATA PASS-THROUGH(32) still has translation and completion paths that
interpret fields as if the command used a 12- or 16-byte CDB.

Patch 1 rejects nonzero reserved CONTROL bits, skips the nonexistent
MULTIPLE_COUNT comparison and corrects the
invalid-PROTOCOL field pointer. Patch 2 rejects unsupported service
actions with sense data. Patch 3 honors CK_COND and generates SAT sense
on completion. Patch 4 corrects the remaining invalid-field pointers,
including distinguishing READ/WRITE LONG protocol and count errors.
The four patches can be applied independently; the numbered order groups
the related translation fixes together.

Changes in v3 (Damien Le Moal):
- Patch 1: reject nonzero byte 1 bits 7:5 for ATA-32 with field pointer
  1; retain the device multiple-mode and 12-/16-byte count checks.
  Update its subject, commit message and CONTROL-byte tests.
- Patches 2-4: code unchanged. Patches 2 and 3 keep Damien's
  Reviewed-by tag; patch 4 gains the tag from his v2 review.
Link to v2: https://lore.kernel.org/all/20261111223123952mgPDVsbO8uOyaDWL2KELB@zte.com.cn/

Shao Mingyin (4):
  ata: libata-scsi: reject reserved bits in 32-byte passthru
  ata: libata-scsi: reject unsupported ATA-32 service actions
  ata: libata-scsi: generate SAT sense data for ATA PASS-THROUGH(32)
  ata: libata-scsi: fix remaining passthru field pointers

 drivers/ata/libata-scsi.c | 64 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 46 insertions(+), 18 deletions(-)

---
base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b

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

* [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru
  2026-11-12 14:01 [PATCH v3 0/4] ata: libata-scsi: fix ATA PASS-THROUGH(32) handling shao.mingyin
@ 2026-11-12 14:01 ` shao.mingyin
  2026-11-13  0:20   ` Damien Le Moal
  2026-11-13 15:36   ` Niklas Cassel
  2026-11-12 14:01 ` [PATCH v3 2/4] ata: libata-scsi: reject unsupported ATA-32 service actions shao.mingyin
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 8+ messages in thread
From: shao.mingyin @ 2026-11-12 14:01 UTC (permalink / raw)
  To: dlemoal, cassel, linux-ide; +Cc: linux-kernel, stable

From: Shao Mingyin <shao.mingyin@zte.com.cn>

ATA PASS-THROUGH(32) has no MULTIPLE_COUNT field. Byte 1 is CONTROL,
and bits 7:5 are reserved or obsolete. Interpreting these bits as a
multiple count can issue spurious count mismatch warnings for multiple
commands instead of rejecting the invalid CDB.

Reject nonzero byte 1 bits 7:5 with field pointer 1. Skip the CDB count
comparison for the 32-byte form while retaining the device multiple-mode
check. Also point to byte 10 for invalid PROTOCOL. The 12- and 16-byte
MULTIPLE_COUNT checks remain unchanged.

Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
Suggested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
Changes in v3 (Damien Le Moal):
- Reject nonzero reserved/obsolete bits 7:5 of byte 1 with fp=1.
- Retain the short-CDB count and device multiple-mode checks.
- Update the subject, description and CONTROL-byte test expectations.
v2: https://lore.kernel.org/all/20261111223129430zClEJF8TDgu_h8ZYM843Q@zte.com.cn/

Validation on x86-64 with GCC 13 and UBSAN: a userspace harness compiles
ata_scsi_pass_thru() verbatim with SCSI/device stubs. All 256 CONTROL
values are checked for both non-multiple and multiple commands. Nonzero
bits 7:5 are rejected with field pointer 1; values with those bits clear
are accepted without count warnings. The device multiple-mode check and
12-/16-byte count checks still pass. Field pointers are observed helper
arguments; sense construction and device access use stubs.

 drivers/ata/libata-scsi.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a61fb03312793ca94d81d8061a16c66e786c4cf3..0bc147cf4c0fa50c7d5b84029b7fb1a548c6f1a3 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3388,7 +3388,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 
 	tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]);
 	if (tf->protocol == ATA_PROT_UNKNOWN) {
-		fp = 1;
+		fp = 1 + cdb_offset;
 		goto invalid_fld;
 	}
 
@@ -3573,27 +3573,32 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 		goto invalid_fld;
 	}
 
-	/* sanity check for pio multi commands */
+	/* Sanity check for pio multi commands (not supported with ATA 32). */
+	if (cdb[0] == VARIABLE_LENGTH_CMD && (cdb[1] & 0xe0)) {
+		fp = 1;
+		goto invalid_fld;
+	}
+
 	if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) {
 		fp = 1;
 		goto invalid_fld;
 	}
 
 	if (is_multi_taskfile(tf)) {
-		unsigned int multi_count = 1 << (cdb[1] >> 5);
-
 		if (!dev->multi_count) {
 			ata_scsi_set_sense(dev, scmd, ABORTED_COMMAND,
 					   NO_ADDITIONAL_SENSE_INFORMATION);
 			return 1;
 		}
 
-		/* compare the passed through multi_count
-		 * with the cached multi_count of libata
-		 */
-		if (multi_count != dev->multi_count)
-			ata_dev_warn(dev, "invalid multi_count %u ignored\n",
-				     multi_count);
+		if (cdb[0] != VARIABLE_LENGTH_CMD) {
+			unsigned int multi_count = 1 << (cdb[1] >> 5);
+
+			/* Compare with the cached multiple count of libata. */
+			if (multi_count != dev->multi_count)
+				ata_dev_warn(dev, "invalid multi_count %u ignored\n",
+					     multi_count);
+		}
 	}
 
 	/*

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

* [PATCH v3 2/4] ata: libata-scsi: reject unsupported ATA-32 service actions
  2026-11-12 14:01 [PATCH v3 0/4] ata: libata-scsi: fix ATA PASS-THROUGH(32) handling shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru shao.mingyin
@ 2026-11-12 14:01 ` shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 3/4] ata: libata-scsi: generate SAT sense data for ATA PASS-THROUGH(32) shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 4/4] ata: libata-scsi: fix remaining passthru field pointers shao.mingyin
  3 siblings, 0 replies; 8+ messages in thread
From: shao.mingyin @ 2026-11-12 14:01 UTC (permalink / raw)
  To: dlemoal, cassel, linux-ide; +Cc: linux-kernel, stable

From: Shao Mingyin <shao.mingyin@zte.com.cn>

ata_scsi_var_len_cdb_xlat() returns 1 for an unsupported service action
without setting sense data. ata_scsi_translate() then completes the
command with the SCSI result still zero, reporting SAM_STAT_GOOD even
though no ATA command was issued and no data was transferred.

Set ILLEGAL REQUEST/INVALID FIELD IN CDB before returning, with the
field pointer referring to the SERVICE ACTION field at byte 8.

Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
Changes in v3:
- Code unchanged; retain the Damien Le Moal Reviewed-by tag.
Previous version: https://lore.kernel.org/all/20261111223130666omUZ0JoWtfZjRFRrWPse8@zte.com.cn/

Changes in v2:
- No code changes; regenerate against the series base and keep the
  Reviewed-by tag.
v1: https://lore.kernel.org/all/20261104221102824qAKUWNkiSgZ1yRnQM8hI9@zte.com.cn/

Validation on x86-64 with GCC 13 and UBSAN: a userspace harness compiled
the translation functions verbatim with SCSI/device stubs. For service
action 0x1234, completion changed from result 0 to ILLEGAL REQUEST,
INVALID FIELD IN CDB; the invalid-field helper received field pointer 8.
A valid ATA_32 service action remained accepted.

 drivers/ata/libata-scsi.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 0bc147cf4c0fa50c7d5b84029b7fb1a548c6f1a3..2491e90fb1a5ec6e83234a07eef5342055875937 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -5032,7 +5032,13 @@ static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc)
 	if (sa == ATA_32)
 		return ata_scsi_pass_thru(qc);
 
-	/* unsupported service action */
+	/*
+	 * Unsupported service action.  Set the sense data explicitly, as
+	 * returning 1 without it makes ata_scsi_translate() complete the
+	 * command with the SCSI result still zero, that is, with
+	 * SAM_STAT_GOOD.
+	 */
+	ata_scsi_set_invalid_field(qc->dev, scmd, 8, 0xff);
 	return 1;
 }

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

* [PATCH v3 3/4] ata: libata-scsi: generate SAT sense data for ATA PASS-THROUGH(32)
  2026-11-12 14:01 [PATCH v3 0/4] ata: libata-scsi: fix ATA PASS-THROUGH(32) handling shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 2/4] ata: libata-scsi: reject unsupported ATA-32 service actions shao.mingyin
@ 2026-11-12 14:01 ` shao.mingyin
  2026-11-12 14:01 ` [PATCH v3 4/4] ata: libata-scsi: fix remaining passthru field pointers shao.mingyin
  3 siblings, 0 replies; 8+ messages in thread
From: shao.mingyin @ 2026-11-12 14:01 UTC (permalink / raw)
  To: dlemoal, cassel, linux-ide; +Cc: linux-kernel, stable

From: Shao Mingyin <shao.mingyin@zte.com.cn>

ata_scsi_qc_complete() only recognizes ATA PASS-THROUGH(12) and (16).
The 32-byte form takes the ordinary completion path, so CK_COND is
ignored and errors lack the ATA Status Return descriptor. Successful
commands with CK_COND set therefore complete GOOD instead of returning
CHECK CONDITION with the ATA register values.

Recognize ATA PASS-THROUGH(32) by its service action and read CK_COND
from byte 11 instead of byte 2, which belongs to the variable-length
CDB header.

Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
Cc: stable@vger.kernel.org
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
Changes in v3:
- Code unchanged; retain the Damien Le Moal Reviewed-by tag.
Previous version: https://lore.kernel.org/all/202611112231319337i08AK7ZzIXm9DYFhmtXx@zte.com.cn/

Changes in v2 (Niklas Cassel):
- Move the unrelated invalid-PROTOCOL hunk to patch 1; this patch only
  changes the completion path.
- Regenerate with git format-patch so the index matches the diff.
- Keep the Reviewed-by tag; apart from the moved hunk this patch is
  unchanged from v1.
v1: https://lore.kernel.org/all/202611042211545962bhKeo8yjWPGFgya4g6LG@zte.com.cn/

Validation on x86-64 with GCC 13 and UBSAN: a userspace harness compiled
ata_scsi_qc_complete() verbatim with sense/completion stubs. For ATA_32,
CK_COND in byte 11 now selected pass-through sense and CHECK CONDITION;
CK_COND clear remained GOOD. Error and preexisting-sense paths selected
the pass-through helpers, and byte 2 did not act as CK_COND. The short
CDB paths and unsupported service-action control were also checked.

 drivers/ata/libata-scsi.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 2491e90fb1a5ec6e83234a07eef5342055875937..8ee68937e884369beb4d7ad218612d28c5a080ff 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1888,9 +1888,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 	struct ata_link *link = qc->dev->link;
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	u8 *cdb = cmd->cmnd;
+	u16 cdb_offset = cdb[0] == VARIABLE_LENGTH_CMD ? 9 : 0;
 	bool have_sense = qc->flags & ATA_QCFLAG_SENSE_VALID;
-	bool is_ata_passthru = cdb[0] == ATA_16 || cdb[0] == ATA_12;
-	bool is_ck_cond_request = cdb[2] & 0x20;
+	bool is_ata_passthru = cdb[0] == ATA_16 || cdb[0] == ATA_12 ||
+		(cdb[0] == VARIABLE_LENGTH_CMD &&
+		 get_unaligned_be16(&cdb[8]) == ATA_32);
+	bool is_ck_cond_request = cdb[2 + cdb_offset] & 0x20;
 	bool is_error = qc->err_mask != 0;
 
 	/* For ATA pass thru (SAT) commands, generate a sense block if

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

* [PATCH v3 4/4] ata: libata-scsi: fix remaining passthru field pointers
  2026-11-12 14:01 [PATCH v3 0/4] ata: libata-scsi: fix ATA PASS-THROUGH(32) handling shao.mingyin
                   ` (2 preceding siblings ...)
  2026-11-12 14:01 ` [PATCH v3 3/4] ata: libata-scsi: generate SAT sense data for ATA PASS-THROUGH(32) shao.mingyin
@ 2026-11-12 14:01 ` shao.mingyin
  3 siblings, 0 replies; 8+ messages in thread
From: shao.mingyin @ 2026-11-12 14:01 UTC (permalink / raw)
  To: dlemoal, cassel, linux-ide; +Cc: linux-kernel, stable

From: Shao Mingyin <shao.mingyin@zte.com.cn>

Several error paths in ata_scsi_pass_thru() report field pointers for
the 12- or 16-byte CDB when rejecting a 32-byte CDB. Initiators then
receive INVALID FIELD IN CDB sense data pointing at an unrelated byte.
READ/WRITE LONG also reports PROTOCOL when its sector count is invalid.

Use the PROTOCOL offset and record the FEATURES, SECTOR COUNT and
COMMAND offsets for each CDB format. Report SECTOR COUNT separately
from PROTOCOL when validating READ/WRITE LONG.

Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
Suggested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
Changes in v3:
- Code unchanged; retain the Damien Le Moal Reviewed-by tag.
Previous version: https://lore.kernel.org/all/20261111223133188VjHq0FbmnzuEZWakS-EYD@zte.com.cn/

Changes in v2 (Niklas Cassel):
- Add a separate patch for the remaining PROTOCOL, FEATURES, COMMAND
  and READ/WRITE LONG sector-count field pointers.
v1: https://lore.kernel.org/all/20261104220832716LXKf7OaS9dt1VJ8Q959AG@zte.com.cn/

Validation on x86-64 with GCC 13 and UBSAN: a userspace harness compiled
the translation functions verbatim with SCSI/device stubs. The rejected
32-byte DMA/NCQ and READ/WRITE LONG protocols passed field pointer 10 to
the invalid-field helper, SET FEATURES passed 21, and TPM passed 25.
Invalid READ/WRITE LONG sector counts passed 4, 6 and 23 for 12-, 16-
and 32-byte CDBs. These are helper arguments observed in the harness.

 drivers/ata/libata-scsi.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8ee68937e884369beb4d7ad218612d28c5a080ff..c59e6567a108bbb353c08e921228eadbd231da63 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3383,6 +3383,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 	struct ata_device *dev = qc->dev;
 	const u8 *cdb = scmd->cmnd;
 	u16 fp;
+	u8 feature_offset, nsect_offset, command_offset;
 	u16 cdb_offset = 0;
 
 	/* 7Fh variable length cmd means a ata pass-thru(32) */
@@ -3443,6 +3444,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 		tf->lbah = cdb[12];
 		tf->device = cdb[13];
 		tf->command = cdb[14];
+		feature_offset = 4;
+		nsect_offset = 6;
+		command_offset = 14;
 		break;
 	case ATA_12:
 		/*
@@ -3457,6 +3461,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 		tf->lbah = cdb[7];
 		tf->device = cdb[8];
 		tf->command = cdb[9];
+		feature_offset = 3;
+		nsect_offset = 4;
+		command_offset = 9;
 		break;
 	default:
 		/*
@@ -3482,6 +3489,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 		tf->device = cdb[24];
 		tf->command = cdb[25];
 		tf->auxiliary = get_unaligned_be32(&cdb[28]);
+		feature_offset = 21;
+		nsect_offset = 23;
+		command_offset = 25;
 		break;
 	}
 
@@ -3499,8 +3509,12 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 	case ATA_CMD_READ_LONG_ONCE:
 	case ATA_CMD_WRITE_LONG:
 	case ATA_CMD_WRITE_LONG_ONCE:
-		if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) {
-			fp = 1;
+		if (tf->protocol != ATA_PROT_PIO) {
+			fp = 1 + cdb_offset;
+			goto invalid_fld;
+		}
+		if (tf->nsect != 1) {
+			fp = nsect_offset;
 			goto invalid_fld;
 		}
 		qc->sect_size = scsi_bufflen(scmd);
@@ -3566,13 +3580,13 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 
 	/* We may not issue DMA commands if no DMA mode is set */
 	if (tf->protocol == ATA_PROT_DMA && !ata_dma_enabled(dev)) {
-		fp = 1;
+		fp = 1 + cdb_offset;
 		goto invalid_fld;
 	}
 
 	/* We may not issue NCQ commands to devices not supporting NCQ */
 	if (ata_is_ncq(tf->protocol) && !ata_ncq_enabled(dev)) {
-		fp = 1;
+		fp = 1 + cdb_offset;
 		goto invalid_fld;
 	}
 
@@ -3613,7 +3627,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 	 */
 	if (tf->command == ATA_CMD_SET_FEATURES &&
 	    tf->feature == SETFEATURES_XFER) {
-		fp = (cdb[0] == ATA_16) ? 4 : 3;
+		fp = feature_offset;
 		goto invalid_fld;
 	}
 
@@ -3633,7 +3647,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 	 * can turn off TC features of their system.
 	 */
 	if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) {
-		fp = (cdb[0] == ATA_16) ? 14 : 9;
+		fp = command_offset;
 		goto invalid_fld;
 	}

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

* Re: [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru
  2026-11-12 14:01 ` [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru shao.mingyin
@ 2026-11-13  0:20   ` Damien Le Moal
  2026-11-13  6:05     ` shao.mingyin
  2026-11-13 15:36   ` Niklas Cassel
  1 sibling, 1 reply; 8+ messages in thread
From: Damien Le Moal @ 2026-11-13  0:20 UTC (permalink / raw)
  To: shao.mingyin, cassel, linux-ide; +Cc: linux-kernel, stable

On 11/12/26 23:01, shao.mingyin@zte.com.cn wrote:
> From: Shao Mingyin <shao.mingyin@zte.com.cn>
> 
> ATA PASS-THROUGH(32) has no MULTIPLE_COUNT field. Byte 1 is CONTROL,
> and bits 7:5 are reserved or obsolete. Interpreting these bits as a
> multiple count can issue spurious count mismatch warnings for multiple
> commands instead of rejecting the invalid CDB.
> 
> Reject nonzero byte 1 bits 7:5 with field pointer 1. Skip the CDB count
> comparison for the 32-byte form while retaining the device multiple-mode
> check. Also point to byte 10 for invalid PROTOCOL. The 12- and 16-byte
> MULTIPLE_COUNT checks remain unchanged.
> 
> Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
> Suggested-by: Niklas Cassel <cassel@kernel.org>
> Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>

One nit below. With that fixed,

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>

> +			/* Compare with the cached multiple count of libata. */
> +			if (multi_count != dev->multi_count)
> +				ata_dev_warn(dev, "invalid multi_count %u ignored\n",

Long line. Please split it after "dev,".

> +					     multi_count);
> +		}
>  	}
>  
>  	/*


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru
  2026-11-13  0:20   ` Damien Le Moal
@ 2026-11-13  6:05     ` shao.mingyin
  0 siblings, 0 replies; 8+ messages in thread
From: shao.mingyin @ 2026-11-13  6:05 UTC (permalink / raw)
  To: dlemoal; +Cc: cassel, linux-ide, linux-kernel, stable

On Fri, Nov 13, 2026 at 09:20:15AM +0900, Damien Le Moal wrote:
> Long line. Please split it after "dev,".

Agreed.  I'll split that line and send a v4 with your Reviewed-by on 1/4;
patches 2/4-4/4 are unchanged and keep their tags.

Thanks,
Shao

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

* Re: [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru
  2026-11-12 14:01 ` [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru shao.mingyin
  2026-11-13  0:20   ` Damien Le Moal
@ 2026-11-13 15:36   ` Niklas Cassel
  1 sibling, 0 replies; 8+ messages in thread
From: Niklas Cassel @ 2026-11-13 15:36 UTC (permalink / raw)
  To: shao.mingyin; +Cc: dlemoal, linux-ide, linux-kernel, stable

On Thu, Nov 12, 2026 at 10:01:20PM +0800, shao.mingyin@zte.com.cn wrote:
> From: Shao Mingyin <shao.mingyin@zte.com.cn>
> 
> ATA PASS-THROUGH(32) has no MULTIPLE_COUNT field. Byte 1 is CONTROL,
> and bits 7:5 are reserved or obsolete. Interpreting these bits as a
> multiple count can issue spurious count mismatch warnings for multiple
> commands instead of rejecting the invalid CDB.
> 
> Reject nonzero byte 1 bits 7:5 with field pointer 1. Skip the CDB count
> comparison for the 32-byte form while retaining the device multiple-mode
> check. Also point to byte 10 for invalid PROTOCOL. The 12- and 16-byte
> MULTIPLE_COUNT checks remain unchanged.
> 
> Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
> Suggested-by: Niklas Cassel <cassel@kernel.org>
> Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
> ---
> Changes in v3 (Damien Le Moal):
> - Reject nonzero reserved/obsolete bits 7:5 of byte 1 with fp=1.
> - Retain the short-CDB count and device multiple-mode checks.
> - Update the subject, description and CONTROL-byte test expectations.
> v2: https://lore.kernel.org/all/20261111223129430zClEJF8TDgu_h8ZYM843Q@zte.com.cn/
> 
> Validation on x86-64 with GCC 13 and UBSAN: a userspace harness compiles
> ata_scsi_pass_thru() verbatim with SCSI/device stubs. All 256 CONTROL
> values are checked for both non-multiple and multiple commands. Nonzero
> bits 7:5 are rejected with field pointer 1; values with those bits clear
> are accepted without count warnings. The device multiple-mode check and
> 12-/16-byte count checks still pass. Field pointers are observed helper
> arguments; sense construction and device access use stubs.
> 
>  drivers/ata/libata-scsi.c | 25 +++++++++++++++----------
>  1 file changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index a61fb03312793ca94d81d8061a16c66e786c4cf3..0bc147cf4c0fa50c7d5b84029b7fb1a548c6f1a3 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -3388,7 +3388,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
>  
>  	tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]);
>  	if (tf->protocol == ATA_PROT_UNKNOWN) {
> -		fp = 1;
> +		fp = 1 + cdb_offset;
>  		goto invalid_fld;
>  	}
>  
> @@ -3573,27 +3573,32 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
>  		goto invalid_fld;
>  	}
>  
> -	/* sanity check for pio multi commands */
> +	/* Sanity check for pio multi commands (not supported with ATA 32). */

This comment is misleading.

READ/WRITE MULTIPLE commands are still accepted with the 32-byte CDB, it is
only the count comparison that will be skipped.

libata reads dev->multi_count from IDENTIFY word 59, during probe/revalidate,
and after receiving a ATA_CMD_SET_MULTI command.

The MULTI_COUNT field is obsolete for 12-byte and 16-byte CDBs in SAT-6
(tables 203 and 209), and the 32-byte CDB has no such field (table 210).

The MULTI_COUNT field was only compared with dev->multi_count, and
if there was a mismatch, libata simply printed a warning:
"invalid multi_count %u ignored", yet the command was still sent and
limited by dev->multi_count (see e.g. ata_pio_sectors() for SFF
controllers).


> +	if (cdb[0] == VARIABLE_LENGTH_CMD && (cdb[1] & 0xe0)) {
> +		fp = 1;
> +		goto invalid_fld;
> +	}

In the 32-byte CDB, byte 1 is CONTROL (SAT-6 r2 spec, table 210), and its
bits 7:6 are vendor specific (6.5, table 10), not reserved or obsolete as
the commit message says.

The reserved bits in place of MULTIPLE_COUNT are bits 7:5 of byte 10.

So I think the test should be:

if (cdb[0] == VARIABLE_LENGTH_CMD && (cdb[10] & 0xe0)) {
	fp = 10;
	goto invalid_fld;
}


Kind regards,
Niklas

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

end of thread, other threads:[~2026-11-13 15:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 14:01 [PATCH v3 0/4] ata: libata-scsi: fix ATA PASS-THROUGH(32) handling shao.mingyin
2026-11-12 14:01 ` [PATCH v3 1/4] ata: libata-scsi: reject reserved bits in 32-byte passthru shao.mingyin
2026-11-13  0:20   ` Damien Le Moal
2026-11-13  6:05     ` shao.mingyin
2026-11-13 15:36   ` Niklas Cassel
2026-11-12 14:01 ` [PATCH v3 2/4] ata: libata-scsi: reject unsupported ATA-32 service actions shao.mingyin
2026-11-12 14:01 ` [PATCH v3 3/4] ata: libata-scsi: generate SAT sense data for ATA PASS-THROUGH(32) shao.mingyin
2026-11-12 14:01 ` [PATCH v3 4/4] ata: libata-scsi: fix remaining passthru field pointers shao.mingyin

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