gpio: cdev: fix missed label sanitizing in debounce_setup()
commit 83092341e15d0dfee1caa8dc502f66c815ccd78a upstream. 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(). Cc: stable@vger.kernel.org Fixes: b34490879baa ("gpio: cdev: sanitize the label before requesting the interrupt") Signed-off-by: Kent Gibson <warthog618@gmail.com> [Bartosz: rebased on top of the fix for empty GPIO labels] Co-developed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d9f0804ab0
commit
2f0262ac3a
@ -655,6 +655,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)
|
||||
@ -942,6 +961,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);
|
||||
@ -964,11 +984,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)
|
||||
label, line);
|
||||
if (ret) {
|
||||
free_irq_label(label);
|
||||
return ret;
|
||||
}
|
||||
line->irq = irq;
|
||||
} else {
|
||||
ret = hte_edge_setup(line, GPIO_V2_LINE_FLAG_EDGE_BOTH);
|
||||
@ -1010,25 +1036,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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user