* [PATCH] gpiolib: Fix crash when exporting non-existant gpio @ 2013-08-24 18:48 danielfsantos 2013-08-24 19:57 ` Guenter Roeck 2013-08-24 20:48 ` danielfsantos 0 siblings, 2 replies; 8+ messages in thread From: danielfsantos @ 2013-08-24 18:48 UTC (permalink / raw) To: Linus Walleij, linux-gpio, LKML; +Cc: Daniel Santos I got this on an RPi and I can't find anything specific to that. Besides, it's clearly wrong to try to access desc->chip when we have just tested that it may be NULL at drivers/gpio/gpiolib.c:1409: chip = desc->chip; if (chip == NULL) goto done; .... done: if (status) pr_debug("_gpio_request: gpio-%d (%s) status %d\n", desc_to_gpio(desc), label ? : "?", status); To reproduce, just pick an invalid gpio nubmer and: echo -n 248 > /sys/class/gpio/export However, I wasn't able to reproduce it on my laptop, maybe because I don't have any real gpio chips there, not sure. More info on RPi bug report: https://github.com/raspberrypi/linux/issues/364 [ 222.961384] Unable to handle kernel NULL pointer dereference at virtual address 00000044 [ 222.969486] pgd = d97d0000 [ 222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000 [ 222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d6413b2..e547f75f8b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -136,7 +136,7 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio) */ static int desc_to_gpio(const struct gpio_desc *desc) { - return desc->chip->base + gpio_chip_hwgpio(desc); + return desc->chip ? desc->chip->base + gpio_chip_hwgpio(desc) : -1; } -- 1.8.1.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] gpiolib: Fix crash when exporting non-existant gpio 2013-08-24 18:48 [PATCH] gpiolib: Fix crash when exporting non-existant gpio danielfsantos @ 2013-08-24 19:57 ` Guenter Roeck 2013-08-24 20:31 ` Daniel Santos 2013-08-24 20:48 ` danielfsantos 1 sibling, 1 reply; 8+ messages in thread From: Guenter Roeck @ 2013-08-24 19:57 UTC (permalink / raw) To: Daniel Santos; +Cc: danielfsantos, Linus Walleij, linux-gpio, LKML On 08/24/2013 11:48 AM, danielfsantos@att.net wrote: > I got this on an RPi and I can't find anything specific to that. > Besides, it's clearly wrong to try to access desc->chip when we have > just tested that it may be NULL at drivers/gpio/gpiolib.c:1409: > > chip = desc->chip; > if (chip == NULL) > goto done; > > .... > > done: > if (status) > pr_debug("_gpio_request: gpio-%d (%s) status %d\n", > desc_to_gpio(desc), label ? : "?", status); > > To reproduce, just pick an invalid gpio nubmer and: > > echo -n 248 > /sys/class/gpio/export > > However, I wasn't able to reproduce it on my laptop, maybe because I > don't have any real gpio chips there, not sure. More info on RPi bug > report: https://github.com/raspberrypi/linux/issues/364 > > [ 222.961384] Unable to handle kernel NULL pointer dereference at > virtual address 00000044 > [ 222.969486] pgd = d97d0000 > [ 222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000 > [ 222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM > --- > drivers/gpio/gpiolib.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c > index d6413b2..e547f75f8b 100644 > --- a/drivers/gpio/gpiolib.c > +++ b/drivers/gpio/gpiolib.c > @@ -136,7 +136,7 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio) > */ > static int desc_to_gpio(const struct gpio_desc *desc) > { > - return desc->chip->base + gpio_chip_hwgpio(desc); > + return desc->chip ? desc->chip->base + gpio_chip_hwgpio(desc) : -1; > } > Looking into calling code, desc_to_gpio() is clearly not supposed to return an error, and it will result in odd behavior if it returns -1. For example, the resulting debug message of "gpio--1 (...) status ..." is not very useful. It would make more sense to fix the calling code. You could for example validate in affected functions if the gpio pin exists by not only checking for desc but also for desc->chip. Another option might be to have gpio_to_desc() return NULL if desc->chip is NULL. Guenter ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] gpiolib: Fix crash when exporting non-existant gpio 2013-08-24 19:57 ` Guenter Roeck @ 2013-08-24 20:31 ` Daniel Santos 0 siblings, 0 replies; 8+ messages in thread From: Daniel Santos @ 2013-08-24 20:31 UTC (permalink / raw) To: Guenter Roeck; +Cc: Linus Walleij, linux-gpio, LKML On 08/24/2013 02:57 PM, Guenter Roeck wrote: > > Looking into calling code, desc_to_gpio() is clearly not supposed to > return an error, > and it will result in odd behavior if it returns -1. For example, the > resulting debug > message of "gpio--1 (...) status ..." is not very useful. > > It would make more sense to fix the calling code. You could for example > validate in affected functions if the gpio pin exists by not only > checking for desc but also for desc->chip. Another option might be > to have gpio_to_desc() return NULL if desc->chip is NULL. Yes, you are correct of course. I guess I was just being lazy. :) I'll re-submit. ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] gpiolib: Fix crash when exporting non-existant gpio 2013-08-24 18:48 [PATCH] gpiolib: Fix crash when exporting non-existant gpio danielfsantos 2013-08-24 19:57 ` Guenter Roeck @ 2013-08-24 20:48 ` danielfsantos 2013-08-24 20:52 ` [PATCH v2] gpiolib: Fix crash when exporting non-existent gpio Daniel Santos ` (2 more replies) 1 sibling, 3 replies; 8+ messages in thread From: danielfsantos @ 2013-08-24 20:48 UTC (permalink / raw) To: Linus Walleij, linux-gpio, LKML; +Cc: Guenter Roeck, Daniel Santos I got this on an RPi and I can't find anything specific to that. Besides, it's clearly wrong to try to access desc->chip when we have just tested that it may be NULL at drivers/gpio/gpiolib.c:1409: chip = desc->chip; if (chip == NULL) goto done; .... done: if (status) pr_debug("_gpio_request: gpio-%d (%s) status %d\n", desc_to_gpio(desc), label ? : "?", status); To reproduce, just pick an invalid gpio nubmer and: echo -n 248 > /sys/class/gpio/export However, I wasn't able to reproduce it on my laptop, maybe because I don't have any real gpio chips there, not sure. More info on RPi bug report: https://github.com/raspberrypi/linux/issues/364 This fix makes sure that gpio_to_desc() only returns non-NULL if the specified gpio really has a chip, and not just if it's within the ranged of gpios for the arch. [ 222.961384] Unable to handle kernel NULL pointer dereference at virtual address 00000044 [ 222.969486] pgd = d97d0000 [ 222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000 [ 222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM --- drivers/gpio/gpiolib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d6413b2..db7c6bb 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -123,7 +123,8 @@ static int gpio_chip_hwgpio(const struct gpio_desc *desc) */ static struct gpio_desc *gpio_to_desc(unsigned gpio) { - if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio)) + if (WARN(!gpio_is_valid(gpio) || !gpio_desc[gpio].chip, + "invalid GPIO %d\n", gpio)) return NULL; else return &gpio_desc[gpio]; @@ -1406,8 +1407,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) spin_lock_irqsave(&gpio_lock, flags); chip = desc->chip; - if (chip == NULL) - goto done; + BUG_ON(!chip); if (!try_module_get(chip->owner)) goto done; -- 1.8.1.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2] gpiolib: Fix crash when exporting non-existent gpio 2013-08-24 20:48 ` danielfsantos @ 2013-08-24 20:52 ` Daniel Santos 2013-08-24 21:51 ` [PATCH] gpiolib: Fix crash when exporting non-existant gpio Guenter Roeck 2013-08-29 9:52 ` Linus Walleij 2 siblings, 0 replies; 8+ messages in thread From: Daniel Santos @ 2013-08-24 20:52 UTC (permalink / raw) To: linux-gpio; +Cc: Linus Walleij, LKML, Guenter Roeck hmm, git send-email didn't change my subject on the above message to "[PATCH v2]", not sure what I did wrong. Sorry about that. Daniel ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] gpiolib: Fix crash when exporting non-existant gpio 2013-08-24 20:48 ` danielfsantos 2013-08-24 20:52 ` [PATCH v2] gpiolib: Fix crash when exporting non-existent gpio Daniel Santos @ 2013-08-24 21:51 ` Guenter Roeck 2013-08-29 9:52 ` Linus Walleij 2 siblings, 0 replies; 8+ messages in thread From: Guenter Roeck @ 2013-08-24 21:51 UTC (permalink / raw) To: Daniel Santos; +Cc: danielfsantos, Linus Walleij, linux-gpio, LKML On 08/24/2013 01:48 PM, danielfsantos@att.net wrote: > I got this on an RPi and I can't find anything specific to that. > Besides, it's clearly wrong to try to access desc->chip when we have > just tested that it may be NULL at drivers/gpio/gpiolib.c:1409: > > chip = desc->chip; > if (chip == NULL) > goto done; > > .... > > done: > if (status) > pr_debug("_gpio_request: gpio-%d (%s) status %d\n", > desc_to_gpio(desc), label ? : "?", status); > > To reproduce, just pick an invalid gpio nubmer and: > > echo -n 248 > /sys/class/gpio/export > > However, I wasn't able to reproduce it on my laptop, maybe because I > don't have any real gpio chips there, not sure. More info on RPi bug > report: https://github.com/raspberrypi/linux/issues/364 > > This fix makes sure that gpio_to_desc() only returns non-NULL if the > specified gpio really has a chip, and not just if it's within the ranged > of gpios for the arch. > > [ 222.961384] Unable to handle kernel NULL pointer dereference at > virtual address 00000044 > [ 222.969486] pgd = d97d0000 > [ 222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000 > [ 222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM > --- > drivers/gpio/gpiolib.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c > index d6413b2..db7c6bb 100644 > --- a/drivers/gpio/gpiolib.c > +++ b/drivers/gpio/gpiolib.c > @@ -123,7 +123,8 @@ static int gpio_chip_hwgpio(const struct gpio_desc *desc) > */ > static struct gpio_desc *gpio_to_desc(unsigned gpio) > { > - if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio)) > + if (WARN(!gpio_is_valid(gpio) || !gpio_desc[gpio].chip, > + "invalid GPIO %d\n", gpio)) I think this triggers a WARN if someone requests an invalid gpio pin from userspace. Is this really a good idea ? [ and then export_store and unexport_store complain again with pr_warn ] May be a separate patch, but if the WARN is useful it might make sense to introduce gpio_to_desc_silent() which doesn't produce the WARN if it fails. Looking further into the code, I suspect there may be some race condition where desc->chip is not (yet) set and export_store is called. So we will see a WARNING instead of a crash, as the underlying condition still exists. > return NULL; > else > return &gpio_desc[gpio]; > @@ -1406,8 +1407,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) > spin_lock_irqsave(&gpio_lock, flags); > > chip = desc->chip; > - if (chip == NULL) > - goto done; > + BUG_ON(!chip); > ... which in turn means we might see this one. If so, this code might replace an invalid memory access crash with a BUG crash. Is this really desirable, or should this better be a WARN ? Guenter > if (!try_module_get(chip->owner)) > goto done; > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] gpiolib: Fix crash when exporting non-existant gpio 2013-08-24 20:48 ` danielfsantos 2013-08-24 20:52 ` [PATCH v2] gpiolib: Fix crash when exporting non-existent gpio Daniel Santos 2013-08-24 21:51 ` [PATCH] gpiolib: Fix crash when exporting non-existant gpio Guenter Roeck @ 2013-08-29 9:52 ` Linus Walleij 2013-08-29 10:23 ` Alexandre Courbot 2 siblings, 1 reply; 8+ messages in thread From: Linus Walleij @ 2013-08-29 9:52 UTC (permalink / raw) To: Daniel Santos, Alexandre Courbot Cc: linux-gpio@vger.kernel.org, LKML, Guenter Roeck, Alexandre Courbot On Sat, Aug 24, 2013 at 10:48 PM, <danielfsantos@att.net> wrote: > [ 222.961384] Unable to handle kernel NULL pointer dereference at > virtual address 00000044 > [ 222.969486] pgd = d97d0000 > [ 222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000 > [ 222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM > --- > drivers/gpio/gpiolib.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c > index d6413b2..db7c6bb 100644 > --- a/drivers/gpio/gpiolib.c > +++ b/drivers/gpio/gpiolib.c > @@ -123,7 +123,8 @@ static int gpio_chip_hwgpio(const struct gpio_desc *desc) > */ > static struct gpio_desc *gpio_to_desc(unsigned gpio) > { > - if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio)) > + if (WARN(!gpio_is_valid(gpio) || !gpio_desc[gpio].chip, > + "invalid GPIO %d\n", gpio)) > return NULL; > else > return &gpio_desc[gpio]; > @@ -1406,8 +1407,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) > spin_lock_irqsave(&gpio_lock, flags); > > chip = desc->chip; > - if (chip == NULL) > - goto done; > + BUG_ON(!chip); It'd be good if Alexandre took a look at this. BUG_ON() is pretty nasty, atleast replace it with a warning. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] gpiolib: Fix crash when exporting non-existant gpio 2013-08-29 9:52 ` Linus Walleij @ 2013-08-29 10:23 ` Alexandre Courbot 0 siblings, 0 replies; 8+ messages in thread From: Alexandre Courbot @ 2013-08-29 10:23 UTC (permalink / raw) To: Linus Walleij Cc: Daniel Santos, Alexandre Courbot, linux-gpio@vger.kernel.org, LKML, Guenter Roeck On Thu, Aug 29, 2013 at 6:52 PM, Linus Walleij <linus.walleij@linaro.org> wrote: > On Sat, Aug 24, 2013 at 10:48 PM, <danielfsantos@att.net> wrote: > >> [ 222.961384] Unable to handle kernel NULL pointer dereference at >> virtual address 00000044 >> [ 222.969486] pgd = d97d0000 >> [ 222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000 >> [ 222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM >> --- >> drivers/gpio/gpiolib.c | 6 +++--- >> 1 file changed, 3 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c >> index d6413b2..db7c6bb 100644 >> --- a/drivers/gpio/gpiolib.c >> +++ b/drivers/gpio/gpiolib.c >> @@ -123,7 +123,8 @@ static int gpio_chip_hwgpio(const struct gpio_desc *desc) >> */ >> static struct gpio_desc *gpio_to_desc(unsigned gpio) >> { >> - if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio)) >> + if (WARN(!gpio_is_valid(gpio) || !gpio_desc[gpio].chip, >> + "invalid GPIO %d\n", gpio)) >> return NULL; >> else >> return &gpio_desc[gpio]; >> @@ -1406,8 +1407,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) >> spin_lock_irqsave(&gpio_lock, flags); >> >> chip = desc->chip; >> - if (chip == NULL) >> - goto done; >> + BUG_ON(!chip); > > It'd be good if Alexandre took a look at this. > > BUG_ON() is pretty nasty, atleast replace it with > a warning. Agreed - that's a cheap way to crash the kernel. desc_to_gpio() assumes a valid descriptor, so we should not call it from contexts where we know the descriptor may be invalid. How about having the initial "if (!desc)" changed into "if (!desc || !desc->chip)" instead? That way an error would be returned immediatly and we would know we have a valid descriptor after that. Having gpio_to_desc() return NULL if the descriptor does not have a chip associated also seems to make sense - otherwise the caller should check it itself. I'd even go as far as saying the check should be done in gpio_is_valid itself. There is probably a lot more potential to improve error handling in gpiolib. Generally speaking, moving safety checks to a lower-level and propagating error codes accordingly should be the right approach, as long as it doesn't clutter performance. We want to be able to assume that GPIO descriptors are valid in most of the code. Alex. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-08-29 10:24 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-08-24 18:48 [PATCH] gpiolib: Fix crash when exporting non-existant gpio danielfsantos 2013-08-24 19:57 ` Guenter Roeck 2013-08-24 20:31 ` Daniel Santos 2013-08-24 20:48 ` danielfsantos 2013-08-24 20:52 ` [PATCH v2] gpiolib: Fix crash when exporting non-existent gpio Daniel Santos 2013-08-24 21:51 ` [PATCH] gpiolib: Fix crash when exporting non-existant gpio Guenter Roeck 2013-08-29 9:52 ` Linus Walleij 2013-08-29 10:23 ` Alexandre Courbot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).