Skip to content

Commit 4e15415

Browse files
committed
gpiolib: improve the robustness of watch/unwatch ioctl()
This makes the new ioctl() a bit more robust - we now check if a line is already being watched and return -EBUSY if the user-space tries to start watching it again. Same for unwatch - return -EBUSY if user-space tries to unwatch a line that's not being watched. Fixes: 51c1064 ("gpiolib: add new ioctl() for monitoring changes in line info") Signed-off-by: Bartosz Golaszewski <[email protected]> Reviewed-by: Linus Walleij <[email protected]>
1 parent dc87f6d commit 4e15415

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

drivers/gpio/gpiolib.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
12271227
void __user *ip = (void __user *)arg;
12281228
struct gpio_desc *desc;
12291229
__u32 offset;
1230+
int hwgpio;
12301231

12311232
/* We fail any subsequent ioctl():s when the chip is gone */
12321233
if (!gc)
@@ -1259,13 +1260,19 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
12591260
if (IS_ERR(desc))
12601261
return PTR_ERR(desc);
12611262

1263+
hwgpio = gpio_chip_hwgpio(desc);
1264+
1265+
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL &&
1266+
test_bit(hwgpio, priv->watched_lines))
1267+
return -EBUSY;
1268+
12621269
gpio_desc_to_lineinfo(desc, &lineinfo);
12631270

12641271
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
12651272
return -EFAULT;
12661273

12671274
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL)
1268-
set_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
1275+
set_bit(hwgpio, priv->watched_lines);
12691276

12701277
return 0;
12711278
} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
@@ -1280,7 +1287,12 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
12801287
if (IS_ERR(desc))
12811288
return PTR_ERR(desc);
12821289

1283-
clear_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
1290+
hwgpio = gpio_chip_hwgpio(desc);
1291+
1292+
if (!test_bit(hwgpio, priv->watched_lines))
1293+
return -EBUSY;
1294+
1295+
clear_bit(hwgpio, priv->watched_lines);
12841296
return 0;
12851297
}
12861298
return -EINVAL;

0 commit comments

Comments
 (0)