Commit 5fdbe44d authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: do not pass injected events back to the originating handler

Sometimes input handlers (as opposed to input devices) have a need to
inject (or re-inject) events back into input core. For example sysrq
filter may want to inject previously suppressed Alt-SysRq so that user
can take a screen print. In this case we do not want to pass such events
back to the same same handler that injected them to avoid loops.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 17d01f28
...@@ -74,6 +74,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) ...@@ -74,6 +74,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
* dev->event_lock held and interrupts disabled. * dev->event_lock held and interrupts disabled.
*/ */
static void input_pass_event(struct input_dev *dev, static void input_pass_event(struct input_dev *dev,
struct input_handler *src_handler,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
struct input_handler *handler; struct input_handler *handler;
...@@ -92,6 +93,15 @@ static void input_pass_event(struct input_dev *dev, ...@@ -92,6 +93,15 @@ static void input_pass_event(struct input_dev *dev,
continue; continue;
handler = handle->handler; handler = handle->handler;
/*
* If this is the handler that injected this
* particular event we want to skip it to avoid
* filters firing again and again.
*/
if (handler == src_handler)
continue;
if (!handler->filter) { if (!handler->filter) {
if (filtered) if (filtered)
break; break;
...@@ -121,7 +131,7 @@ static void input_repeat_key(unsigned long data) ...@@ -121,7 +131,7 @@ static void input_repeat_key(unsigned long data)
if (test_bit(dev->repeat_key, dev->key) && if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
input_pass_event(dev, EV_KEY, dev->repeat_key, 2); input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2);
if (dev->sync) { if (dev->sync) {
/* /*
...@@ -130,7 +140,7 @@ static void input_repeat_key(unsigned long data) ...@@ -130,7 +140,7 @@ static void input_repeat_key(unsigned long data)
* Otherwise assume that the driver will send * Otherwise assume that the driver will send
* SYN_REPORT once it's done. * SYN_REPORT once it's done.
*/ */
input_pass_event(dev, EV_SYN, SYN_REPORT, 1); input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
} }
if (dev->rep[REP_PERIOD]) if (dev->rep[REP_PERIOD])
...@@ -163,6 +173,7 @@ static void input_stop_autorepeat(struct input_dev *dev) ...@@ -163,6 +173,7 @@ static void input_stop_autorepeat(struct input_dev *dev)
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
static int input_handle_abs_event(struct input_dev *dev, static int input_handle_abs_event(struct input_dev *dev,
struct input_handler *src_handler,
unsigned int code, int *pval) unsigned int code, int *pval)
{ {
bool is_mt_event; bool is_mt_event;
...@@ -206,13 +217,15 @@ static int input_handle_abs_event(struct input_dev *dev, ...@@ -206,13 +217,15 @@ static int input_handle_abs_event(struct input_dev *dev,
/* Flush pending "slot" event */ /* Flush pending "slot" event */
if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); input_pass_event(dev, src_handler,
EV_ABS, ABS_MT_SLOT, dev->slot);
} }
return INPUT_PASS_TO_HANDLERS; return INPUT_PASS_TO_HANDLERS;
} }
static void input_handle_event(struct input_dev *dev, static void input_handle_event(struct input_dev *dev,
struct input_handler *src_handler,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
int disposition = INPUT_IGNORE_EVENT; int disposition = INPUT_IGNORE_EVENT;
...@@ -265,7 +278,8 @@ static void input_handle_event(struct input_dev *dev, ...@@ -265,7 +278,8 @@ static void input_handle_event(struct input_dev *dev,
case EV_ABS: case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX)) if (is_event_supported(code, dev->absbit, ABS_MAX))
disposition = input_handle_abs_event(dev, code, &value); disposition = input_handle_abs_event(dev, src_handler,
code, &value);
break; break;
...@@ -323,7 +337,7 @@ static void input_handle_event(struct input_dev *dev, ...@@ -323,7 +337,7 @@ static void input_handle_event(struct input_dev *dev,
dev->event(dev, type, code, value); dev->event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS) if (disposition & INPUT_PASS_TO_HANDLERS)
input_pass_event(dev, type, code, value); input_pass_event(dev, src_handler, type, code, value);
} }
/** /**
...@@ -352,7 +366,7 @@ void input_event(struct input_dev *dev, ...@@ -352,7 +366,7 @@ void input_event(struct input_dev *dev,
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
add_input_randomness(type, code, value); add_input_randomness(type, code, value);
input_handle_event(dev, type, code, value); input_handle_event(dev, NULL, type, code, value);
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
} }
} }
...@@ -382,7 +396,8 @@ void input_inject_event(struct input_handle *handle, ...@@ -382,7 +396,8 @@ void input_inject_event(struct input_handle *handle,
rcu_read_lock(); rcu_read_lock();
grab = rcu_dereference(dev->grab); grab = rcu_dereference(dev->grab);
if (!grab || grab == handle) if (!grab || grab == handle)
input_handle_event(dev, type, code, value); input_handle_event(dev, handle->handler,
type, code, value);
rcu_read_unlock(); rcu_read_unlock();
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
...@@ -595,10 +610,10 @@ static void input_dev_release_keys(struct input_dev *dev) ...@@ -595,10 +610,10 @@ static void input_dev_release_keys(struct input_dev *dev)
for (code = 0; code <= KEY_MAX; code++) { for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) && if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) { __test_and_clear_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0); input_pass_event(dev, NULL, EV_KEY, code, 0);
} }
} }
input_pass_event(dev, EV_SYN, SYN_REPORT, 1); input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
} }
} }
...@@ -873,9 +888,9 @@ int input_set_keycode(struct input_dev *dev, ...@@ -873,9 +888,9 @@ int input_set_keycode(struct input_dev *dev,
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) && !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(old_keycode, dev->key)) { __test_and_clear_bit(old_keycode, dev->key)) {
input_pass_event(dev, EV_KEY, old_keycode, 0); input_pass_event(dev, NULL, EV_KEY, old_keycode, 0);
if (dev->sync) if (dev->sync)
input_pass_event(dev, EV_SYN, SYN_REPORT, 1); input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
} }
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment