Message ID | 20240404093328.21604-3-brgl@bgdev.pl |
---|---|
State | New |
Headers | show |
Series | gpio: cdev: label sanitization fixes | expand |
On Thu, Apr 04, 2024 at 11:33:28AM +0200, Bartosz Golaszewski wrote: > From: Kent Gibson <warthog618@gmail.com> > > When adding sanitization of the label, the path through > edge_detector_setup() that leads to debounce_setup() was overlooked. > A request taking this path does not allocate a new label and the > request label is freed twice when the request is released, resulting > in memory corruption. > > Add label sanitization to debounce_setup(). ... > +static inline char *make_irq_label(const char *orig) > +{ > + char *new; > + > + if (!orig) > + return NULL; > + > + new = kstrdup_and_replace(orig, '/', ':', GFP_KERNEL); > + if (!new) > + return ERR_PTR(-ENOMEM); > + > + return new; > +} > + > +static inline void free_irq_label(const char *label) > +{ > + kfree(label); > +} First of all this could have been done in the previous patch already, but okay. ... > + label = make_irq_label(line->req->label); > + if (IS_ERR(label)) > + return -ENOMEM; > + > irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; > ret = request_irq(irq, debounce_irq_handler, irqflags, > line->req->label, line); But the main point how does this change fix anything? Shouldn't be - line->req->label, line); + label, line); ? > + if (ret) { > + free_irq_label(label); > return ret; > + }
On Thu, Apr 4, 2024 at 5:36 PM Andy Shevchenko <andriy.shevchenko@intel.com> wrote: > > On Thu, Apr 04, 2024 at 11:33:28AM +0200, Bartosz Golaszewski wrote: > > From: Kent Gibson <warthog618@gmail.com> > > > > When adding sanitization of the label, the path through > > edge_detector_setup() that leads to debounce_setup() was overlooked. > > A request taking this path does not allocate a new label and the > > request label is freed twice when the request is released, resulting > > in memory corruption. > > > > Add label sanitization to debounce_setup(). > > ... > > > +static inline char *make_irq_label(const char *orig) > > +{ > > + char *new; > > + > > + if (!orig) > > + return NULL; > > + > > + new = kstrdup_and_replace(orig, '/', ':', GFP_KERNEL); > > + if (!new) > > + return ERR_PTR(-ENOMEM); > > + > > + return new; > > +} > > + > > +static inline void free_irq_label(const char *label) > > +{ > > + kfree(label); > > +} > > First of all this could have been done in the previous patch already, but okay. > > ... > > > + label = make_irq_label(line->req->label); > > + if (IS_ERR(label)) > > + return -ENOMEM; > > + > > irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; > > ret = request_irq(irq, debounce_irq_handler, irqflags, > > line->req->label, line); > > But the main point how does this change fix anything? > > Shouldn't be > > - line->req->label, line); > + label, line); It should, I badly copy-pasted Kent's correct code. Thanks, I fixed it in tree. Bart > > ? > > > + if (ret) { > > + free_irq_label(label); > > return ret; > > + } > > -- > With Best Regards, > Andy Shevchenko > >
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 1426cc1c4a28..6fe978535047 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -728,6 +728,25 @@ static u32 line_event_id(int level) GPIO_V2_LINE_EVENT_FALLING_EDGE; } +static inline char *make_irq_label(const char *orig) +{ + char *new; + + if (!orig) + return NULL; + + new = kstrdup_and_replace(orig, '/', ':', GFP_KERNEL); + if (!new) + return ERR_PTR(-ENOMEM); + + return new; +} + +static inline void free_irq_label(const char *label) +{ + kfree(label); +} + #ifdef CONFIG_HTE static enum hte_return process_hw_ts_thread(void *p) @@ -1015,6 +1034,7 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us) { unsigned long irqflags; int ret, level, irq; + char *label; /* try hardware */ ret = gpiod_set_debounce(line->desc, debounce_period_us); @@ -1037,11 +1057,17 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us) if (irq < 0) return -ENXIO; + label = make_irq_label(line->req->label); + if (IS_ERR(label)) + return -ENOMEM; + irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; ret = request_irq(irq, debounce_irq_handler, irqflags, line->req->label, line); - if (ret) + if (ret) { + free_irq_label(label); return ret; + } line->irq = irq; } else { ret = hte_edge_setup(line, GPIO_V2_LINE_FLAG_EDGE_BOTH); @@ -1083,25 +1109,6 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc, return 0; } -static inline char *make_irq_label(const char *orig) -{ - char *new; - - if (!orig) - return NULL; - - new = kstrdup_and_replace(orig, '/', ':', GFP_KERNEL); - if (!new) - return ERR_PTR(-ENOMEM); - - return new; -} - -static inline void free_irq_label(const char *label) -{ - kfree(label); -} - static void edge_detector_stop(struct line *line) { if (line->irq) {