mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-25 11:55:37 +00:00
gpio: cdev: fix missed label sanitizing in debounce_setup()
commit83092341e1
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:b34490879b
("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
78d0146446
commit
dbba73560e
1 changed files with 28 additions and 21 deletions
|
@ -734,6 +734,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)
|
||||
|
@ -1021,6 +1040,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);
|
||||
|
@ -1043,11 +1063,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);
|
||||
|
@ -1089,25 +1115,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…
Reference in a new issue