linux
NULL pointer on !OF_IRQ gets dereferenced if IRQ_DOMAIN
In TWL4030 driver, attempt to register an IRQ domain with a NULL ops structure; ops is de-referenced when registering an IRQ domain, but this field is only set when OF_IRQ.
Bug fixed by commit 6252547b8a7
Type | NullDereference |
Config | "TWL4030_CORE && !OF_IRQ" (2nd degree) |
C-features | FunctionPointers |
Fix-in | model, mapping |
Location | include/linux/ |
#define NULL (void*)0 #ifdef CONFIG_TWL4030_CORE #define CONFIG_IRQ_DOMAIN #endif #ifdef CONFIG_IRQ_DOMAIN int irq_domain_simple_ops = 1; void irq_domain_add(int *ops) { int irq = *ops; // (4) ERROR } #endif #ifdef CONFIG_TWL4030_CORE int twl_probe() { int *ops = NULL; // (2) #ifdef CONFIG_OF_IRQ ops = &irq_domain_simple_ops; #endif irq_domain_add(ops); // (3) } #endif int main() { #ifdef CONFIG_TWL4030_CORE twl_probe(); // (1) #endif return 0; }
diff --git a/simple/6252547.c b/simple/6252547.c --- a/simple/6252547.c +++ b/simple/6252547.c @@ -1,10 +1,6 @@ #define NULL (void*)0 -#ifdef CONFIG_TWL4030_CORE -#define CONFIG_IRQ_DOMAIN -#endif - #ifdef CONFIG_IRQ_DOMAIN int irq_domain_simple_ops = 1; @@ -17,13 +13,13 @@ #ifdef CONFIG_TWL4030_CORE int twl_probe() { +#ifdef CONFIG_IRQ_DOMAIN int *ops = NULL; // (2) -#ifdef CONFIG_OF_IRQ ops = &irq_domain_simple_ops; -#endif irq_domain_add(ops); // (3) +#endif } #endif
#include <stdlib.h> #ifdef CONFIG_TWL4030_CORE #define CONFIG_IRQ_DOMAIN #endif #ifdef CONFIG_IRQ_DOMAIN int irq_domain_simple_ops = 1; #endif int main() { #ifdef CONFIG_TWL4030_CORE // twl_probe(); int *ops = NULL; #ifdef CONFIG_OF_IRQ ops = &irq_domain_simple_ops; #endif int irq = *ops; // ERROR #endif return 0; }
. call drivers/base/dd.c:203:driver_probe_device() . 215: ret = really_probe(dev, drv); .. 108:really_probe() .. 124: if (dev->bus->probe) ... dyn-call drivers/i2c/i2c-core.c:106:i2c_device_probe() ... 124: status = driver->probe(client, i2c_match_id(driver->id_table, client)); .... dyn-call drivers/mfd/twl-core.c:1190:twl_probe() .... [OF_IRQ] 1233: domain.ops = &irq_domain_simple_ops; .... 1235: irq_domain_add(&domain); ..... call kernel/irq/irqdomain.c:20:irq_domain_add() ..... 30: irq_domain_for_each_irq(domain, hwirq, irq) ...... call include/linux/irqdomain.h:74:irq_domain_to_irq() ...... ERROR 77: if (d->ops->to_irq)