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)