linux/drivers/iio
Fabrice Gasnier 246ead036a iio: core: fix a possible circular locking dependency
commit 7f75591fc5 upstream.

This fixes a possible circular locking dependency detected warning seen
with:
- CONFIG_PROVE_LOCKING=y
- consumer/provider IIO devices (ex: "voltage-divider" consumer of "adc")

When using the IIO consumer interface, e.g. iio_channel_get(), the consumer
device will likely call iio_read_channel_raw() or similar that rely on
'info_exist_lock' mutex.

typically:
...
	mutex_lock(&chan->indio_dev->info_exist_lock);
	if (chan->indio_dev->info == NULL) {
		ret = -ENODEV;
		goto err_unlock;
	}
	ret = do_some_ops()
err_unlock:
	mutex_unlock(&chan->indio_dev->info_exist_lock);
	return ret;
...

Same mutex is also hold in iio_device_unregister().

The following deadlock warning happens when:
- the consumer device has called an API like iio_read_channel_raw()
  at least once.
- the consumer driver is unregistered, removed (unbind from sysfs)

======================================================
WARNING: possible circular locking dependency detected
4.19.24 #577 Not tainted
------------------------------------------------------
sh/372 is trying to acquire lock:
(kn->count#30){++++}, at: kernfs_remove_by_name_ns+0x3c/0x84

but task is already holding lock:
(&dev->info_exist_lock){+.+.}, at: iio_device_unregister+0x18/0x60

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 (&dev->info_exist_lock){+.+.}:
       __mutex_lock+0x70/0xa3c
       mutex_lock_nested+0x1c/0x24
       iio_read_channel_raw+0x1c/0x60
       iio_read_channel_info+0xa8/0xb0
       dev_attr_show+0x1c/0x48
       sysfs_kf_seq_show+0x84/0xec
       seq_read+0x154/0x528
       __vfs_read+0x2c/0x15c
       vfs_read+0x8c/0x110
       ksys_read+0x4c/0xac
       ret_fast_syscall+0x0/0x28
       0xbedefb60

-> #0 (kn->count#30){++++}:
       lock_acquire+0xd8/0x268
       __kernfs_remove+0x288/0x374
       kernfs_remove_by_name_ns+0x3c/0x84
       remove_files+0x34/0x78
       sysfs_remove_group+0x40/0x9c
       sysfs_remove_groups+0x24/0x34
       device_remove_attrs+0x38/0x64
       device_del+0x11c/0x360
       cdev_device_del+0x14/0x2c
       iio_device_unregister+0x24/0x60
       release_nodes+0x1bc/0x200
       device_release_driver_internal+0x1a0/0x230
       unbind_store+0x80/0x130
       kernfs_fop_write+0x100/0x1e4
       __vfs_write+0x2c/0x160
       vfs_write+0xa4/0x17c
       ksys_write+0x4c/0xac
       ret_fast_syscall+0x0/0x28
       0xbe906840

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&dev->info_exist_lock);
                               lock(kn->count#30);
                               lock(&dev->info_exist_lock);
  lock(kn->count#30);

 *** DEADLOCK ***
...

cdev_device_del() can be called without holding the lock. It should be safe
as info_exist_lock prevents kernelspace consumers to use the exported
routines during/after provider removal. cdev_device_del() is for userspace.

Help to reproduce:
See example: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
sysv {
	compatible = "voltage-divider";
	io-channels = <&adc 0>;
	output-ohms = <22>;
	full-ohms = <222>;
};

First, go to iio:deviceX for the "voltage-divider", do one read:
$ cd /sys/bus/iio/devices/iio:deviceX
$ cat in_voltage0_raw

Then, unbind the consumer driver. It triggers above deadlock warning.
$ cd /sys/bus/platform/drivers/iio-rescale/
$ echo sysv > unbind

Note I don't actually expect stable will pick this up all the
way back into IIO being in staging, but if's probably valid that
far back.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Fixes: ac917a8111 ("staging:iio:core set the iio_dev.info pointer to null on unregister")
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
History 2019-08-13 12:38:58 +01:00
..
accel iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers 2019-02-11 17:54:05 +00:00
adc iio: ad_sigma_delta: select channel when reading register 2019-08-13 12:38:53 +01:00
amplifiers iio: amplifiers: ad8366: Remove regulator_put 2013-09-28 11:49:45 +01:00
common iio: hid-sensor-attributes: Fix sensor property setting failure. 2017-07-18 18:40:29 +01:00
dac iio: dac: mcp4725: add missing powerdown bits in store eeprom 2019-08-13 12:38:42 +01:00
frequency iio: ad9523: Fix return value for ad952x_store() 2018-12-16 22:08:29 +00:00
gyro iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers 2019-02-11 17:54:05 +00:00
humidity iio: dht11: Use usleep_range instead of msleep for start signal 2017-03-16 02:27:04 +00:00
imu iio: adis_lib: Initialize trigger before requesting interrupt 2018-06-16 22:22:19 +01:00
light iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers 2019-02-11 17:54:05 +00:00
magnetometer iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers 2019-02-11 17:54:05 +00:00
orientation iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers 2019-02-11 17:54:05 +00:00
pressure iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers 2019-02-11 17:54:05 +00:00
proximity iio: proximity: as3935: fix iio_trigger_poll issue 2017-09-15 18:29:33 +01:00
temperature iio: tmp006: Check channel info on write 2015-08-10 09:54:08 +01:00
trigger iio:trigger: fix sysfs name on list mutex 2013-09-28 11:51:16 +01:00
buffer_cb.c iio get rid of unneccessary error_ret 2014-02-18 08:46:36 +00:00
iio_core.h IIO: core: Introduce read_raw_multi 2014-04-29 22:05:32 +01:00
iio_core_trigger.h iio: fix semicolon in io_core_trigger.h 2013-08-03 18:40:32 +01:00
industrialio-buffer.c iio: Fix scan mask selection 2019-08-13 12:38:40 +01:00
industrialio-core.c iio: core: fix a possible circular locking dependency 2019-08-13 12:38:58 +01:00
industrialio-event.c iio: event: Remove negative error code from iio_event_poll 2015-09-28 10:21:38 +01:00
industrialio-trigger.c iio: Fix error handling in iio_trigger_attach_poll_func 2016-08-22 22:38:13 +01:00
industrialio-triggered-buffer.c iio:triggered-buffer: Remove redundant call to iio_sw_buffer_preenable(). 2013-10-16 19:12:47 +01:00
inkern.c iio: inkern: fix a NULL dereference on error 2016-02-25 00:18:38 +00:00
Kconfig iio: always select ANON_INODES 2014-05-10 11:39:57 +01:00
kfifo_buf.c iio:kfifo_buf: check for uint overflow 2018-10-21 08:45:05 +01:00
Makefile iio: Add AS3935 lightning sensor support 2014-03-16 18:00:32 +00:00