Skip to content

Fix null pointer segfault in find_keyboard_device() - #2

Open
randytate wants to merge 1 commit into
m-bartlett:mainfrom
randytate:fix-null-ptr-and-meta-suppression
Open

Fix null pointer segfault in find_keyboard_device()#2
randytate wants to merge 1 commit into
m-bartlett:mainfrom
randytate:fix-null-ptr-and-meta-suppression

Conversation

@randytate

Copy link
Copy Markdown

Fix null pointer segfault in find_keyboard_device() + meta suppression for correct RightCtrl mapping

Hardware & OS

  • Laptop: LG Gram Ultra 7 Series 2 (14Z90T-G.ADB6U1)
  • OS: Fedora 43

Bug 1: Null pointer segfault in find_keyboard_device()

Problem

On Fedora 43, running remap-copilot without a --device argument immediately segfaults:

Segmentation fault (core dumped) remap-copilot

The coredump points to libevdev_free() inside find_keyboard_device():

#0  libevdev_free (libevdev.so.2)
#1  find_keyboard_device (/usr/local/bin/remap-copilot)
#2  main (/usr/local/bin/remap-copilot)

Root Cause

test_dev is declared but never initialized in find_keyboard_device(). When neither scan loop finds a matching device and execution falls through to find_keyboard_device_end, libevdev_free(test_dev) is called on an uninitialized pointer, causing the segfault.

Fix

Initialize test_dev to NULL. libevdev_free(NULL) is a safe no-op, correctly handling the no-device-found path.

// Before
struct libevdev *test_dev;

// After
struct libevdev *test_dev = NULL;

Bug 2: KEY_LEFTMETA and KEY_LEFTSHIFT leak through to the virtual device

Problem

Even after the null pointer fix, the Copilot key does not correctly behave as RightCtrl for key combinations. For example, pressing Copilot + = in Chrome does not zoom in. Monitoring the virtual uinput device with evtest reveals that KEY_LEFTMETA and KEY_LEFTSHIFT are being passed through alongside KEY_RIGHTCTRL:

KEY_LEFTMETA    value 1
KEY_LEFTSHIFT   value 1
KEY_RIGHTCTRL   value 1
KEY_EQUAL       value 1

Applications see Meta+Shift+RightCtrl+Equal instead of the intended RightCtrl+Equal, so shortcuts do not fire correctly.

Root Cause

The existing code only suppresses KEY_LEFTMETA and KEY_LEFTSHIFT passthrough after copilot_active is set — but by then both modifier keys have already been forwarded to the virtual device. The suppression is too late.

Fix

Buffer KEY_LEFTMETA on keydown rather than forwarding it immediately. If KEY_F23 follows (confirming a Copilot sequence), the buffered meta event is discarded. If meta is released without F23 — meaning it was a genuine Super key tap — the buffered down+up pair is flushed to the virtual device so normal Super key behavior (e.g. GNOME Activities) is preserved.

KEY_LEFTSHIFT is suppressed whenever meta_pressed is true, since shift only ever appears alongside meta as part of the Copilot chord.

case KEY_LEFTMETA:
    key_state.meta_pressed = (event.value != KEY_RELEASED);
    if (event.value == KEY_PRESSED) {
        key_state.meta_suppressed = true;
        goto skip_event_write;
    } else {
        if (key_state.meta_suppressed && !key_state.copilot_active) {
            // Genuine Super key tap - flush buffered down+up
            libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTMETA, 1);
            libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
        }
        key_state.meta_suppressed = false;
        if (key_state.copilot_active) goto skip_event_write;
        break;
    }
case KEY_LEFTSHIFT:
    key_state.shift_pressed = (event.value != KEY_RELEASED);
    if (key_state.meta_pressed || key_state.copilot_active) goto skip_event_write;
    break;

Testing

Verified on LG Gram Ultra 7 Series 2 (14Z90T-G.ADB6U1) running Fedora 43:

  • remap-copilot --list correctly enumerates input devices without crashing
  • remap-copilot --verbose successfully finds, grabs, and remaps the Copilot key on /dev/input/event3 (AT Translated Set 2 keyboard)
  • evtest on the virtual uinput device confirms clean KEY_RIGHTCTRL output with no meta/shift leakthrough
  • Copilot + = correctly zooms in Chrome
  • Super key tap alone correctly opens GNOME Activities
  • Confirmed working as a persistent user systemd service via make install-systemd

Note: Bug 1 (null pointer) is self-contained and can be merged independently. Bug 2 (meta suppression) is included here as it is required for the tool to actually function correctly as a RightCtrl replacement on this hardware.

test_dev was uninitialized when no device was found, causing
libevdev_free() to be called on a garbage pointer. Initialize
to NULL so libevdev_free(NULL) is safe.
@FalsePhilosopher

Copy link
Copy Markdown

Can confirm this does fix the issue. It doesn't detect my copilot button but it doesn't segfault anymore.

@randytate

Copy link
Copy Markdown
Author

Can confirm this does fix the issue. It doesn't detect my copilot button but it doesn't segfault anymore.

Yeah, it's working well for me ... using this LG Gram now. So glad I have a right-ctrl key again 'cause I use it for a lot of keyboard shortcuts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants