Linux Input/HID development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Evan Lawrence" <development@laserology.net>
Cc: dmitry.torokhov@gmail.com, linux-input@vger.kernel.org
Subject: Re: [PATCH v5] Input: synaptics - add pass-through mode for TrackPoint
Date: Mon, 10 Aug 2026 14:45:48 +0000	[thread overview]
Message-ID: <20260810144549.3FE281F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260810142440.9060-1-development@laserology.net>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Type confusion leading to out-of-bounds read/write due to relying solely on hardware port ID for driver validation.
- [High] Unsynchronized hardware commands interleave with pass-through byte stream, corrupting PS/2 communication.
- [High] Child port is leaked when parent driver probe fails, leading to a Use-After-Free crash.
- [Medium] Escape sequence aborts if the first byte is not ACKed, permanently locking the hardware in transparent mode.
--

--- Patch [1]: [PATCH v5] Input: synaptics - add pass-through mode for TrackPoint ---
commit 0baba0d9c35febab280e4dc02e618df2555881dc
Author: Evan Lawrence <development@laserology.net>
Subject: Input: synaptics - add pass-through mode for TrackPoint

This commit introduces a transparent pass-through mode for Synaptics touchpads
with a PS/2 guest port, allowing the guest (e.g., TrackPoint) to bypass the
touchpad's low poll rate by relaying raw byte streams directly. It adds a sysfs
attribute to toggle the mode at runtime.

Link: https://lore.kernel.org/all/6932d599-2625-0376-d9c6-58cbb8879ff4@gmail.com/

> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -636,12 +650,90 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
>  /*****************************************************************************
>   *	Synaptics pass-through PS/2 port support
>   ****************************************************************************/

[ ... ]

> +static int synaptics_exit_transparent_mode(struct psmouse *psmouse)
> +{
> +	struct synaptics_data *priv = psmouse->private;
> +	int error;
> +
> +	/* Send scaling 2:1, 1:1 to exit transparent mode */
> +	error = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE21);
> +	if (error)
> +		return error;
> +	error = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
> +	if (error)
> +		return error;

[Severity: Medium]
Will a failure on the first byte permanently lock the hardware in transparent
mode?

If the guest device is missing, resetting, or unresponsive, the first
PSMOUSE_CMD_SETSCALE21 byte may time out waiting for an ACK. When ps2_command()
returns an error, this function aborts without sending the crucial second byte
(PSMOUSE_CMD_SETSCALE11).

Since synaptics_pt_stop() clears the software transparent_mode flag even if the
hardware exit fails, doesn't this leave the driver fully desynchronized from
the hardware state, leaving the touchpad permanently unresponsive until a
reboot?

> +
> +	/* Re-enter the regular operating mode of the touchpad */
> +	error = synaptics_mode_cmd(psmouse, priv->mode & ~SYN_BIT_TRANSPARENT_MODE);
> +	if (error)
> +		return error;
> +
> +	priv->mode &= ~SYN_BIT_TRANSPARENT_MODE;
> +
> +	return 0;
> +}
> +
>  static int synaptics_pt_write(struct serio *serio, u8 c)
>  {
>  	struct psmouse *parent = psmouse_from_serio(serio->parent);
> +	struct synaptics_data *priv = parent->private;
>  	u8 rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
>  	int error;
>  
> +	guard(mutex)(&priv->pt_mutex);
> +
> +	if (READ_ONCE(priv->transparent_mode))
> +		return parent->ps2dev.serio->write(parent->ps2dev.serio, c);

[Severity: High]
Can this lead to corrupted PS/2 communication due to interleaved byte streams?

When transparent_mode is active, synaptics_pt_write() bypasses ps2_cmd_mutex to
forward raw guest bytes. However, other paths like synaptics_set_disable_gesture()
or synaptics_reconnect() can send PS/2 commands while holding ps2_cmd_mutex but
without checking transparent_mode or holding pt_mutex.

For example, if a user writes to the disable_gesture sysfs attribute while the
pass-through guest is active, won't the host command bytes and guest data
bytes interleave on the physical PS/2 bus?

> +
>  	error = ps2_sliced_command(&parent->ps2dev, c);
>  	if (error)
>  		return error;

[ ... ]

> @@ -681,6 +795,19 @@ static int synaptics_pt_open(struct serio *serio)
>  	guard(serio_pause_rx)(parent->ps2dev.serio);
>  	priv->pt_port_open = true;
>  
> +	/*
> +	 * In transparent mode every byte on the parent serio belongs to
> +	 * the pass-through guest and is not a BAT announcement.  Skip
> +	 * BAT detection on the child as well so that guest motion data
> +	 * that happens to look like 0xAA 0x00 does not trigger a
> +	 * spurious parent reconnect.
> +	 */
> +	if (READ_ONCE(priv->transparent_mode) &&
> +	    serio->id.type == SERIO_PS_PSTHRU) {
> +		struct psmouse *child = psmouse_from_serio(serio);
> +		WRITE_ONCE(child->pt_bypass_bat, true);
> +	}

[Severity: High]
Can this cause an out-of-bounds write if the child port is bound to a
different driver?

Checking serio->id.type == SERIO_PS_PSTHRU only verifies the hardware port
type, but does not guarantee the bound driver is psmouse. If a privileged user
unbinds the psmouse driver and binds serio_raw instead, won't psmouse_from_serio()
cast a smaller private data structure to struct psmouse, causing
WRITE_ONCE(child->pt_bypass_bat, true) to corrupt slab memory?

This type confusion also appears to happen in synaptics_pt_close(),
synaptics_pass_pt_packet(), synaptics_pt_activate(), and
synaptics_set_transparent_mode().

> +
>  	return 0;
>  }

[ ... ]

> @@ -1447,10 +1692,20 @@ static void synaptics_disconnect(struct psmouse *psmouse)
>  	 */
>  	psmouse_smbus_cleanup(psmouse);
>  
> +	if (READ_ONCE(priv->transparent_mode)) {
> +		guard(mutex)(&priv->pt_mutex);
> +		synaptics_exit_transparent_mode(psmouse);
> +		WRITE_ONCE(priv->transparent_mode, false);
> +		WRITE_ONCE(psmouse->pt_bypass_bat, false);
> +	}
> +
>  	if (!priv->absolute_mode &&
>  			SYN_ID_DISGEST_SUPPORTED(priv->info.identity))
>  		device_remove_file(&psmouse->ps2dev.serio->dev,
>  				   &psmouse_attr_disable_gesture.dattr);
> +	if (SYN_CAP_PASS_THROUGH(priv->info.capabilities))
> +		device_remove_file(&psmouse->ps2dev.serio->dev,
> +				   &psmouse_attr_transparent_mode.dattr);
>  
>  	synaptics_reset(psmouse);
>  	kfree(priv);

[Severity: High]
Does this leak the pass-through child port if probe fails, leading to a
use-after-free?

If psmouse_connect() fails late in probe (for example, during
input_register_device() due to memory exhaustion), it calls the driver's
disconnect callback, which frees the priv structure here.

Since there is no call to serio_unregister_port() for the child port, it
remains registered. When the system asynchronously finishes adding the leaked
port, any driver binding to it will call synaptics_pt_start(). Won't this
extract and dereference the freed parent driver data, causing a crash?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260810142440.9060-1-development@laserology.net?part=1

      reply	other threads:[~2026-08-10 14:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-10 14:25 [PATCH v5] Input: synaptics - add pass-through mode for TrackPoint Evan Lawrence
2026-08-10 14:45 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260810144549.3FE281F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=development@laserology.net \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox