]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: core: Fix error handler encryption support
authorBrian Kao <powenkao@google.com>
Thu, 18 Dec 2025 03:17:23 +0000 (03:17 +0000)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sun, 4 Jan 2026 20:16:20 +0000 (15:16 -0500)
Some low-level drivers (LLD) access block layer crypto fields, such as
rq->crypt_keyslot and rq->crypt_ctx within `struct request`, to
configure hardware for inline encryption.  However, SCSI Error Handling
(EH) commands (e.g., TEST UNIT READY, START STOP UNIT) should not
involve any encryption setup.

To prevent drivers from erroneously applying crypto settings during EH,
this patch saves the original values of rq->crypt_keyslot and
rq->crypt_ctx before an EH command is prepared via scsi_eh_prep_cmnd().
These fields in the 'struct request' are then set to NULL.  The original
values are restored in scsi_eh_restore_cmnd() after the EH command
completes.

This ensures that the block layer crypto context does not leak into EH
command execution.

Signed-off-by: Brian Kao <powenkao@google.com>
Link: https://patch.msgid.link/20251218031726.2642834-1-powenkao@google.com
Cc: stable@vger.kernel.org
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_error.c
include/scsi/scsi_eh.h

index f869108fd9693cfdcfb503a0504eec73c86733f4..eebca96c1fc1560b1439a87a67cefa0048bb3fe2 100644 (file)
@@ -1063,6 +1063,9 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
                        unsigned char *cmnd, int cmnd_size, unsigned sense_bytes)
 {
        struct scsi_device *sdev = scmd->device;
+#ifdef CONFIG_BLK_INLINE_ENCRYPTION
+       struct request *rq = scsi_cmd_to_rq(scmd);
+#endif
 
        /*
         * We need saved copies of a number of fields - this is because
@@ -1114,6 +1117,18 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
                scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
                        (sdev->lun << 5 & 0xe0);
 
+       /*
+        * Encryption must be disabled for the commands submitted by the error handler.
+        * Hence, clear the encryption context information.
+        */
+#ifdef CONFIG_BLK_INLINE_ENCRYPTION
+       ses->rq_crypt_keyslot = rq->crypt_keyslot;
+       ses->rq_crypt_ctx = rq->crypt_ctx;
+
+       rq->crypt_keyslot = NULL;
+       rq->crypt_ctx = NULL;
+#endif
+
        /*
         * Zero the sense buffer.  The scsi spec mandates that any
         * untransferred sense data should be interpreted as being zero.
@@ -1131,6 +1146,10 @@ EXPORT_SYMBOL(scsi_eh_prep_cmnd);
  */
 void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 {
+#ifdef CONFIG_BLK_INLINE_ENCRYPTION
+       struct request *rq = scsi_cmd_to_rq(scmd);
+#endif
+
        /*
         * Restore original data
         */
@@ -1143,6 +1162,11 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
        scmd->underflow = ses->underflow;
        scmd->prot_op = ses->prot_op;
        scmd->eh_eflags = ses->eh_eflags;
+
+#ifdef CONFIG_BLK_INLINE_ENCRYPTION
+       rq->crypt_keyslot = ses->rq_crypt_keyslot;
+       rq->crypt_ctx = ses->rq_crypt_ctx;
+#endif
 }
 EXPORT_SYMBOL(scsi_eh_restore_cmnd);
 
index 1ae08e81339fac2a6da230a1abc60abb6fbdbaa6..15679be90c5c3dd6641e4b431f477639d3f7b1f1 100644 (file)
@@ -41,6 +41,12 @@ struct scsi_eh_save {
        unsigned char cmnd[32];
        struct scsi_data_buffer sdb;
        struct scatterlist sense_sgl;
+
+       /* struct request fields */
+#ifdef CONFIG_BLK_INLINE_ENCRYPTION
+       struct bio_crypt_ctx *rq_crypt_ctx;
+       struct blk_crypto_keyslot *rq_crypt_keyslot;
+#endif
 };
 
 extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,