mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 12:52:30 +00:00
gpio: cdev: fix missed label sanitizing in debounce_setup()
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>
This commit is contained in:
parent
b3b9596459
commit
83092341e1
@ -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)
|
||||
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);
|
||||
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user