mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	cdc-acm: fix race between callback and unthrottle
Abn URB may be may marked free only after the buffer has been processed or there is a small window during which it could be submitted on another CPU and overwrite an unprocessed buffer Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									c0ab6bb059
								
							
						
					
					
						commit
						36e59e0d70
					
				
					 1 changed files with 10 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -417,25 +417,33 @@ static void acm_read_bulk_callback(struct urb *urb)
 | 
			
		|||
	struct acm_rb *rb = urb->context;
 | 
			
		||||
	struct acm *acm = rb->instance;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	int status = urb->status;
 | 
			
		||||
 | 
			
		||||
	dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__,
 | 
			
		||||
					rb->index, urb->actual_length);
 | 
			
		||||
	set_bit(rb->index, &acm->read_urbs_free);
 | 
			
		||||
 | 
			
		||||
	if (!acm->dev) {
 | 
			
		||||
		set_bit(rb->index, &acm->read_urbs_free);
 | 
			
		||||
		dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (urb->status) {
 | 
			
		||||
		set_bit(rb->index, &acm->read_urbs_free);
 | 
			
		||||
		dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
 | 
			
		||||
							__func__, urb->status);
 | 
			
		||||
							__func__, status);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	usb_mark_last_busy(acm->dev);
 | 
			
		||||
 | 
			
		||||
	acm_process_read_urb(acm, urb);
 | 
			
		||||
	/*
 | 
			
		||||
	 * Unthrottle may run on another CPU which needs to see events
 | 
			
		||||
	 * in the same order. Submission has an implict barrier
 | 
			
		||||
	 */
 | 
			
		||||
	smp_mb__before_atomic();
 | 
			
		||||
	set_bit(rb->index, &acm->read_urbs_free);
 | 
			
		||||
 | 
			
		||||
	/* throttle device if requested by tty */
 | 
			
		||||
	spin_lock_irqsave(&acm->read_lock, flags);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue