Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpiolib: extend the critical sections of lookup tables

There are two places in the code where we retrieve a lookup table using
gpiod_find_lookup_table() (which protects the table list with the lookup
table lock) and then use it after the lock is released.

We need to keep the lookup table mutex locked the entire time we're using
the tables. Remove the locking from gpiod_find_lookup_table() and use
guards to protect the code actually using the table objects.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

+15 -15
+15 -15
drivers/gpio/gpiolib.c
··· 3822 3822 const char *dev_id = dev ? dev_name(dev) : NULL; 3823 3823 struct gpiod_lookup_table *table; 3824 3824 3825 - mutex_lock(&gpio_lookup_lock); 3826 - 3827 3825 list_for_each_entry(table, &gpio_lookup_list, list) { 3828 3826 if (table->dev_id && dev_id) { 3829 3827 /* ··· 3829 3831 * a match 3830 3832 */ 3831 3833 if (!strcmp(table->dev_id, dev_id)) 3832 - goto found; 3834 + return table; 3833 3835 } else { 3834 3836 /* 3835 3837 * One of the pointers is NULL, so both must be to have 3836 3838 * a match 3837 3839 */ 3838 3840 if (dev_id == table->dev_id) 3839 - goto found; 3841 + return table; 3840 3842 } 3841 3843 } 3842 - table = NULL; 3843 3844 3844 - found: 3845 - mutex_unlock(&gpio_lookup_lock); 3846 - return table; 3845 + return NULL; 3847 3846 } 3848 3847 3849 3848 static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, ··· 3849 3854 struct gpio_desc *desc = ERR_PTR(-ENOENT); 3850 3855 struct gpiod_lookup_table *table; 3851 3856 struct gpiod_lookup *p; 3857 + 3858 + guard(mutex)(&gpio_lookup_lock); 3852 3859 3853 3860 table = gpiod_find_lookup_table(dev); 3854 3861 if (!table) ··· 3917 3920 struct gpiod_lookup *p; 3918 3921 unsigned int count = 0; 3919 3922 3920 - table = gpiod_find_lookup_table(dev); 3921 - if (!table) 3922 - return -ENOENT; 3923 + scoped_guard(mutex, &gpio_lookup_lock) { 3924 + table = gpiod_find_lookup_table(dev); 3925 + if (!table) 3926 + return -ENOENT; 3923 3927 3924 - for (p = &table->table[0]; p->key; p++) { 3925 - if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) || 3926 - (!con_id && !p->con_id)) 3927 - count++; 3928 + for (p = &table->table[0]; p->key; p++) { 3929 + if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) || 3930 + (!con_id && !p->con_id)) 3931 + count++; 3932 + } 3928 3933 } 3934 + 3929 3935 if (!count) 3930 3936 return -ENOENT; 3931 3937