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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'gpio-fixes-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:
"Some last-minute fixes for this release from the GPIO subsystem.

The first two address a regression in performance reported to me after
the conversion to using SRCU in GPIOLIB that was merged during the
v6.9 merge window. The second patch is not technically a fix but since
after the first one we no longer need to use a per-descriptor SRCU
struct, I think it's worth to simplify the code before it gets
released on Sunday.

The next two commits fix two memory issues: one use-after-free bug and
one instance of possibly leaking kernel stack memory to user-space.

Summary:

- fix a performance regression in GPIO requesting and releasing after
the conversion to SRCU

- fix a use-after-free bug due to a race-condition

- fix leaking stack memory to user-space in a GPIO uABI corner case"

* tag 'gpio-fixes-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
gpiolib: cdev: fix uninitialised kfifo
gpiolib: cdev: Fix use after free in lineinfo_changed_notify
gpiolib: use a single SRCU struct for all GPIO descriptors
gpiolib: fix the speed of descriptor label setting with SRCU

+63 -30
+16 -2
drivers/gpio/gpiolib-cdev.c
··· 1193 1193 struct gpio_v2_line_config *lc, 1194 1194 unsigned int line_idx, u64 edflags) 1195 1195 { 1196 + u64 eflags; 1197 + int ret; 1196 1198 u64 active_edflags = READ_ONCE(line->edflags); 1197 1199 unsigned int debounce_period_us = 1198 1200 gpio_v2_line_config_debounce_period(lc, line_idx); ··· 1206 1204 /* sw debounced and still will be...*/ 1207 1205 if (debounce_period_us && READ_ONCE(line->sw_debounced)) { 1208 1206 line_set_debounce_period(line, debounce_period_us); 1207 + /* 1208 + * ensure event fifo is initialised if edge detection 1209 + * is now enabled. 1210 + */ 1211 + eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS; 1212 + if (eflags && !kfifo_initialized(&line->req->events)) { 1213 + ret = kfifo_alloc(&line->req->events, 1214 + line->req->event_buffer_size, 1215 + GFP_KERNEL); 1216 + if (ret) 1217 + return ret; 1218 + } 1209 1219 return 0; 1210 1220 } 1211 1221 ··· 2365 2351 2366 2352 dflags = READ_ONCE(desc->flags); 2367 2353 2368 - scoped_guard(srcu, &desc->srcu) { 2354 + scoped_guard(srcu, &desc->gdev->desc_srcu) { 2369 2355 label = gpiod_get_label(desc); 2370 2356 if (label && test_bit(FLAG_REQUESTED, &dflags)) 2371 2357 strscpy(info->consumer, label, ··· 2813 2799 struct gpio_chardev_data *cdev = file->private_data; 2814 2800 struct gpio_device *gdev = cdev->gdev; 2815 2801 2816 - bitmap_free(cdev->watched_lines); 2817 2802 blocking_notifier_chain_unregister(&gdev->device_notifier, 2818 2803 &cdev->device_unregistered_nb); 2819 2804 blocking_notifier_chain_unregister(&gdev->line_state_notifier, 2820 2805 &cdev->lineinfo_changed_nb); 2806 + bitmap_free(cdev->watched_lines); 2821 2807 gpio_device_put(gdev); 2822 2808 kfree(cdev); 2823 2809
+36 -22
drivers/gpio/gpiolib.c
··· 101 101 102 102 const char *gpiod_get_label(struct gpio_desc *desc) 103 103 { 104 + struct gpio_desc_label *label; 104 105 unsigned long flags; 105 106 106 107 flags = READ_ONCE(desc->flags); ··· 109 108 !test_bit(FLAG_REQUESTED, &flags)) 110 109 return "interrupt"; 111 110 112 - return test_bit(FLAG_REQUESTED, &flags) ? 113 - srcu_dereference(desc->label, &desc->srcu) : NULL; 111 + if (!test_bit(FLAG_REQUESTED, &flags)) 112 + return NULL; 113 + 114 + label = srcu_dereference_check(desc->label, &desc->gdev->desc_srcu, 115 + srcu_read_lock_held(&desc->gdev->desc_srcu)); 116 + 117 + return label->str; 118 + } 119 + 120 + static void desc_free_label(struct rcu_head *rh) 121 + { 122 + kfree(container_of(rh, struct gpio_desc_label, rh)); 114 123 } 115 124 116 125 static int desc_set_label(struct gpio_desc *desc, const char *label) 117 126 { 118 - const char *new = NULL, *old; 127 + struct gpio_desc_label *new = NULL, *old; 119 128 120 129 if (label) { 121 - new = kstrdup_const(label, GFP_KERNEL); 130 + new = kzalloc(struct_size(new, str, strlen(label) + 1), 131 + GFP_KERNEL); 122 132 if (!new) 123 133 return -ENOMEM; 134 + 135 + strcpy(new->str, label); 124 136 } 125 137 126 138 old = rcu_replace_pointer(desc->label, new, 1); 127 - synchronize_srcu(&desc->srcu); 128 - kfree_const(old); 139 + if (old) 140 + call_srcu(&desc->gdev->desc_srcu, &old->rh, desc_free_label); 129 141 130 142 return 0; 131 143 } ··· 709 695 static void gpiodev_release(struct device *dev) 710 696 { 711 697 struct gpio_device *gdev = to_gpio_device(dev); 712 - unsigned int i; 713 698 714 - for (i = 0; i < gdev->ngpio; i++) 715 - cleanup_srcu_struct(&gdev->descs[i].srcu); 699 + /* Call pending kfree()s for descriptor labels. */ 700 + synchronize_srcu(&gdev->desc_srcu); 701 + cleanup_srcu_struct(&gdev->desc_srcu); 716 702 717 703 ida_free(&gpio_ida, gdev->id); 718 704 kfree_const(gdev->label); ··· 989 975 if (ret) 990 976 goto err_remove_from_list; 991 977 978 + ret = init_srcu_struct(&gdev->desc_srcu); 979 + if (ret) 980 + goto err_cleanup_gdev_srcu; 981 + 992 982 #ifdef CONFIG_PINCTRL 993 983 INIT_LIST_HEAD(&gdev->pin_ranges); 994 984 #endif ··· 1000 982 if (gc->names) { 1001 983 ret = gpiochip_set_desc_names(gc); 1002 984 if (ret) 1003 - goto err_cleanup_gdev_srcu; 985 + goto err_cleanup_desc_srcu; 1004 986 } 1005 987 ret = gpiochip_set_names(gc); 1006 988 if (ret) 1007 - goto err_cleanup_gdev_srcu; 989 + goto err_cleanup_desc_srcu; 1008 990 1009 991 ret = gpiochip_init_valid_mask(gc); 1010 992 if (ret) 1011 - goto err_cleanup_gdev_srcu; 993 + goto err_cleanup_desc_srcu; 1012 994 1013 995 for (desc_index = 0; desc_index < gc->ngpio; desc_index++) { 1014 996 struct gpio_desc *desc = &gdev->descs[desc_index]; 1015 - 1016 - ret = init_srcu_struct(&desc->srcu); 1017 - if (ret) 1018 - goto err_cleanup_desc_srcu; 1019 997 1020 998 if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) { 1021 999 assign_bit(FLAG_IS_OUT, ··· 1024 1010 1025 1011 ret = of_gpiochip_add(gc); 1026 1012 if (ret) 1027 - goto err_cleanup_desc_srcu; 1013 + goto err_free_valid_mask; 1028 1014 1029 1015 ret = gpiochip_add_pin_ranges(gc); 1030 1016 if (ret) ··· 1071 1057 gpiochip_remove_pin_ranges(gc); 1072 1058 err_remove_of_chip: 1073 1059 of_gpiochip_remove(gc); 1074 - err_cleanup_desc_srcu: 1075 - while (desc_index--) 1076 - cleanup_srcu_struct(&gdev->descs[desc_index].srcu); 1060 + err_free_valid_mask: 1077 1061 gpiochip_free_valid_mask(gc); 1062 + err_cleanup_desc_srcu: 1063 + cleanup_srcu_struct(&gdev->desc_srcu); 1078 1064 err_cleanup_gdev_srcu: 1079 1065 cleanup_srcu_struct(&gdev->srcu); 1080 1066 err_remove_from_list: ··· 2404 2390 if (!test_bit(FLAG_REQUESTED, &desc->flags)) 2405 2391 return NULL; 2406 2392 2407 - guard(srcu)(&desc->srcu); 2393 + guard(srcu)(&desc->gdev->desc_srcu); 2408 2394 2409 2395 label = kstrdup(gpiod_get_label(desc), GFP_KERNEL); 2410 2396 if (!label) ··· 4795 4781 } 4796 4782 4797 4783 for_each_gpio_desc(gc, desc) { 4798 - guard(srcu)(&desc->srcu); 4784 + guard(srcu)(&desc->gdev->desc_srcu); 4799 4785 if (test_bit(FLAG_REQUESTED, &desc->flags)) { 4800 4786 gpiod_get_direction(desc); 4801 4787 is_out = test_bit(FLAG_IS_OUT, &desc->flags);
+11 -6
drivers/gpio/gpiolib.h
··· 31 31 * @chip: pointer to the corresponding gpiochip, holding static 32 32 * data for this device 33 33 * @descs: array of ngpio descriptors. 34 + * @desc_srcu: ensures consistent state of GPIO descriptors exposed to users 34 35 * @ngpio: the number of GPIO lines on this GPIO device, equal to the size 35 36 * of the @descs array. 36 37 * @can_sleep: indicate whether the GPIO chip driver's callbacks can sleep ··· 62 61 struct module *owner; 63 62 struct gpio_chip __rcu *chip; 64 63 struct gpio_desc *descs; 64 + struct srcu_struct desc_srcu; 65 65 int base; 66 66 u16 ngpio; 67 67 bool can_sleep; ··· 139 137 140 138 void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action); 141 139 140 + struct gpio_desc_label { 141 + struct rcu_head rh; 142 + char str[]; 143 + }; 144 + 142 145 /** 143 146 * struct gpio_desc - Opaque descriptor for a GPIO 144 147 * ··· 152 145 * @label: Name of the consumer 153 146 * @name: Line name 154 147 * @hog: Pointer to the device node that hogs this line (if any) 155 - * @srcu: SRCU struct protecting the label pointer. 156 148 * 157 149 * These are obtained using gpiod_get() and are preferable to the old 158 150 * integer-based handles. ··· 183 177 #define FLAG_EVENT_CLOCK_HTE 19 /* GPIO CDEV reports hardware timestamps in events */ 184 178 185 179 /* Connection label */ 186 - const char __rcu *label; 180 + struct gpio_desc_label __rcu *label; 187 181 /* Name of the GPIO */ 188 182 const char *name; 189 183 #ifdef CONFIG_OF_DYNAMIC 190 184 struct device_node *hog; 191 185 #endif 192 - struct srcu_struct srcu; 193 186 }; 194 187 195 188 #define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) ··· 256 251 257 252 #define gpiod_err(desc, fmt, ...) \ 258 253 do { \ 259 - scoped_guard(srcu, &desc->srcu) { \ 254 + scoped_guard(srcu, &desc->gdev->desc_srcu) { \ 260 255 pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), \ 261 256 gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \ 262 257 } \ ··· 264 259 265 260 #define gpiod_warn(desc, fmt, ...) \ 266 261 do { \ 267 - scoped_guard(srcu, &desc->srcu) { \ 262 + scoped_guard(srcu, &desc->gdev->desc_srcu) { \ 268 263 pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), \ 269 264 gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \ 270 265 } \ ··· 272 267 273 268 #define gpiod_dbg(desc, fmt, ...) \ 274 269 do { \ 275 - scoped_guard(srcu, &desc->srcu) { \ 270 + scoped_guard(srcu, &desc->gdev->desc_srcu) { \ 276 271 pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), \ 277 272 gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \ 278 273 } \