diff options
| author | Eduard Zingerman <eddyz87@gmail.com> | 2026-09-04 17:05:56 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-04 18:17:30 -0700 |
| commit | 506ada89629ec7059b96ecfb0dc7d33ece0103ca (patch) | |
| tree | 0b07297409b68d2333fb4f0eae7f3b072eb68d4c /drivers/accessibility/speakup/fakekey.c | |
| download | linux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.tar.gz linux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.zip | |
bpf: mark a NULL kfunc argument precisegrafted
check_kfunc_arg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.
Fixes: 3bda08b63670 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-5-0f5a360ff15d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'drivers/accessibility/speakup/fakekey.c')
| -rw-r--r-- | drivers/accessibility/speakup/fakekey.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/accessibility/speakup/fakekey.c b/drivers/accessibility/speakup/fakekey.c new file mode 100644 index 000000000..868c47b2a --- /dev/null +++ b/drivers/accessibility/speakup/fakekey.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* fakekey.c + * Functions for simulating key presses. + * + * Copyright (C) 2010 the Speakup Team + */ +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/preempt.h> +#include <linux/percpu.h> +#include <linux/input.h> + +#include "speakup.h" + +#define PRESSED 1 +#define RELEASED 0 + +static DEFINE_PER_CPU(int, reporting_keystroke); + +static struct input_dev *virt_keyboard; + +int speakup_add_virtual_keyboard(void) +{ + int err; + + virt_keyboard = input_allocate_device(); + + if (!virt_keyboard) + return -ENOMEM; + + virt_keyboard->name = "Speakup"; + virt_keyboard->id.bustype = BUS_VIRTUAL; + virt_keyboard->phys = "speakup/input0"; + virt_keyboard->dev.parent = NULL; + + __set_bit(EV_KEY, virt_keyboard->evbit); + __set_bit(KEY_DOWN, virt_keyboard->keybit); + + err = input_register_device(virt_keyboard); + if (err) { + input_free_device(virt_keyboard); + virt_keyboard = NULL; + } + + return err; +} + +void speakup_remove_virtual_keyboard(void) +{ + if (virt_keyboard) { + input_unregister_device(virt_keyboard); + virt_keyboard = NULL; + } +} + +/* + * Send a simulated down-arrow to the application. + */ +void speakup_fake_down_arrow(void) +{ + unsigned long flags; + + /* disable keyboard interrupts */ + local_irq_save(flags); + /* don't change CPU */ + preempt_disable(); + + __this_cpu_write(reporting_keystroke, true); + input_report_key(virt_keyboard, KEY_DOWN, PRESSED); + input_report_key(virt_keyboard, KEY_DOWN, RELEASED); + input_sync(virt_keyboard); + __this_cpu_write(reporting_keystroke, false); + + /* reenable preemption */ + preempt_enable(); + /* reenable keyboard interrupts */ + local_irq_restore(flags); +} + +/* + * Are we handling a simulated key press on the current CPU? + * Returns a boolean. + */ +bool speakup_fake_key_pressed(void) +{ + return this_cpu_read(reporting_keystroke); +} |
