Skip to content

Commit b344908

Browse files
author
Bartosz Golaszewski
committed
gpio: cdev: sanitize the label before requesting the interrupt
When an interrupt is requested, a procfs directory is created under "/proc/irq/<irqnum>/<label>" where <label> is the string passed to one of the request_irq() variants. What follows is that the string must not contain the "/" character or the procfs mkdir operation will fail. We don't have such constraints for GPIO consumer labels which are used verbatim as interrupt labels for GPIO irqs. We must therefore sanitize the consumer string before requesting the interrupt. Let's replace all "/" with ":". Cc: [email protected] Reported-by: Stefan Wahren <[email protected]> Closes: https://lore.kernel.org/linux-gpio/[email protected]/ Signed-off-by: Bartosz Golaszewski <[email protected]> Reviewed-by: Kent Gibson <[email protected]>
1 parent 4cece76 commit b344908

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

drivers/gpio/gpiolib-cdev.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,10 +1083,20 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc,
10831083
return 0;
10841084
}
10851085

1086+
static inline char *make_irq_label(const char *orig)
1087+
{
1088+
return kstrdup_and_replace(orig, '/', ':', GFP_KERNEL);
1089+
}
1090+
1091+
static inline void free_irq_label(const char *label)
1092+
{
1093+
kfree(label);
1094+
}
1095+
10861096
static void edge_detector_stop(struct line *line)
10871097
{
10881098
if (line->irq) {
1089-
free_irq(line->irq, line);
1099+
free_irq_label(free_irq(line->irq, line));
10901100
line->irq = 0;
10911101
}
10921102

@@ -1110,6 +1120,7 @@ static int edge_detector_setup(struct line *line,
11101120
unsigned long irqflags = 0;
11111121
u64 eflags;
11121122
int irq, ret;
1123+
char *label;
11131124

11141125
eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
11151126
if (eflags && !kfifo_initialized(&line->req->events)) {
@@ -1146,11 +1157,17 @@ static int edge_detector_setup(struct line *line,
11461157
IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
11471158
irqflags |= IRQF_ONESHOT;
11481159

1160+
label = make_irq_label(line->req->label);
1161+
if (!label)
1162+
return -ENOMEM;
1163+
11491164
/* Request a thread to read the events */
11501165
ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread,
1151-
irqflags, line->req->label, line);
1152-
if (ret)
1166+
irqflags, label, line);
1167+
if (ret) {
1168+
free_irq_label(label);
11531169
return ret;
1170+
}
11541171

11551172
line->irq = irq;
11561173
return 0;
@@ -1973,7 +1990,7 @@ static void lineevent_free(struct lineevent_state *le)
19731990
blocking_notifier_chain_unregister(&le->gdev->device_notifier,
19741991
&le->device_unregistered_nb);
19751992
if (le->irq)
1976-
free_irq(le->irq, le);
1993+
free_irq_label(free_irq(le->irq, le));
19771994
if (le->desc)
19781995
gpiod_free(le->desc);
19791996
kfree(le->label);
@@ -2114,6 +2131,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
21142131
int fd;
21152132
int ret;
21162133
int irq, irqflags = 0;
2134+
char *label;
21172135

21182136
if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
21192137
return -EFAULT;
@@ -2198,15 +2216,23 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
21982216
if (ret)
21992217
goto out_free_le;
22002218

2219+
label = make_irq_label(le->label);
2220+
if (!label) {
2221+
ret = -ENOMEM;
2222+
goto out_free_le;
2223+
}
2224+
22012225
/* Request a thread to read the events */
22022226
ret = request_threaded_irq(irq,
22032227
lineevent_irq_handler,
22042228
lineevent_irq_thread,
22052229
irqflags,
2206-
le->label,
2230+
label,
22072231
le);
2208-
if (ret)
2232+
if (ret) {
2233+
free_irq_label(label);
22092234
goto out_free_le;
2235+
}
22102236

22112237
le->irq = irq;
22122238

0 commit comments

Comments
 (0)