scsi: core: Fix error handler encryption support

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>

authored by Brian Kao and committed by Martin K. Petersen 9a49157d 1523d50a

+30
+24
drivers/scsi/scsi_error.c
··· 1063 unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) 1064 { 1065 struct scsi_device *sdev = scmd->device; 1066 1067 /* 1068 * We need saved copies of a number of fields - this is because ··· 1118 (sdev->lun << 5 & 0xe0); 1119 1120 /* 1121 * Zero the sense buffer. The scsi spec mandates that any 1122 * untransferred sense data should be interpreted as being zero. 1123 */ ··· 1146 */ 1147 void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) 1148 { 1149 /* 1150 * Restore original data 1151 */ ··· 1162 scmd->underflow = ses->underflow; 1163 scmd->prot_op = ses->prot_op; 1164 scmd->eh_eflags = ses->eh_eflags; 1165 } 1166 EXPORT_SYMBOL(scsi_eh_restore_cmnd); 1167
··· 1063 unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) 1064 { 1065 struct scsi_device *sdev = scmd->device; 1066 + #ifdef CONFIG_BLK_INLINE_ENCRYPTION 1067 + struct request *rq = scsi_cmd_to_rq(scmd); 1068 + #endif 1069 1070 /* 1071 * We need saved copies of a number of fields - this is because ··· 1115 (sdev->lun << 5 & 0xe0); 1116 1117 /* 1118 + * Encryption must be disabled for the commands submitted by the error handler. 1119 + * Hence, clear the encryption context information. 1120 + */ 1121 + #ifdef CONFIG_BLK_INLINE_ENCRYPTION 1122 + ses->rq_crypt_keyslot = rq->crypt_keyslot; 1123 + ses->rq_crypt_ctx = rq->crypt_ctx; 1124 + 1125 + rq->crypt_keyslot = NULL; 1126 + rq->crypt_ctx = NULL; 1127 + #endif 1128 + 1129 + /* 1130 * Zero the sense buffer. The scsi spec mandates that any 1131 * untransferred sense data should be interpreted as being zero. 1132 */ ··· 1131 */ 1132 void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) 1133 { 1134 + #ifdef CONFIG_BLK_INLINE_ENCRYPTION 1135 + struct request *rq = scsi_cmd_to_rq(scmd); 1136 + #endif 1137 + 1138 /* 1139 * Restore original data 1140 */ ··· 1143 scmd->underflow = ses->underflow; 1144 scmd->prot_op = ses->prot_op; 1145 scmd->eh_eflags = ses->eh_eflags; 1146 + 1147 + #ifdef CONFIG_BLK_INLINE_ENCRYPTION 1148 + rq->crypt_keyslot = ses->rq_crypt_keyslot; 1149 + rq->crypt_ctx = ses->rq_crypt_ctx; 1150 + #endif 1151 } 1152 EXPORT_SYMBOL(scsi_eh_restore_cmnd); 1153
+6
include/scsi/scsi_eh.h
··· 41 unsigned char cmnd[32]; 42 struct scsi_data_buffer sdb; 43 struct scatterlist sense_sgl; 44 }; 45 46 extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
··· 41 unsigned char cmnd[32]; 42 struct scsi_data_buffer sdb; 43 struct scatterlist sense_sgl; 44 + 45 + /* struct request fields */ 46 + #ifdef CONFIG_BLK_INLINE_ENCRYPTION 47 + struct bio_crypt_ctx *rq_crypt_ctx; 48 + struct blk_crypto_keyslot *rq_crypt_keyslot; 49 + #endif 50 }; 51 52 extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,