Skip to content

Commit c73bbaa

Browse files
committed
[media] rc-core: don't lock device at rc_register_device()
The mutex lock at rc_register_device() was added by commit 08aeb7c ("[media] rc: add locking to fix register/show race"). It is meant to avoid race issues when trying to open a sysfs file while the RC register didn't complete. Adding a lock there causes troubles, as detected by the Kernel lock debug instrumentation at the Kernel: ====================================================== [ INFO: possible circular locking dependency detected ] 4.5.0-rc3+ torvalds#46 Not tainted ------------------------------------------------------- systemd-udevd/2681 is trying to acquire lock: (s_active#171){++++.+}, at: [<ffffffff8171a115>] kernfs_remove_by_name_ns+0x45/0xa0 but task is already holding lock: (&dev->lock){+.+.+.}, at: [<ffffffffa0724def>] rc_register_device+0xb2f/0x1450 [rc_core] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> rib#1 (&dev->lock){+.+.+.}: [<ffffffff8124817d>] lock_acquire+0x13d/0x320 [<ffffffff822de966>] mutex_lock_nested+0xb6/0x860 [<ffffffffa0721f2b>] show_protocols+0x3b/0x3f0 [rc_core] [<ffffffff81cdaba5>] dev_attr_show+0x45/0xc0 [<ffffffff8171f1b3>] sysfs_kf_seq_show+0x203/0x3c0 [<ffffffff8171a6a1>] kernfs_seq_show+0x121/0x1b0 [<ffffffff81617c71>] seq_read+0x2f1/0x1160 [<ffffffff8171c911>] kernfs_fop_read+0x321/0x460 [<ffffffff815abc20>] __vfs_read+0xe0/0x3d0 [<ffffffff815ae90e>] vfs_read+0xde/0x2d0 [<ffffffff815b1d01>] SyS_read+0x111/0x230 [<ffffffff822e8636>] entry_SYSCALL_64_fastpath+0x16/0x76 -> #0 (s_active#171){++++.+}: [<ffffffff81244f24>] __lock_acquire+0x4304/0x5990 [<ffffffff8124817d>] lock_acquire+0x13d/0x320 [<ffffffff81717d3a>] __kernfs_remove+0x58a/0x810 [<ffffffff8171a115>] kernfs_remove_by_name_ns+0x45/0xa0 [<ffffffff81721592>] remove_files.isra.0+0x72/0x190 [<ffffffff8172174b>] sysfs_remove_group+0x9b/0x150 [<ffffffff81721854>] sysfs_remove_groups+0x54/0xa0 [<ffffffff81cd97d0>] device_remove_attrs+0xb0/0x140 [<ffffffff81cdb27c>] device_del+0x38c/0x6b0 [<ffffffffa0724b8b>] rc_register_device+0x8cb/0x1450 [rc_core] [<ffffffffa1326a7b>] dvb_usb_remote_init+0x66b/0x14d0 [dvb_usb] [<ffffffffa1321c81>] dvb_usb_device_init+0xf21/0x1860 [dvb_usb] [<ffffffffa13517dc>] dib0700_probe+0x14c/0x410 [dvb_usb_dib0700] [<ffffffff81dbb1dd>] usb_probe_interface+0x45d/0x940 [<ffffffff81ce7e7a>] driver_probe_device+0x21a/0xc30 [<ffffffff81ce89b1>] __driver_attach+0x121/0x160 [<ffffffff81ce21bf>] bus_for_each_dev+0x11f/0x1a0 [<ffffffff81ce6cdd>] driver_attach+0x3d/0x50 [<ffffffff81ce5df9>] bus_add_driver+0x4c9/0x770 [<ffffffff81cea39c>] driver_register+0x18c/0x3b0 [<ffffffff81db6e98>] usb_register_driver+0x1f8/0x440 [<ffffffffa074001e>] dib0700_driver_init+0x1e/0x1000 [dvb_usb_dib0700] [<ffffffff810021b1>] do_one_initcall+0x141/0x300 [<ffffffff8144d8eb>] do_init_module+0x1d0/0x5ad [<ffffffff812f27b6>] load_module+0x6666/0x9ba0 [<ffffffff812f5fe8>] SyS_finit_module+0x108/0x130 [<ffffffff822e8636>] entry_SYSCALL_64_fastpath+0x16/0x76 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&dev->lock); lock(s_active#171); lock(&dev->lock); lock(s_active#171); *** DEADLOCK *** 3 locks held by systemd-udevd/2681: #0: (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160 rib#1: (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160 rib#2: (&dev->lock){+.+.+.}, at: [<ffffffffa0724def>] rc_register_device+0xb2f/0x1450 [rc_core] In this specific case, some error happened during device init, causing IR to be disabled. Let's fix it by adding a var that will tell when the device is initialized. Any calls before that will return a -EINVAL. That should prevent the race issues. Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent eee7d35 commit c73bbaa

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

drivers/media/rc/rc-main.c

+26-19
Original file line numberDiff line numberDiff line change
@@ -723,12 +723,18 @@ int rc_open(struct rc_dev *rdev)
723723
return -EINVAL;
724724

725725
mutex_lock(&rdev->lock);
726+
if (!rdev->initialized) {
727+
rval = -EINVAL;
728+
goto unlock;
729+
}
730+
726731
if (!rdev->users++ && rdev->open != NULL)
727732
rval = rdev->open(rdev);
728733

729734
if (rval)
730735
rdev->users--;
731736

737+
unlock:
732738
mutex_unlock(&rdev->lock);
733739

734740
return rval;
@@ -874,6 +880,10 @@ static ssize_t show_protocols(struct device *device,
874880
return -EINVAL;
875881

876882
mutex_lock(&dev->lock);
883+
if (!dev->initialized) {
884+
mutex_unlock(&dev->lock);
885+
return -EINVAL;
886+
}
877887

878888
if (fattr->type == RC_FILTER_NORMAL) {
879889
enabled = dev->enabled_protocols;
@@ -1074,6 +1084,10 @@ static ssize_t store_protocols(struct device *device,
10741084
}
10751085

10761086
mutex_lock(&dev->lock);
1087+
if (!dev->initialized) {
1088+
rc = -EINVAL;
1089+
goto out;
1090+
}
10771091

10781092
old_protocols = *current_protocols;
10791093
new_protocols = old_protocols;
@@ -1154,12 +1168,17 @@ static ssize_t show_filter(struct device *device,
11541168
if (!dev)
11551169
return -EINVAL;
11561170

1171+
mutex_lock(&dev->lock);
1172+
if (!dev->initialized) {
1173+
mutex_unlock(&dev->lock);
1174+
return -EINVAL;
1175+
}
1176+
11571177
if (fattr->type == RC_FILTER_NORMAL)
11581178
filter = &dev->scancode_filter;
11591179
else
11601180
filter = &dev->scancode_wakeup_filter;
11611181

1162-
mutex_lock(&dev->lock);
11631182
if (fattr->mask)
11641183
val = filter->mask;
11651184
else
@@ -1222,6 +1241,10 @@ static ssize_t store_filter(struct device *device,
12221241
return -EINVAL;
12231242

12241243
mutex_lock(&dev->lock);
1244+
if (!dev->initialized) {
1245+
ret = -EINVAL;
1246+
goto unlock;
1247+
}
12251248

12261249
new_filter = *filter;
12271250
if (fattr->mask)
@@ -1419,14 +1442,6 @@ int rc_register_device(struct rc_dev *dev)
14191442
dev->sysfs_groups[attr++] = &rc_dev_wakeup_protocol_attr_grp;
14201443
dev->sysfs_groups[attr++] = NULL;
14211444

1422-
/*
1423-
* Take the lock here, as the device sysfs node will appear
1424-
* when device_add() is called, which may trigger an ir-keytable udev
1425-
* rule, which will in turn call show_protocols and access
1426-
* dev->enabled_protocols before it has been initialized.
1427-
*/
1428-
mutex_lock(&dev->lock);
1429-
14301445
rc = device_add(&dev->dev);
14311446
if (rc)
14321447
goto out_unlock;
@@ -1440,13 +1455,7 @@ int rc_register_device(struct rc_dev *dev)
14401455
dev->input_dev->phys = dev->input_phys;
14411456
dev->input_dev->name = dev->input_name;
14421457

1443-
/* input_register_device can call ir_open, so unlock mutex here */
1444-
mutex_unlock(&dev->lock);
1445-
14461458
rc = input_register_device(dev->input_dev);
1447-
1448-
mutex_lock(&dev->lock);
1449-
14501459
if (rc)
14511460
goto out_table;
14521461

@@ -1475,10 +1484,7 @@ int rc_register_device(struct rc_dev *dev)
14751484
request_module_nowait("ir-lirc-codec");
14761485
raw_init = true;
14771486
}
1478-
/* calls ir_register_device so unlock mutex here*/
1479-
mutex_unlock(&dev->lock);
14801487
rc = ir_raw_event_register(dev);
1481-
mutex_lock(&dev->lock);
14821488
if (rc < 0)
14831489
goto out_input;
14841490
}
@@ -1491,6 +1497,8 @@ int rc_register_device(struct rc_dev *dev)
14911497
dev->enabled_protocols = rc_type;
14921498
}
14931499

1500+
mutex_lock(&dev->lock);
1501+
dev->initialized = true;
14941502
mutex_unlock(&dev->lock);
14951503

14961504
IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
@@ -1512,7 +1520,6 @@ int rc_register_device(struct rc_dev *dev)
15121520
out_dev:
15131521
device_del(&dev->dev);
15141522
out_unlock:
1515-
mutex_unlock(&dev->lock);
15161523
ida_simple_remove(&rc_ida, minor);
15171524
return rc;
15181525
}

include/media/rc-core.h

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum rc_filter_type {
6060
/**
6161
* struct rc_dev - represents a remote control device
6262
* @dev: driver model's view of this device
63+
* @initialized: true if the device init has completed
6364
* @sysfs_groups: sysfs attribute groups
6465
* @input_name: name of the input child device
6566
* @input_phys: physical path to the input child device
@@ -121,6 +122,7 @@ enum rc_filter_type {
121122
*/
122123
struct rc_dev {
123124
struct device dev;
125+
bool initialized;
124126
const struct attribute_group *sysfs_groups[5];
125127
const char *input_name;
126128
const char *input_phys;

0 commit comments

Comments
 (0)