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

iio: cm36651: Fix i2c client leak and possible NULL pointer dereference

During probe the driver allocates dummy I2C devices (i2c_new_dummy())
but they aren't unregistered during driver remove or probe failure.

Additionally driver does not check the return value of i2c_new_dummy().
In case of error (i2c_new_device(): memory allocation failure or I2C
address cannot be used) this function returns NULL which is later
dereferenced by i2c_smbus_{read,write}_data() functions.

Fix issues by properly checking for i2c_new_dummy() return value and
unregistering I2C devices on driver remove or probe failure.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Beomho Seo <beomho.seo@samsung.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Krzysztof Kozlowski and committed by
Jonathan Cameron
d0a588a5 2076a20f

+20 -2
+20 -2
drivers/iio/light/cm36651.c
··· 652 652 cm36651->client = client; 653 653 cm36651->ps_client = i2c_new_dummy(client->adapter, 654 654 CM36651_I2C_ADDR_PS); 655 + if (!cm36651->ps_client) { 656 + dev_err(&client->dev, "%s: new i2c device failed\n", __func__); 657 + ret = -ENODEV; 658 + goto error_disable_reg; 659 + } 660 + 655 661 cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA); 662 + if (!cm36651->ara_client) { 663 + dev_err(&client->dev, "%s: new i2c device failed\n", __func__); 664 + ret = -ENODEV; 665 + goto error_i2c_unregister_ps; 666 + } 667 + 656 668 mutex_init(&cm36651->lock); 657 669 indio_dev->dev.parent = &client->dev; 658 670 indio_dev->channels = cm36651_channels; ··· 676 664 ret = cm36651_setup_reg(cm36651); 677 665 if (ret) { 678 666 dev_err(&client->dev, "%s: register setup failed\n", __func__); 679 - goto error_disable_reg; 667 + goto error_i2c_unregister_ara; 680 668 } 681 669 682 670 ret = request_threaded_irq(client->irq, NULL, cm36651_irq_handler, ··· 684 672 "cm36651", indio_dev); 685 673 if (ret) { 686 674 dev_err(&client->dev, "%s: request irq failed\n", __func__); 687 - goto error_disable_reg; 675 + goto error_i2c_unregister_ara; 688 676 } 689 677 690 678 ret = iio_device_register(indio_dev); ··· 697 685 698 686 error_free_irq: 699 687 free_irq(client->irq, indio_dev); 688 + error_i2c_unregister_ara: 689 + i2c_unregister_device(cm36651->ara_client); 690 + error_i2c_unregister_ps: 691 + i2c_unregister_device(cm36651->ps_client); 700 692 error_disable_reg: 701 693 regulator_disable(cm36651->vled_reg); 702 694 return ret; ··· 714 698 iio_device_unregister(indio_dev); 715 699 regulator_disable(cm36651->vled_reg); 716 700 free_irq(client->irq, indio_dev); 701 + i2c_unregister_device(cm36651->ps_client); 702 + i2c_unregister_device(cm36651->ara_client); 717 703 718 704 return 0; 719 705 }