aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-12-02 00:54:35 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-12-02 00:57:48 -0500
commit66d2a5952eab875f1286e04f738ef029afdaf013 (patch)
tree6d30e807108ef7d2a56ec43271c45acc357df699
parent6ee88d713fb75ab191515f66edffa4e866386565 (diff)
Input: keyboard - fix lack of locking when traversing handler->h_list
Keyboard handler should not attempt to traverse handler->h_list on its own, without any locking, otherwise it races with registering and unregistering of input handles which leads to crashes. Introduce input_handler_for_each_handle() helper that allows safely iterate over all handles attached to a particular handler and switch keyboard handler to use it. Reported-by: Jim Paradis <jparadis@redhat.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/char/keyboard.c202
-rw-r--r--drivers/input/input.c37
-rw-r--r--include/linux/input.h10
3 files changed, 148 insertions, 101 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index ca090e57e161..ff8e9345f3c9 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -46,8 +46,6 @@
46 46
47extern void ctrl_alt_del(void); 47extern void ctrl_alt_del(void);
48 48
49#define to_handle_h(n) container_of(n, struct input_handle, h_node)
50
51/* 49/*
52 * Exported functions/variables 50 * Exported functions/variables
53 */ 51 */
@@ -191,78 +189,85 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
191 * etc.). So this means that scancodes for the extra function keys won't 189 * etc.). So this means that scancodes for the extra function keys won't
192 * be valid for the first event device, but will be for the second. 190 * be valid for the first event device, but will be for the second.
193 */ 191 */
192
193struct getset_keycode_data {
194 unsigned int scancode;
195 unsigned int keycode;
196 int error;
197};
198
199static int getkeycode_helper(struct input_handle *handle, void *data)
200{
201 struct getset_keycode_data *d = data;
202
203 d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode);
204
205 return d->error == 0; /* stop as soon as we successfully get one */
206}
207
194int getkeycode(unsigned int scancode) 208int getkeycode(unsigned int scancode)
195{ 209{
196 struct input_handle *handle; 210 struct getset_keycode_data d = { scancode, 0, -ENODEV };
197 int keycode;
198 int error = -ENODEV;
199 211
200 list_for_each_entry(handle, &kbd_handler.h_list, h_node) { 212 input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
201 error = input_get_keycode(handle->dev, scancode, &keycode);
202 if (!error)
203 return keycode;
204 }
205 213
206 return error; 214 return d.error ?: d.keycode;
215}
216
217static int setkeycode_helper(struct input_handle *handle, void *data)
218{
219 struct getset_keycode_data *d = data;
220
221 d->error = input_set_keycode(handle->dev, d->scancode, d->keycode);
222
223 return d->error == 0; /* stop as soon as we successfully set one */
207} 224}
208 225
209int setkeycode(unsigned int scancode, unsigned int keycode) 226int setkeycode(unsigned int scancode, unsigned int keycode)
210{ 227{
211 struct input_handle *handle; 228 struct getset_keycode_data d = { scancode, keycode, -ENODEV };
212 int error = -ENODEV;
213 229
214 list_for_each_entry(handle, &kbd_handler.h_list, h_node) { 230 input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
215 error = input_set_keycode(handle->dev, scancode, keycode);
216 if (!error)
217 break;
218 }
219 231
220 return error; 232 return d.error;
221} 233}
222 234
223/* 235/*
224 * Making beeps and bells. 236 * Making beeps and bells.
225 */ 237 */
226static void kd_nosound(unsigned long ignored) 238
239static int kd_sound_helper(struct input_handle *handle, void *data)
227{ 240{
228 struct input_handle *handle; 241 unsigned int *hz = data;
242 struct input_dev *dev = handle->dev;
229 243
230 list_for_each_entry(handle, &kbd_handler.h_list, h_node) { 244 if (test_bit(EV_SND, dev->evbit)) {
231 if (test_bit(EV_SND, handle->dev->evbit)) { 245 if (test_bit(SND_TONE, dev->sndbit))
232 if (test_bit(SND_TONE, handle->dev->sndbit)) 246 input_inject_event(handle, EV_SND, SND_TONE, *hz);
233 input_inject_event(handle, EV_SND, SND_TONE, 0); 247 if (test_bit(SND_BELL, handle->dev->sndbit))
234 if (test_bit(SND_BELL, handle->dev->sndbit)) 248 input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
235 input_inject_event(handle, EV_SND, SND_BELL, 0);
236 }
237 } 249 }
250
251 return 0;
252}
253
254static void kd_nosound(unsigned long ignored)
255{
256 static unsigned int zero;
257
258 input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
238} 259}
239 260
240static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0); 261static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
241 262
242void kd_mksound(unsigned int hz, unsigned int ticks) 263void kd_mksound(unsigned int hz, unsigned int ticks)
243{ 264{
244 struct list_head *node; 265 del_timer_sync(&kd_mksound_timer);
245 266
246 del_timer(&kd_mksound_timer); 267 input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
247 268
248 if (hz) { 269 if (hz && ticks)
249 list_for_each_prev(node, &kbd_handler.h_list) { 270 mod_timer(&kd_mksound_timer, jiffies + ticks);
250 struct input_handle *handle = to_handle_h(node);
251 if (test_bit(EV_SND, handle->dev->evbit)) {
252 if (test_bit(SND_TONE, handle->dev->sndbit)) {
253 input_inject_event(handle, EV_SND, SND_TONE, hz);
254 break;
255 }
256 if (test_bit(SND_BELL, handle->dev->sndbit)) {
257 input_inject_event(handle, EV_SND, SND_BELL, 1);
258 break;
259 }
260 }
261 }
262 if (ticks)
263 mod_timer(&kd_mksound_timer, jiffies + ticks);
264 } else
265 kd_nosound(0);
266} 271}
267EXPORT_SYMBOL(kd_mksound); 272EXPORT_SYMBOL(kd_mksound);
268 273
@@ -270,27 +275,34 @@ EXPORT_SYMBOL(kd_mksound);
270 * Setting the keyboard rate. 275 * Setting the keyboard rate.
271 */ 276 */
272 277
273int kbd_rate(struct kbd_repeat *rep) 278static int kbd_rate_helper(struct input_handle *handle, void *data)
274{ 279{
275 struct list_head *node; 280 struct input_dev *dev = handle->dev;
276 unsigned int d = 0; 281 struct kbd_repeat *rep = data;
277 unsigned int p = 0; 282
278 283 if (test_bit(EV_REP, dev->evbit)) {
279 list_for_each(node, &kbd_handler.h_list) { 284
280 struct input_handle *handle = to_handle_h(node); 285 if (rep[0].delay > 0)
281 struct input_dev *dev = handle->dev; 286 input_inject_event(handle,
282 287 EV_REP, REP_DELAY, rep[0].delay);
283 if (test_bit(EV_REP, dev->evbit)) { 288 if (rep[0].period > 0)
284 if (rep->delay > 0) 289 input_inject_event(handle,
285 input_inject_event(handle, EV_REP, REP_DELAY, rep->delay); 290 EV_REP, REP_PERIOD, rep[0].period);
286 if (rep->period > 0) 291
287 input_inject_event(handle, EV_REP, REP_PERIOD, rep->period); 292 rep[1].delay = dev->rep[REP_DELAY];
288 d = dev->rep[REP_DELAY]; 293 rep[1].period = dev->rep[REP_PERIOD];
289 p = dev->rep[REP_PERIOD];
290 }
291 } 294 }
292 rep->delay = d; 295
293 rep->period = p; 296 return 0;
297}
298
299int kbd_rate(struct kbd_repeat *rep)
300{
301 struct kbd_repeat data[2] = { *rep };
302
303 input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
304 *rep = data[1]; /* Copy currently used settings */
305
294 return 0; 306 return 0;
295} 307}
296 308
@@ -998,36 +1010,36 @@ static inline unsigned char getleds(void)
998 return leds; 1010 return leds;
999} 1011}
1000 1012
1013static int kbd_update_leds_helper(struct input_handle *handle, void *data)
1014{
1015 unsigned char leds = *(unsigned char *)data;
1016
1017 if (test_bit(EV_LED, handle->dev->evbit)) {
1018 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
1019 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1020 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1021 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1022 }
1023
1024 return 0;
1025}
1026
1001/* 1027/*
1002 * This routine is the bottom half of the keyboard interrupt 1028 * This is the tasklet that updates LED state on all keyboards
1003 * routine, and runs with all interrupts enabled. It does 1029 * attached to the box. The reason we use tasklet is that we
1004 * console changing, led setting and copy_to_cooked, which can 1030 * need to handle the scenario when keyboard handler is not
1005 * take a reasonably long time. 1031 * registered yet but we already getting updates form VT to
1006 * 1032 * update led state.
1007 * Aside from timing (which isn't really that important for
1008 * keyboard interrupts as they happen often), using the software
1009 * interrupt routines for this thing allows us to easily mask
1010 * this when we don't want any of the above to happen.
1011 * This allows for easy and efficient race-condition prevention
1012 * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
1013 */ 1033 */
1014
1015static void kbd_bh(unsigned long dummy) 1034static void kbd_bh(unsigned long dummy)
1016{ 1035{
1017 struct list_head *node;
1018 unsigned char leds = getleds(); 1036 unsigned char leds = getleds();
1019 1037
1020 if (leds != ledstate) { 1038 if (leds != ledstate) {
1021 list_for_each(node, &kbd_handler.h_list) { 1039 input_handler_for_each_handle(&kbd_handler, &leds,
1022 struct input_handle *handle = to_handle_h(node); 1040 kbd_update_leds_helper);
1023 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); 1041 ledstate = leds;
1024 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
1025 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
1026 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1027 }
1028 } 1042 }
1029
1030 ledstate = leds;
1031} 1043}
1032 1044
1033DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); 1045DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
@@ -1370,15 +1382,11 @@ static void kbd_disconnect(struct input_handle *handle)
1370 */ 1382 */
1371static void kbd_start(struct input_handle *handle) 1383static void kbd_start(struct input_handle *handle)
1372{ 1384{
1373 unsigned char leds = ledstate;
1374
1375 tasklet_disable(&keyboard_tasklet); 1385 tasklet_disable(&keyboard_tasklet);
1376 if (leds != 0xff) { 1386
1377 input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); 1387 if (ledstate != 0xff)
1378 input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); 1388 kbd_update_leds_helper(handle, &ledstate);
1379 input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); 1389
1380 input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
1381 }
1382 tasklet_enable(&keyboard_tasklet); 1390 tasklet_enable(&keyboard_tasklet);
1383} 1391}
1384 1392
diff --git a/drivers/input/input.c b/drivers/input/input.c
index cc763c96fada..5d6421bde4ba 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1651,6 +1651,38 @@ void input_unregister_handler(struct input_handler *handler)
1651EXPORT_SYMBOL(input_unregister_handler); 1651EXPORT_SYMBOL(input_unregister_handler);
1652 1652
1653/** 1653/**
1654 * input_handler_for_each_handle - handle iterator
1655 * @handler: input handler to iterate
1656 * @data: data for the callback
1657 * @fn: function to be called for each handle
1658 *
1659 * Iterate over @bus's list of devices, and call @fn for each, passing
1660 * it @data and stop when @fn returns a non-zero value. The function is
1661 * using RCU to traverse the list and therefore may be usind in atonic
1662 * contexts. The @fn callback is invoked from RCU critical section and
1663 * thus must not sleep.
1664 */
1665int input_handler_for_each_handle(struct input_handler *handler, void *data,
1666 int (*fn)(struct input_handle *, void *))
1667{
1668 struct input_handle *handle;
1669 int retval = 0;
1670
1671 rcu_read_lock();
1672
1673 list_for_each_entry_rcu(handle, &handler->h_list, h_node) {
1674 retval = fn(handle, data);
1675 if (retval)
1676 break;
1677 }
1678
1679 rcu_read_unlock();
1680
1681 return retval;
1682}
1683EXPORT_SYMBOL(input_handler_for_each_handle);
1684
1685/**
1654 * input_register_handle - register a new input handle 1686 * input_register_handle - register a new input handle
1655 * @handle: handle to register 1687 * @handle: handle to register
1656 * 1688 *
@@ -1683,7 +1715,7 @@ int input_register_handle(struct input_handle *handle)
1683 * we can't be racing with input_unregister_handle() 1715 * we can't be racing with input_unregister_handle()
1684 * and so separate lock is not needed here. 1716 * and so separate lock is not needed here.
1685 */ 1717 */
1686 list_add_tail(&handle->h_node, &handler->h_list); 1718 list_add_tail_rcu(&handle->h_node, &handler->h_list);
1687 1719
1688 if (handler->start) 1720 if (handler->start)
1689 handler->start(handle); 1721 handler->start(handle);
@@ -1706,7 +1738,7 @@ void input_unregister_handle(struct input_handle *handle)
1706{ 1738{
1707 struct input_dev *dev = handle->dev; 1739 struct input_dev *dev = handle->dev;
1708 1740
1709 list_del_init(&handle->h_node); 1741 list_del_rcu(&handle->h_node);
1710 1742
1711 /* 1743 /*
1712 * Take dev->mutex to prevent race with input_release_device(). 1744 * Take dev->mutex to prevent race with input_release_device().
@@ -1714,6 +1746,7 @@ void input_unregister_handle(struct input_handle *handle)
1714 mutex_lock(&dev->mutex); 1746 mutex_lock(&dev->mutex);
1715 list_del_rcu(&handle->d_node); 1747 list_del_rcu(&handle->d_node);
1716 mutex_unlock(&dev->mutex); 1748 mutex_unlock(&dev->mutex);
1749
1717 synchronize_rcu(); 1750 synchronize_rcu();
1718} 1751}
1719EXPORT_SYMBOL(input_unregister_handle); 1752EXPORT_SYMBOL(input_unregister_handle);
diff --git a/include/linux/input.h b/include/linux/input.h
index 56d8e048c646..db563bbac9dd 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1021,9 +1021,12 @@ struct ff_effect {
1021 * @keycodesize: size of elements in keycode table 1021 * @keycodesize: size of elements in keycode table
1022 * @keycode: map of scancodes to keycodes for this device 1022 * @keycode: map of scancodes to keycodes for this device
1023 * @setkeycode: optional method to alter current keymap, used to implement 1023 * @setkeycode: optional method to alter current keymap, used to implement
1024 * sparse keymaps. If not supplied default mechanism will be used 1024 * sparse keymaps. If not supplied default mechanism will be used.
1025 * The method is being called while holding event_lock and thus must
1026 * not sleep
1025 * @getkeycode: optional method to retrieve current keymap. If not supplied 1027 * @getkeycode: optional method to retrieve current keymap. If not supplied
1026 * default mechanism will be used 1028 * default mechanism will be used. The method is being called while
1029 * holding event_lock and thus must not sleep
1027 * @ff: force feedback structure associated with the device if device 1030 * @ff: force feedback structure associated with the device if device
1028 * supports force feedback effects 1031 * supports force feedback effects
1029 * @repeat_key: stores key code of the last key pressed; used to implement 1032 * @repeat_key: stores key code of the last key pressed; used to implement
@@ -1295,6 +1298,9 @@ void input_unregister_device(struct input_dev *);
1295int __must_check input_register_handler(struct input_handler *); 1298int __must_check input_register_handler(struct input_handler *);
1296void input_unregister_handler(struct input_handler *); 1299void input_unregister_handler(struct input_handler *);
1297 1300
1301int input_handler_for_each_handle(struct input_handler *, void *data,
1302 int (*fn)(struct input_handle *, void *));
1303
1298int input_register_handle(struct input_handle *); 1304int input_register_handle(struct input_handle *);
1299void input_unregister_handle(struct input_handle *); 1305void input_unregister_handle(struct input_handle *);
1300 1306