mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	scsi: sg: check for valid direction before starting the request
Check for a valid direction before starting the request, otherwise we risk running into an assertion in the scsi midlayer checking for valid requests. [mkp: fixed typo] Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Link: http://www.spinics.net/lists/linux-scsi/msg104400.html Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Hannes Reinecke <hare@suse.com> Tested-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									1bc0eb0446
								
							
						
					
					
						commit
						28676d869b
					
				
					 1 changed files with 34 additions and 12 deletions
				
			
		| 
						 | 
					@ -663,18 +663,14 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 | 
				
			||||||
	 * is a non-zero input_size, so emit a warning.
 | 
						 * is a non-zero input_size, so emit a warning.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
 | 
						if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
 | 
				
			||||||
		static char cmd[TASK_COMM_LEN];
 | 
							printk_ratelimited(KERN_WARNING
 | 
				
			||||||
		if (strcmp(current->comm, cmd)) {
 | 
									   "sg_write: data in/out %d/%d bytes "
 | 
				
			||||||
			printk_ratelimited(KERN_WARNING
 | 
									   "for SCSI command 0x%x-- guessing "
 | 
				
			||||||
					   "sg_write: data in/out %d/%d bytes "
 | 
									   "data in;\n   program %s not setting "
 | 
				
			||||||
					   "for SCSI command 0x%x-- guessing "
 | 
									   "count and/or reply_len properly\n",
 | 
				
			||||||
					   "data in;\n   program %s not setting "
 | 
									   old_hdr.reply_len - (int)SZ_SG_HEADER,
 | 
				
			||||||
					   "count and/or reply_len properly\n",
 | 
									   input_size, (unsigned int) cmnd[0],
 | 
				
			||||||
					   old_hdr.reply_len - (int)SZ_SG_HEADER,
 | 
									   current->comm);
 | 
				
			||||||
					   input_size, (unsigned int) cmnd[0],
 | 
					 | 
				
			||||||
					   current->comm);
 | 
					 | 
				
			||||||
			strcpy(cmd, current->comm);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);
 | 
						k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);
 | 
				
			||||||
	return (k < 0) ? k : count;
 | 
						return (k < 0) ? k : count;
 | 
				
			||||||
| 
						 | 
					@ -753,6 +749,29 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool sg_is_valid_dxfer(sg_io_hdr_t *hp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (hp->dxfer_direction) {
 | 
				
			||||||
 | 
						case SG_DXFER_NONE:
 | 
				
			||||||
 | 
							if (hp->dxferp || hp->dxfer_len > 0)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						case SG_DXFER_TO_DEV:
 | 
				
			||||||
 | 
						case SG_DXFER_FROM_DEV:
 | 
				
			||||||
 | 
						case SG_DXFER_TO_FROM_DEV:
 | 
				
			||||||
 | 
							if (!hp->dxferp || hp->dxfer_len == 0)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						case SG_DXFER_UNKNOWN:
 | 
				
			||||||
 | 
							if ((!hp->dxferp && hp->dxfer_len) ||
 | 
				
			||||||
 | 
							    (hp->dxferp && hp->dxfer_len == 0))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
sg_common_write(Sg_fd * sfp, Sg_request * srp,
 | 
					sg_common_write(Sg_fd * sfp, Sg_request * srp,
 | 
				
			||||||
		unsigned char *cmnd, int timeout, int blocking)
 | 
							unsigned char *cmnd, int timeout, int blocking)
 | 
				
			||||||
| 
						 | 
					@ -773,6 +792,9 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
 | 
				
			||||||
			"sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
 | 
								"sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
 | 
				
			||||||
			(int) cmnd[0], (int) hp->cmd_len));
 | 
								(int) cmnd[0], (int) hp->cmd_len));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!sg_is_valid_dxfer(hp))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	k = sg_start_req(srp, cmnd);
 | 
						k = sg_start_req(srp, cmnd);
 | 
				
			||||||
	if (k) {
 | 
						if (k) {
 | 
				
			||||||
		SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp,
 | 
							SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue