aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2011-05-11 14:14:31 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 15:21:22 -0400
commit08aeb7c9a42ab7aa8b53c8f7779ec58f860a565c (patch)
tree03bd9f53baecbc565adeb94c8a464cc97abc4411 /include
parent51ea62927e5bbb577360dd92c3f282edbf4cd3f8 (diff)
[media] rc: add locking to fix register/show race
When device_add is called in rc_register_device, the rc sysfs nodes show up, and there's a window in which ir-keytable can be launched via udev and trigger a show_protocols call, which runs without various rc_dev fields filled in yet. Add some locking around registration and store/show_protocols to prevent that from happening. The problem manifests thusly: [64692.957872] BUG: unable to handle kernel NULL pointer dereference at 0000000000000090 [64692.957878] IP: [<ffffffffa036a4c1>] show_protocols+0x47/0xf1 [rc_core] [64692.957890] PGD 19cfc7067 PUD 19cfc6067 PMD 0 [64692.957894] Oops: 0000 [#1] SMP [64692.957897] last sysfs file: /sys/devices/pci0000:00/0000:00:03.1/usb3/3-1/3-1:1.0/rc/rc2/protocols [64692.957902] CPU 3 [64692.957903] Modules linked in: redrat3(+) ir_lirc_codec lirc_dev ir_sony_decoder ir_jvc_decoder ir_rc6_decoder ir_rc5_decoder rc_hauppauge ir_nec _decoder rc_core ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables snd_emu10k1_synth snd_emux_synth snd_seq_virmidi snd_seq_mi di_event snd_seq_midi_emul snd_emu10k1 snd_rawmidi snd_ac97_codec ac97_bus snd_seq snd_pcm snd_seq_device snd_timer snd_page_alloc snd_util_mem pcsp kr tg3 snd_hwdep emu10k1_gp snd amd64_edac_mod gameport edac_core soundcore edac_mce_amd k8temp shpchp i2c_piix4 lm63 e100 mii uinput ipv6 raid0 rai d1 ata_generic firewire_ohci pata_acpi firewire_core crc_itu_t sata_svw pata_serverworks floppy radeon ttm drm_kms_helper drm i2c_algo_bit i2c_core [last unloaded: redrat3] [64692.957949] [64692.957952] Pid: 12265, comm: ir-keytable Tainted: G M W 2.6.39-rc6+ #2 empty empty/TYAN Thunder K8HM S3892 [64692.957957] RIP: 0010:[<ffffffffa036a4c1>] [<ffffffffa036a4c1>] show_protocols+0x47/0xf1 [rc_core] [64692.957962] RSP: 0018:ffff880194509e38 EFLAGS: 00010202 [64692.957964] RAX: 0000000000000000 RBX: ffffffffa036d1e0 RCX: ffffffffa036a47a [64692.957966] RDX: ffff88019a84d000 RSI: ffffffffa036d1e0 RDI: ffff88019cf2f3f0 [64692.957969] RBP: ffff880194509e68 R08: 0000000000000002 R09: 0000000000000000 [64692.957971] R10: 0000000000000002 R11: 0000000000001617 R12: ffff88019a84d000 [64692.957973] R13: 0000000000001000 R14: ffff8801944d2e38 R15: ffff88019ce5f190 [64692.957976] FS: 00007f0a30c9a720(0000) GS:ffff88019fc00000(0000) knlGS:0000000000000000 [64692.957979] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [64692.957981] CR2: 0000000000000090 CR3: 000000019a8e0000 CR4: 00000000000006e0 [64692.957983] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [64692.957986] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [64692.957989] Process ir-keytable (pid: 12265, threadinfo ffff880194508000, task ffff88019a9fc720) [64692.957991] Stack: [64692.957992] 0000000000000002 ffffffffa036d1e0 ffff880194509f58 0000000000001000 [64692.957997] ffff8801944d2e38 ffff88019ce5f190 ffff880194509e98 ffffffff8131484b [64692.958001] ffffffff8118e923 ffffffff810e9b2f ffff880194509e98 ffff8801944d2e18 [64692.958005] Call Trace: [64692.958014] [<ffffffff8131484b>] dev_attr_show+0x27/0x4e [64692.958014] [<ffffffff8118e923>] ? sysfs_read_file+0x94/0x172 [64692.958014] [<ffffffff810e9b2f>] ? __get_free_pages+0x16/0x52 [64692.958014] [<ffffffff8118e94c>] sysfs_read_file+0xbd/0x172 [64692.958014] [<ffffffff8113205e>] vfs_read+0xac/0xf3 [64692.958014] [<ffffffff8113347b>] ? fget_light+0x3a/0xa1 [64692.958014] [<ffffffff811320f2>] sys_read+0x4d/0x74 [64692.958014] [<ffffffff814c19c2>] system_call_fastpath+0x16/0x1b Its a bit difficult to reproduce, but I'm fairly confident this has fixed the problem. Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/media/rc-core.h7
1 files changed, 5 insertions, 2 deletions
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 2963263f31e2..60536c74c1ea 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -40,10 +40,12 @@ enum rc_driver_type {
40 * @driver_name: name of the hardware driver which registered this device 40 * @driver_name: name of the hardware driver which registered this device
41 * @map_name: name of the default keymap 41 * @map_name: name of the default keymap
42 * @rc_map: current scan/key table 42 * @rc_map: current scan/key table
43 * @lock: used to ensure we've filled in all protocol details before
44 * anyone can call show_protocols or store_protocols
43 * @devno: unique remote control device number 45 * @devno: unique remote control device number
44 * @raw: additional data for raw pulse/space devices 46 * @raw: additional data for raw pulse/space devices
45 * @input_dev: the input child device used to communicate events to userspace 47 * @input_dev: the input child device used to communicate events to userspace
46 * @driver_type: specifies if protocol decoding is done in hardware or software 48 * @driver_type: specifies if protocol decoding is done in hardware or software
47 * @idle: used to keep track of RX state 49 * @idle: used to keep track of RX state
48 * @allowed_protos: bitmask with the supported RC_TYPE_* protocols 50 * @allowed_protos: bitmask with the supported RC_TYPE_* protocols
49 * @scanmask: some hardware decoders are not capable of providing the full 51 * @scanmask: some hardware decoders are not capable of providing the full
@@ -86,7 +88,8 @@ struct rc_dev {
86 struct input_id input_id; 88 struct input_id input_id;
87 char *driver_name; 89 char *driver_name;
88 const char *map_name; 90 const char *map_name;
89 struct rc_map rc_map; 91 struct rc_map rc_map;
92 struct mutex lock;
90 unsigned long devno; 93 unsigned long devno;
91 struct ir_raw_event_ctrl *raw; 94 struct ir_raw_event_ctrl *raw;
92 struct input_dev *input_dev; 95 struct input_dev *input_dev;