From cd08c4a5aade48adb5b5a568633c74c36afc55ab Mon Sep 17 00:00:00 2001 From: Liav A Date: Fri, 6 May 2022 14:49:13 +0300 Subject: [PATCH] Kernel/HID: Take a spinlock when calling KeyboardClient::on_key_pressed The KeyboardClient class member could be updated due to TTY switch, so we must ensure we always use a valid pointer. --- Kernel/Devices/HID/HIDManagement.cpp | 6 ++++++ Kernel/Devices/HID/HIDManagement.h | 3 ++- Kernel/Devices/HID/KeyboardDevice.cpp | 8 ++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Kernel/Devices/HID/HIDManagement.cpp b/Kernel/Devices/HID/HIDManagement.cpp index 51348c0e16..7641c0514c 100644 --- a/Kernel/Devices/HID/HIDManagement.cpp +++ b/Kernel/Devices/HID/HIDManagement.cpp @@ -75,6 +75,12 @@ static constexpr Keyboard::CharacterMapData DEFAULT_CHARACTER_MAP = }; // clang-format on +void HIDManagement::set_client(KeyboardClient* client) +{ + SpinlockLocker locker(m_client_lock); + m_client = client; +} + size_t HIDManagement::generate_minor_device_number_for_mouse() { // FIXME: Lock this to prevent race conditions with hot-plugging devices! diff --git a/Kernel/Devices/HID/HIDManagement.h b/Kernel/Devices/HID/HIDManagement.h index 9588bf8e7e..8806fbe7d1 100644 --- a/Kernel/Devices/HID/HIDManagement.h +++ b/Kernel/Devices/HID/HIDManagement.h @@ -50,7 +50,7 @@ public: u32 get_char_from_character_map(KeyEvent) const; - void set_client(KeyboardClient* client) { m_client = client; } + void set_client(KeyboardClient* client); void set_maps(NonnullOwnPtr character_map_name, Keyboard::CharacterMapData const& character_map); private: @@ -63,6 +63,7 @@ private: KeyboardClient* m_client { nullptr }; RefPtr m_i8042_controller; NonnullRefPtrVector m_hid_devices; + Spinlock m_client_lock; }; class KeyboardClient { diff --git a/Kernel/Devices/HID/KeyboardDevice.cpp b/Kernel/Devices/HID/KeyboardDevice.cpp index ee1179cb54..32daf78116 100644 --- a/Kernel/Devices/HID/KeyboardDevice.cpp +++ b/Kernel/Devices/HID/KeyboardDevice.cpp @@ -254,8 +254,12 @@ void KeyboardDevice::key_state_changed(u8 scan_code, bool pressed) if (pressed) event.flags |= Is_Press; - if (HIDManagement::the().m_client) - HIDManagement::the().m_client->on_key_pressed(event); + + { + SpinlockLocker locker(HIDManagement::the().m_client_lock); + if (HIDManagement::the().m_client) + HIDManagement::the().m_client->on_key_pressed(event); + } { SpinlockLocker lock(m_queue_lock);