Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

eeprom: ee1004: Fix locking issues in ee1004_probe()

Currently, the devres-based management of ee1004_bus_data has
several issues when it comes to locking:

1. It does not call mutex_unlock() before returning an error.

2. When encountering an error, it deadlocks when trying to recursively
lock a mutex.

Fix this by moving the mutex-protected bus data initialization into
a separate function so that devm_add_action_or_reset() is called
without the mutex being held.

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Fixes: 55d57ef6fa97 ("eeprom: ee1004: Use devres for bus data cleanup")
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://lore.kernel.org/r/20240713234813.21746-1-W_Armin@gmx.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Armin Wolf and committed by
Greg Kroah-Hartman
e6cd0dc9 be62f128

+51 -34
+51 -34
drivers/misc/eeprom/ee1004.c
··· 233 233 mutex_unlock(&ee1004_bus_lock); 234 234 } 235 235 236 + static int ee1004_init_bus_data(struct i2c_client *client) 237 + { 238 + struct ee1004_bus_data *bd; 239 + int err, cnr = 0; 240 + 241 + bd = ee1004_get_bus_data(client->adapter); 242 + if (!bd) 243 + return dev_err_probe(&client->dev, -ENOSPC, "Only %d busses supported", 244 + EE1004_MAX_BUSSES); 245 + 246 + i2c_set_clientdata(client, bd); 247 + 248 + if (++bd->dev_count == 1) { 249 + /* Use 2 dummy devices for page select command */ 250 + for (cnr = 0; cnr < EE1004_NUM_PAGES; cnr++) { 251 + struct i2c_client *cl; 252 + 253 + cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); 254 + if (IS_ERR(cl)) { 255 + err = PTR_ERR(cl); 256 + goto err_out; 257 + } 258 + 259 + bd->set_page[cnr] = cl; 260 + } 261 + 262 + /* Remember current page to avoid unneeded page select */ 263 + err = ee1004_get_current_page(bd); 264 + if (err < 0) 265 + goto err_out; 266 + 267 + dev_dbg(&client->dev, "Currently selected page: %d\n", err); 268 + bd->current_page = err; 269 + } 270 + 271 + return 0; 272 + 273 + err_out: 274 + ee1004_cleanup(cnr, bd); 275 + 276 + return err; 277 + } 278 + 236 279 static int ee1004_probe(struct i2c_client *client) 237 280 { 238 281 struct nvmem_config config = { ··· 294 251 .compat = true, 295 252 .base_dev = &client->dev, 296 253 }; 297 - struct ee1004_bus_data *bd; 298 254 struct nvmem_device *ndev; 299 - int err, cnr = 0; 255 + int err; 300 256 301 257 /* Make sure we can operate on this adapter */ 302 258 if (!i2c_check_functionality(client->adapter, ··· 306 264 307 265 mutex_lock(&ee1004_bus_lock); 308 266 309 - bd = ee1004_get_bus_data(client->adapter); 310 - if (!bd) { 267 + err = ee1004_init_bus_data(client); 268 + if (err < 0) { 311 269 mutex_unlock(&ee1004_bus_lock); 312 - return dev_err_probe(&client->dev, -ENOSPC, 313 - "Only %d busses supported", EE1004_MAX_BUSSES); 314 - } 315 - 316 - err = devm_add_action_or_reset(&client->dev, ee1004_cleanup_bus_data, bd); 317 - if (err < 0) 318 270 return err; 319 - 320 - i2c_set_clientdata(client, bd); 321 - 322 - if (++bd->dev_count == 1) { 323 - /* Use 2 dummy devices for page select command */ 324 - for (cnr = 0; cnr < EE1004_NUM_PAGES; cnr++) { 325 - struct i2c_client *cl; 326 - 327 - cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); 328 - if (IS_ERR(cl)) { 329 - mutex_unlock(&ee1004_bus_lock); 330 - return PTR_ERR(cl); 331 - } 332 - bd->set_page[cnr] = cl; 333 - } 334 - 335 - /* Remember current page to avoid unneeded page select */ 336 - err = ee1004_get_current_page(bd); 337 - if (err < 0) { 338 - mutex_unlock(&ee1004_bus_lock); 339 - return err; 340 - } 341 - dev_dbg(&client->dev, "Currently selected page: %d\n", err); 342 - bd->current_page = err; 343 271 } 344 272 345 273 ee1004_probe_temp_sensor(client); 346 274 347 275 mutex_unlock(&ee1004_bus_lock); 276 + 277 + err = devm_add_action_or_reset(&client->dev, ee1004_cleanup_bus_data, 278 + i2c_get_clientdata(client)); 279 + if (err < 0) 280 + return err; 348 281 349 282 ndev = devm_nvmem_register(&client->dev, &config); 350 283 if (IS_ERR(ndev))