On Fri, 18 Oct 2019, Martin K. Petersen wrote: > > (Sorry, zhengbin, you opened a can of worms. This is some of our oldest > and most arcane code in SCSI) > A call to set_host_byte(cmd, x) or set_msg_byte(cmd, x) when x & 0x80 is set clobbers the most significant bytes in cmd->result. Avoid this implicit sign extension when shifting bits by using an unsigned formal parameter. This is a theoretical bug, found by inspection, so I'm sending an untested RFC patch. I didn't try to find possible callers that might pass a negative parameter and neither did I check whether the clobber might be intentional... diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 76ed5e4acd38..ae814fa68bb8 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -306,17 +306,17 @@ static inline struct scsi_data_buffer *scsi_prot(struct scsi_cmnd *cmd) #define scsi_for_each_prot_sg(cmd, sg, nseg, __i) \ for_each_sg(scsi_prot_sglist(cmd), sg, nseg, __i) -static inline void set_msg_byte(struct scsi_cmnd *cmd, char status) +static inline void set_msg_byte(struct scsi_cmnd *cmd, unsigned char status) { cmd->result = (cmd->result & 0xffff00ff) | (status << 8); } -static inline void set_host_byte(struct scsi_cmnd *cmd, char status) +static inline void set_host_byte(struct scsi_cmnd *cmd, unsigned char status) { cmd->result = (cmd->result & 0xff00ffff) | (status << 16); } -static inline void set_driver_byte(struct scsi_cmnd *cmd, char status) +static inline void set_driver_byte(struct scsi_cmnd *cmd, unsigned char status) { cmd->result = (cmd->result & 0x00ffffff) | (status << 24); }