forked from mirrors/linux
		
	gpioib: do not free unrequested descriptors
If the main loop in linehandle_create() encounters an error, it
unwinds completely by freeing all previously requested GPIO
descriptors.  However, if the error occurs in the beginning of
the loop before that GPIO is requested, then the exit code
attempts to free a null descriptor.  If extrachecks is enabled,
gpiod_free() triggers a WARN_ON.
Instead, keep a separate count of legitimate GPIOs so that only
those are freed.
Cc: stable@vger.kernel.org
Fixes: d7c51b47ac ("gpio: userspace ABI for reading/writing GPIO lines")
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Timur Tabi <timur@codeaurora.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
			
			
This commit is contained in:
		
							parent
							
								
									f241632fd0
								
							
						
					
					
						commit
						ab3dbcf78f
					
				
					 1 changed files with 3 additions and 2 deletions
				
			
		|  | @ -497,7 +497,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) | ||||||
| 	struct gpiohandle_request handlereq; | 	struct gpiohandle_request handlereq; | ||||||
| 	struct linehandle_state *lh; | 	struct linehandle_state *lh; | ||||||
| 	struct file *file; | 	struct file *file; | ||||||
| 	int fd, i, ret; | 	int fd, i, count = 0, ret; | ||||||
| 	u32 lflags; | 	u32 lflags; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&handlereq, ip, sizeof(handlereq))) | 	if (copy_from_user(&handlereq, ip, sizeof(handlereq))) | ||||||
|  | @ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto out_free_descs; | 			goto out_free_descs; | ||||||
| 		lh->descs[i] = desc; | 		lh->descs[i] = desc; | ||||||
|  | 		count = i; | ||||||
| 
 | 
 | ||||||
| 		if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) | 		if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) | ||||||
| 			set_bit(FLAG_ACTIVE_LOW, &desc->flags); | 			set_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||||||
|  | @ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) | ||||||
| out_put_unused_fd: | out_put_unused_fd: | ||||||
| 	put_unused_fd(fd); | 	put_unused_fd(fd); | ||||||
| out_free_descs: | out_free_descs: | ||||||
| 	for (; i >= 0; i--) | 	for (i = 0; i < count; i++) | ||||||
| 		gpiod_free(lh->descs[i]); | 		gpiod_free(lh->descs[i]); | ||||||
| 	kfree(lh->label); | 	kfree(lh->label); | ||||||
| out_free_lh: | out_free_lh: | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Timur Tabi
						Timur Tabi