* [PATCH v2 0/3] platform/x86: panasonic-laptop: CF-33 hotkey fixes
@ 2026-08-13 22:17 Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 1/3] platform/x86: panasonic-laptop: Handle CF-33 rotation-lock button Hilgad Montelo
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Hilgad Montelo @ 2026-08-13 22:17 UTC (permalink / raw)
To: kenneth.t.chan, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Hilgad Montelo
This series fixes two non-working buttons on the Panasonic Toughbook
CF-33 Mk1 and an independent bug found along the way, all in
drivers/platform/x86/panasonic-laptop.c.
Patch 1 fixes the bezel Rotation Lock button, which turns out to
signal via raw i8042 scancodes that alias the real Left-GUI key,
rather than via ACPI notify like the driver's other hotkeys.
Patch 2 adds support for the bezel A1/A2 buttons, which are wired to a
second ACPI device (MAT003C/TBTN) that nothing currently binds to.
Found by disassembling the platform's ACPI tables, since these buttons
produced no signal through any of evdev, ACPI notify, WMI, or ACPI GPE
interrupt counters.
Patch 3 fixes a latent off-by-one heap overflow in the existing HKEY
SINF-parsing code, independently triggered by this hardware's exact
SQTY/SINF sizes and caught via UBSan while testing patch 2. It's
unrelated to the CF-33-specific work but is included here since it was
found in the course of it and touches the same file.
Changes in v2:
- Patch 1: fix a bug in panasonic_i8042_filter() found after this
series was first posted. The filter's scancode switch masked off
the top bit (data & 0x7f) so a key's make and break codes share a
case label; that's correct for the volume keys (both make and
break are meant to be fully swallowed there) but it also made the
genuine Left-GUI/Meta break code (0xdb) collide with its make code
(0x5b), since 0xdb & 0x7f == 0x5b too. The filter misidentified
every real release of the physical Left-GUI/Meta key as a possible
start of the rotate-lock sequence, silently dropped it, and left
the kernel's input core believing the key was still held -
reproducible on hardware as GNOME/Mutter treating every subsequent
keystroke as a stuck-Super-modified shortcut. Fixed by requiring an
exact match against the make code before entering the wait state;
any other byte (i.e. the real break code) now falls through to the
default path and is replayed untouched, as it always should have
been.
All three verified on real CF-33 Mk1 hardware, including across a
reboot with the combined patch set installed via DKMS, and v2's fix
specifically verified via raw i8042 event capture on
/dev/input/event3 across five separate Windows-key taps interleaved
with normal typing, confirming clean make/break pairs and no more
stuck-modifier behavior.
Hilgad Montelo (3):
platform/x86: panasonic-laptop: Handle CF-33 rotation-lock button
platform/x86: panasonic-laptop: Add driver for CF-33 A1/A2 buttons
(TBTN)
platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[]
drivers/platform/x86/panasonic-laptop.c | 264 +++++++++++++++++++++++-
1 file changed, 261 insertions(+), 3 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/3] platform/x86: panasonic-laptop: Handle CF-33 rotation-lock button
2026-08-13 22:17 [PATCH v2 0/3] platform/x86: panasonic-laptop: CF-33 hotkey fixes Hilgad Montelo
@ 2026-08-13 22:17 ` Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 2/3] platform/x86: panasonic-laptop: Add driver for CF-33 A1/A2 buttons (TBTN) Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 3/3] platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[] Hilgad Montelo
2 siblings, 0 replies; 5+ messages in thread
From: Hilgad Montelo @ 2026-08-13 22:17 UTC (permalink / raw)
To: kenneth.t.chan, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Hilgad Montelo
On the Panasonic Toughbook CF-33 the bezel "Rotation Lock" button does
not signal via ACPI notify like the other hotkeys. Instead the
embedded controller injects raw i8042/PS2 scancodes that alias the
real Left-GUI/Meta key:
press: e0 5b 65
release: e5 e0 db
e0 5b / e0 db are the standard AT scancode for the physical Left-GUI
key. The bare 65 / e5 bytes interleaved with them are not valid codes
for any real key and only ever appear as part of this vendor signal
(confirmed by tracing raw bytes crossing the i8042 port on the actual
hardware). Left unfiltered, this shows up as a spurious KEY_LEFTMETA +
KEY_F14 combo, which does nothing useful and can trigger desktop
environment Meta-key bindings on every press.
This driver already installs an i8042 filter (panasonic_i8042_filter)
to de-duplicate volume key events. Extend it with a small state
machine that recognizes and swallows the exact e0 5b 65 ... e5 e0 db
sequence, and emits a single debounced KEY_ROTATE_LOCK_TOGGLE event
instead. The 600ms debounce is needed because the EC repeats the
make/break unit every ~280-400ms for as long as the button is
physically held, which would otherwise fire multiple toggles for one
tap. If a byte sequence starts the same way but doesn't complete the
pattern, the buffered e0 5b bytes are replayed unfiltered, so a
genuine Left-GUI keypress is unaffected.
Verified on a CF-33 Mk1: each button press now produces exactly one
KEY_ROTATE_LOCK_TOGGLE pair, the plain keyboard device stays silent
during presses (no more stray LEFTMETA/F14), and GNOME's auto-rotate
lock correctly engages/disengages. Brightness and volume hotkeys are
unaffected.
Signed-off-by: Hilgad Montelo <hilgad.montelo@gmail.com>
---
drivers/platform/x86/panasonic-laptop.c | 85 ++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 719add7..0c0e4a6 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -127,6 +127,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -256,15 +257,81 @@ struct pcc_acpi {
/*
* On some Panasonic models the volume up / down / mute keys send duplicate
* keypress events over the PS/2 kbd interface, filter these out.
+ *
+ * On the CF-33 the bezel "Rotation Lock" button also signals over this same
+ * interface, instead of via an ACPI notify like the other hotkeys. It does
+ * so by injecting scancodes that alias the real Left-GUI/Meta key
+ * (e0 5b make / e0 db break), interleaved with a bare byte (0x65 / 0xe5)
+ * that no physical key on this keyboard uses. Left unfiltered this shows up
+ * as a bogus LEFTMETA+F14 combo. We recognize and swallow the whole
+ * sequence and emit a single debounced KEY_ROTATE_LOCK_TOGGLE instead; any
+ * byte that breaks the expected pattern is treated as a genuine key and
+ * replayed unfiltered.
*/
+enum rot_lock_state {
+ ROT_IDLE,
+ ROT_WAIT_65,
+ ROT_WAIT_E5,
+ ROT_WAIT_E0B,
+ ROT_WAIT_DB,
+};
+
static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
struct serio *port, void *context)
{
+ struct pcc_acpi *pcc = context;
static bool extended;
+ static enum rot_lock_state rstate = ROT_IDLE;
+ static unsigned long last_toggle;
+ const unsigned long debounce = msecs_to_jiffies(600);
if (str & I8042_STR_AUXDATA)
return false;
+ switch (rstate) {
+ case ROT_WAIT_65:
+ if (data == 0x65) {
+ rstate = ROT_WAIT_E5;
+ if (pcc && pcc->input_dev &&
+ time_after(jiffies, last_toggle + debounce)) {
+ input_report_key(pcc->input_dev,
+ KEY_ROTATE_LOCK_TOGGLE, 1);
+ input_sync(pcc->input_dev);
+ input_report_key(pcc->input_dev,
+ KEY_ROTATE_LOCK_TOGGLE, 0);
+ input_sync(pcc->input_dev);
+ last_toggle = jiffies;
+ }
+ return true;
+ }
+ /* Not our sequence: replay the buffered genuine Left-GUI make. */
+ rstate = ROT_IDLE;
+ serio_interrupt(port, 0xe0, 0);
+ serio_interrupt(port, 0x5b, 0);
+ break;
+ case ROT_WAIT_E5:
+ if (data == 0xe5) {
+ rstate = ROT_WAIT_E0B;
+ return true;
+ }
+ rstate = ROT_IDLE;
+ break;
+ case ROT_WAIT_E0B:
+ if (data == 0xe0) {
+ rstate = ROT_WAIT_DB;
+ return true;
+ }
+ rstate = ROT_IDLE;
+ break;
+ case ROT_WAIT_DB:
+ rstate = ROT_IDLE;
+ if (data == 0xdb)
+ return true;
+ break;
+ case ROT_IDLE:
+ break;
+ }
+
if (data == 0xe0) {
extended = true;
return true;
@@ -276,6 +343,19 @@ static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
return true;
+ case 0x5b: /* e0 5b, possible start of rotate-lock sequence */
+ if (data == 0x5b) {
+ rstate = ROT_WAIT_65;
+ return true;
+ }
+ /*
+ * data == 0xdb: genuine Left-GUI/Meta break code.
+ * The rotate-lock sequence only ever begins with
+ * the make code, so this is a real key release,
+ * not our sequence; the code below replays it
+ * untouched.
+ */
+ fallthrough;
default:
/*
* Report the previously filtered e0 before continuing
@@ -944,6 +1024,9 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc)
goto err_free_dev;
}
+ /* Synthesized by panasonic_i8042_filter(), not part of the ACPI keymap. */
+ input_set_capability(input_dev, EV_KEY, KEY_ROTATE_LOCK_TOGGLE);
+
error = input_register_device(input_dev);
if (error) {
pr_err("Unable to register input device\n");
@@ -1090,7 +1173,7 @@ static int acpi_pcc_hotkey_probe(struct platform_device *pdev)
pcc->platform = NULL;
}
- i8042_install_filter(panasonic_i8042_filter, NULL);
+ i8042_install_filter(panasonic_i8042_filter, pcc);
return 0;
out_platform:
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] platform/x86: panasonic-laptop: Add driver for CF-33 A1/A2 buttons (TBTN)
2026-08-13 22:17 [PATCH v2 0/3] platform/x86: panasonic-laptop: CF-33 hotkey fixes Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 1/3] platform/x86: panasonic-laptop: Handle CF-33 rotation-lock button Hilgad Montelo
@ 2026-08-13 22:17 ` Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 3/3] platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[] Hilgad Montelo
2 siblings, 0 replies; 5+ messages in thread
From: Hilgad Montelo @ 2026-08-13 22:17 UTC (permalink / raw)
To: kenneth.t.chan, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Hilgad Montelo
On the Panasonic Toughbook CF-33 the bezel A1/A2 buttons are wired to
a separate ACPI device, MAT003C (ACPI path \_SB.TBTN), rather than the
main Hotkey device (MAT0019/HKEY) this driver already talks to.
MAT003C was present in the ACPI namespace but had no driver bound to
it, so A1/A2 produced no signal through any channel: no evdev events,
no ACPI notify (nothing logged), no WMI device, and no correlated ACPI
GPE interrupt activity.
Found by dumping and disassembling the platform's ACPI tables
(acpidump -b + iasl -d) and searching for EC _Qxx query handlers that
push scancodes into a hotkey queue. TBTN turned out to implement its
own HINF/HIND/SQTY/SINF method quartet, structurally a clone of HKEY's:
_Qxx handlers call TBTN.HIND(code) then Notify(TBTN, 0x80); HINF()
dequeues one scancode from a small EC-side FIFO. Confirmed scancodes:
0x38/0x39 = A1 press/release, 0x42/0x43 = A2 press/release. Unlike
HKEY, TBTN's codes never set the high bit -- press and release are
distinct scancodes rather than one code plus an up/down flag.
TBTN.SQTY returns 1 (it has no brightness/battery data, just a
button-availability flag), so it cannot be probed via the existing
acpi_pcc_hotkey_probe(), which requires num_sifr > SINF_DC_CUR_BRIGHT
(assumes every device has the full brightness/eco-mode/battery SINF
block). Add a second, minimal platform_driver bound to MAT003C
instead, with its own small input device reporting KEY_PROG2 (A1) and
KEY_PROG3 (A2) -- both already carry standard XKB keysym mappings
(XF86Launch2/XF86Launch3), so no udev/hwdb work is needed for desktop
environments to bind them to actions.
Verified on a CF-33 Mk1: evtest shows clean KEY_PROG2/KEY_PROG3
press/release pairs with real physical timing; confirmed bindable as
GNOME custom shortcuts and launching applications correctly.
Signed-off-by: Hilgad Montelo <hilgad.montelo@gmail.com>
---
drivers/platform/x86/panasonic-laptop.c | 168 +++++++++++++++++++++++-
1 file changed, 167 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 0c0e4a6..93e6511 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -197,6 +197,42 @@ static const struct acpi_device_id pcc_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
+/*
+ * On the CF-33 the bezel A1/A2 buttons are wired to a separate ACPI device
+ * (MAT003C, ACPI path \_SB.TBTN) rather than the main Hotkey (MAT0019/HKEY)
+ * device the rest of this driver talks to. TBTN implements its own
+ * HINF/HIND/SQTY/SINF method quartet, structurally a clone of HKEY's, but
+ * SQTY only reports a single SIFR element (a button-availability flag) --
+ * it has none of HKEY's brightness/battery/backlight state, so it can't be
+ * probed via acpi_pcc_hotkey_probe(), which requires the full SINF block.
+ * Register a second, minimal platform_driver for it instead.
+ */
+#define METHOD_TBTN_QUERY "HINF"
+#define TBTN_NOTIFY 0x80
+
+static const struct acpi_device_id tbtn_device_ids[] = {
+ { "MAT003C", 0},
+ { "", 0},
+};
+MODULE_DEVICE_TABLE(acpi, tbtn_device_ids);
+
+struct tbtn_acpi {
+ acpi_handle handle;
+ struct input_dev *input_dev;
+};
+
+static int tbtn_probe(struct platform_device *pdev);
+static void tbtn_remove(struct platform_device *pdev);
+
+static struct platform_driver acpi_tbtn_driver = {
+ .probe = tbtn_probe,
+ .remove = tbtn_remove,
+ .driver = {
+ .name = "Panasonic Tablet Buttons",
+ .acpi_match_table = tbtn_device_ids,
+ },
+};
+
#ifdef CONFIG_PM_SLEEP
static int acpi_pcc_hotkey_resume(struct device *dev);
#endif
@@ -961,6 +997,112 @@ static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
}
}
+/*
+ * TBTN's HINF dequeues one raw scancode from a small EC-side FIFO (0 if
+ * empty) and re-Notify()s itself if more than one entry was pending, so a
+ * single evaluate-and-report per notification is sufficient here -- unlike
+ * HKEY, TBTN's codes never set the high bit, since press and release are
+ * distinct scancodes rather than one code plus an up/down flag.
+ */
+static void tbtn_report_key(struct tbtn_acpi *tbtn, unsigned int code)
+{
+ static const struct {
+ unsigned int code;
+ unsigned int keycode;
+ bool down;
+ } keymap[] = {
+ { 0x38, KEY_PROG2, true }, /* A1 press */
+ { 0x39, KEY_PROG2, false }, /* A1 release */
+ { 0x42, KEY_PROG3, true }, /* A2 press */
+ { 0x43, KEY_PROG3, false }, /* A2 release */
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(keymap); i++) {
+ if (keymap[i].code != code)
+ continue;
+ input_report_key(tbtn->input_dev, keymap[i].keycode, keymap[i].down);
+ input_sync(tbtn->input_dev);
+ return;
+ }
+
+ pr_info("Unknown TBTN hotkey event: 0x%02x\n", code);
+}
+
+static void tbtn_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct tbtn_acpi *tbtn = data;
+ unsigned long long result;
+ acpi_status status;
+
+ if (event != TBTN_NOTIFY)
+ return;
+
+ status = acpi_evaluate_integer(tbtn->handle, METHOD_TBTN_QUERY,
+ NULL, &result);
+ if (ACPI_FAILURE(status)) {
+ pr_err("TBTN: error getting hotkey status\n");
+ return;
+ }
+
+ if (result)
+ tbtn_report_key(tbtn, result);
+}
+
+static int tbtn_probe(struct platform_device *pdev)
+{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+ struct tbtn_acpi *tbtn;
+ struct input_dev *input_dev;
+ int error;
+
+ if (!device)
+ return -ENODEV;
+
+ tbtn = devm_kzalloc(&pdev->dev, sizeof(*tbtn), GFP_KERNEL);
+ if (!tbtn)
+ return -ENOMEM;
+
+ tbtn->handle = device->handle;
+ device->driver_data = tbtn;
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "Panasonic Tablet Buttons";
+ input_dev->phys = "panasonic/tbtn0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0002;
+ input_dev->id.version = 0x0100;
+ input_set_capability(input_dev, EV_KEY, KEY_PROG2);
+ input_set_capability(input_dev, EV_KEY, KEY_PROG3);
+
+ error = input_register_device(input_dev);
+ if (error) {
+ pr_err("TBTN: unable to register input device\n");
+ return error;
+ }
+
+ tbtn->input_dev = input_dev;
+
+ error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ tbtn_notify, tbtn);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static void tbtn_remove(struct platform_device *pdev)
+{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, tbtn_notify);
+ device->driver_data = NULL;
+}
+
static void pcc_optd_notify(acpi_handle handle, u32 event, void *data)
{
if (event != ACPI_NOTIFY_EJECT_REQUEST)
@@ -1221,4 +1363,28 @@ static void acpi_pcc_hotkey_remove(struct platform_device *pdev)
kfree(pcc);
}
-module_platform_driver(acpi_pcc_driver);
+static int __init panasonic_module_init(void)
+{
+ int error;
+
+ error = platform_driver_register(&acpi_pcc_driver);
+ if (error)
+ return error;
+
+ error = platform_driver_register(&acpi_tbtn_driver);
+ if (error) {
+ platform_driver_unregister(&acpi_pcc_driver);
+ return error;
+ }
+
+ return 0;
+}
+
+static void __exit panasonic_module_exit(void)
+{
+ platform_driver_unregister(&acpi_tbtn_driver);
+ platform_driver_unregister(&acpi_pcc_driver);
+}
+
+module_init(panasonic_module_init);
+module_exit(panasonic_module_exit);
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[]
2026-08-13 22:17 [PATCH v2 0/3] platform/x86: panasonic-laptop: CF-33 hotkey fixes Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 1/3] platform/x86: panasonic-laptop: Handle CF-33 rotation-lock button Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 2/3] platform/x86: panasonic-laptop: Add driver for CF-33 A1/A2 buttons (TBTN) Hilgad Montelo
@ 2026-08-13 22:17 ` Hilgad Montelo
2026-08-18 11:09 ` Ilpo Järvinen
2 siblings, 1 reply; 5+ messages in thread
From: Hilgad Montelo @ 2026-08-13 22:17 UTC (permalink / raw)
To: kenneth.t.chan, hansg, ilpo.jarvinen
Cc: platform-driver-x86, linux-kernel, Hilgad Montelo
acpi_pcc_retrieve_biosdata() rejects SINF packages only when
pcc->num_sifr is strictly less than hkey->package.count, then
unconditionally writes a trailing sentinel at
pcc->sinf[hkey->package.count]. But pcc->sinf[] is allocated with
exactly pcc->num_sifr elements (valid indices 0..num_sifr-1), so that
write needs num_sifr strictly greater than package.count to stay in
bounds -- num_sifr == package.count passes the existing check but
still overflows by one element.
This is exactly the case probe()'s existing num_sifr++ workaround
("Some DSDT-s have an off-by-one bug where the SINF package count is
one higher than the SQTY reported value") is written to accommodate:
when a DSDT's SINF package count equals SQTY+1, the workaround makes
num_sifr equal to package.count, which is precisely the boundary that
overflows here. Found via UBSan (array-index-out-of-bounds) on
hardware where HKEY.SQTY returns 37 and HKEY.SINF()'s package has 38
elements: num_sifr becomes 38 after the += 1 workaround, the loop
correctly fills indices 0..37, and the sentinel write then targets
index 38, one past the end -- a silent 4-byte heap overflow on kernels
without CONFIG_UBSAN.
Tightening the rejection check to num_sifr <= package.count would
avoid the overflow but breaks probe() entirely on exactly this
hardware, since num_sifr == package.count is the case the off-by-one
workaround exists to support. Nothing else in the driver reads this
sentinel value back, so simply skip the write when there is no room
for it instead.
Signed-off-by: Hilgad Montelo <hilgad.montelo@gmail.com>
---
drivers/platform/x86/panasonic-laptop.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 93e6511..9511440 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -476,7 +476,16 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
} else
pr_err("Invalid HKEY.SINF data\n");
}
- pcc->sinf[hkey->package.count] = -1;
+ /*
+ * pcc->sinf[] has pcc->num_sifr elements (valid indices
+ * 0..num_sifr-1). On DSDTs where SINF's package count equals
+ * num_sifr exactly -- the off-by-one case probe()'s num_sifr++
+ * already allocates a spare element for -- there is no room left
+ * for this trailing sentinel; nothing reads it back, so just skip
+ * the write rather than running one element past the flex array.
+ */
+ if (hkey->package.count < pcc->num_sifr)
+ pcc->sinf[hkey->package.count] = -1;
end:
kfree(buffer.pointer);
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 3/3] platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[]
2026-08-13 22:17 ` [PATCH v2 3/3] platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[] Hilgad Montelo
@ 2026-08-18 11:09 ` Ilpo Järvinen
0 siblings, 0 replies; 5+ messages in thread
From: Ilpo Järvinen @ 2026-08-18 11:09 UTC (permalink / raw)
To: Hilgad Montelo, Rosen Penev
Cc: kenneth.t.chan, Hans de Goede, platform-driver-x86, LKML
On Thu, 13 Aug 2026, Hilgad Montelo wrote:
> acpi_pcc_retrieve_biosdata() rejects SINF packages only when
> pcc->num_sifr is strictly less than hkey->package.count, then
> unconditionally writes a trailing sentinel at
> pcc->sinf[hkey->package.count]. But pcc->sinf[] is allocated with
> exactly pcc->num_sifr elements (valid indices 0..num_sifr-1), so that
> write needs num_sifr strictly greater than package.count to stay in
> bounds -- num_sifr == package.count passes the existing check but
> still overflows by one element.
>
> This is exactly the case probe()'s existing num_sifr++ workaround
> ("Some DSDT-s have an off-by-one bug where the SINF package count is
> one higher than the SQTY reported value") is written to accommodate:
> when a DSDT's SINF package count equals SQTY+1, the workaround makes
> num_sifr equal to package.count, which is precisely the boundary that
> overflows here. Found via UBSan (array-index-out-of-bounds) on
> hardware where HKEY.SQTY returns 37 and HKEY.SINF()'s package has 38
> elements: num_sifr becomes 38 after the += 1 workaround, the loop
> correctly fills indices 0..37, and the sentinel write then targets
> index 38, one past the end -- a silent 4-byte heap overflow on kernels
> without CONFIG_UBSAN.
>
> Tightening the rejection check to num_sifr <= package.count would
> avoid the overflow but breaks probe() entirely on exactly this
> hardware, since num_sifr == package.count is the case the off-by-one
> workaround exists to support. Nothing else in the driver reads this
> sentinel value back, so simply skip the write when there is no room
> for it instead.
>
> Signed-off-by: Hilgad Montelo <hilgad.montelo@gmail.com>
> ---
> drivers/platform/x86/panasonic-laptop.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
> index 93e6511..9511440 100644
> --- a/drivers/platform/x86/panasonic-laptop.c
> +++ b/drivers/platform/x86/panasonic-laptop.c
> @@ -476,7 +476,16 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
> } else
> pr_err("Invalid HKEY.SINF data\n");
> }
> - pcc->sinf[hkey->package.count] = -1;
> + /*
> + * pcc->sinf[] has pcc->num_sifr elements (valid indices
> + * 0..num_sifr-1). On DSDTs where SINF's package count equals
> + * num_sifr exactly -- the off-by-one case probe()'s num_sifr++
> + * already allocates a spare element for -- there is no room left
> + * for this trailing sentinel; nothing reads it back, so just skip
> + * the write rather than running one element past the flex array.
> + */
> + if (hkey->package.count < pcc->num_sifr)
> + pcc->sinf[hkey->package.count] = -1;
Hi,
Thanks for the patch. I've applied this fix patch 3 (only) into the
review-ilpo-next to get it in within this cycle.
I did add:
Fixes: a3d0dbd18ce9 ("platform/x86: panasonic-laptop: simplify allocation of sinf")
...because I think it removed one extra entry (there were initially 2
extra entries and we didn't realize the second one was probably for this
particular assignment) allowing write past the array.
I'll consider the other two patches of this series later.
--
i.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-18 11:10 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-13 22:17 [PATCH v2 0/3] platform/x86: panasonic-laptop: CF-33 hotkey fixes Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 1/3] platform/x86: panasonic-laptop: Handle CF-33 rotation-lock button Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 2/3] platform/x86: panasonic-laptop: Add driver for CF-33 A1/A2 buttons (TBTN) Hilgad Montelo
2026-08-13 22:17 ` [PATCH v2 3/3] platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[] Hilgad Montelo
2026-08-18 11:09 ` Ilpo Järvinen
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.