[PATCH 5/8] i2c: core: fix adapter registration race
From: Johan Hovold
Date: Tue May 05 2026 - 10:36:11 EST
Adapters can be looked up based on their id using i2c_get_adapter()
which takes a reference to the embedded struct device.
Make sure that the adapter (including its struct device) has been
initialised before adding it to the IDR to avoid accessing uninitialised
data which could, for example, lead to NULL-pointer dereferences or
use-after-free.
Fixes: 6e13e6418418 ("i2c: Add i2c_add_numbered_adapter()")
Cc: stable@xxxxxxxxxxxxxxx # 2.6.22
Signed-off-by: Johan Hovold <johan@xxxxxxxxxx>
---
drivers/i2c/i2c-core-base.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 31f7d43e4ab5..be909d6bc776 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1587,6 +1587,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
if (res)
goto out_reg;
+ mutex_lock(&core_lock);
+ idr_replace(&i2c_adapter_idr, adap, adap->nr);
+ mutex_unlock(&core_lock);
+
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
/* create pre-declared device nodes */
@@ -1633,7 +1637,7 @@ static int __i2c_add_numbered_adapter(struct i2c_adapter *adap)
int id;
mutex_lock(&core_lock);
- id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1, GFP_KERNEL);
+ id = idr_alloc(&i2c_adapter_idr, NULL, adap->nr, adap->nr + 1, GFP_KERNEL);
mutex_unlock(&core_lock);
if (WARN(id < 0, "couldn't get idr"))
return id == -ENOSPC ? -EBUSY : id;
@@ -1667,7 +1671,7 @@ int i2c_add_adapter(struct i2c_adapter *adapter)
}
mutex_lock(&core_lock);
- id = idr_alloc(&i2c_adapter_idr, adapter,
+ id = idr_alloc(&i2c_adapter_idr, NULL,
__i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
mutex_unlock(&core_lock);
if (WARN(id < 0, "couldn't get idr"))
--
2.53.0