+++ /dev/null
-From b34490879baa847d16fc529c8ea6e6d34f004b38 Mon Sep 17 00:00:00 2001
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Date: Mon, 25 Mar 2024 10:02:42 +0100
-Subject: gpio: cdev: sanitize the label before requesting the interrupt
-
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-commit b34490879baa847d16fc529c8ea6e6d34f004b38 upstream.
-
-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: stable@vger.kernel.org
-Reported-by: Stefan Wahren <wahrenst@gmx.net>
-Closes: https://lore.kernel.org/linux-gpio/39fe95cb-aa83-4b8b-8cab-63947a726754@gmx.net/
-Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Reviewed-by: Kent Gibson <warthog618@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/gpio/gpiolib-cdev.c | 38 ++++++++++++++++++++++++++++++++------
- 1 file changed, 32 insertions(+), 6 deletions(-)
-
---- a/drivers/gpio/gpiolib-cdev.c
-+++ b/drivers/gpio/gpiolib-cdev.c
-@@ -999,10 +999,20 @@ static u32 gpio_v2_line_config_debounce_
- return 0;
- }
-
-+static inline char *make_irq_label(const char *orig)
-+{
-+ return kstrdup_and_replace(orig, '/', ':', GFP_KERNEL);
-+}
-+
-+static inline void free_irq_label(const char *label)
-+{
-+ kfree(label);
-+}
-+
- static void edge_detector_stop(struct line *line)
- {
- if (line->irq) {
-- free_irq(line->irq, line);
-+ free_irq_label(free_irq(line->irq, line));
- line->irq = 0;
- }
-
-@@ -1027,6 +1037,7 @@ static int edge_detector_setup(struct li
- unsigned long irqflags = 0;
- u64 eflags;
- int irq, ret;
-+ char *label;
-
- eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
- if (eflags && !kfifo_initialized(&line->req->events)) {
-@@ -1063,11 +1074,17 @@ static int edge_detector_setup(struct li
- IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
- irqflags |= IRQF_ONESHOT;
-
-+ label = make_irq_label(line->req->label);
-+ if (!label)
-+ return -ENOMEM;
-+
- /* Request a thread to read the events */
- ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread,
-- irqflags, line->req->label, line);
-- if (ret)
-+ irqflags, label, line);
-+ if (ret) {
-+ free_irq_label(label);
- return ret;
-+ }
-
- line->irq = irq;
- return 0;
-@@ -1910,7 +1927,7 @@ static ssize_t lineevent_read(struct fil
- static void lineevent_free(struct lineevent_state *le)
- {
- if (le->irq)
-- free_irq(le->irq, le);
-+ free_irq_label(free_irq(le->irq, le));
- if (le->desc)
- gpiod_free(le->desc);
- kfree(le->label);
-@@ -2058,6 +2075,7 @@ static int lineevent_create(struct gpio_
- int fd;
- int ret;
- int irq, irqflags = 0;
-+ char *label;
-
- if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
- return -EFAULT;
-@@ -2138,15 +2156,23 @@ static int lineevent_create(struct gpio_
- INIT_KFIFO(le->events);
- init_waitqueue_head(&le->wait);
-
-+ label = make_irq_label(le->label);
-+ if (!label) {
-+ ret = -ENOMEM;
-+ goto out_free_le;
-+ }
-+
- /* Request a thread to read the events */
- ret = request_threaded_irq(irq,
- lineevent_irq_handler,
- lineevent_irq_thread,
- irqflags,
-- le->label,
-+ label,
- le);
-- if (ret)
-+ if (ret) {
-+ free_irq_label(label);
- goto out_free_le;
-+ }
-
- le->irq = irq;
-