mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx+linux-hardening@kernel.org>
To: Shihuang Liu <shlomojune6@gmail.com>
Cc: linux-input@vger.kernel.org, linux-hardening@vger.kernel.org,
	 Marcus Folkesson <marcus.folkesson@gmail.com>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	 Ville Syrjala <syrjala@sci.fi>,
	Henk Vergonet <Henk.Vergonet@gmail.com>,
	 Henrik Rydberg <rydberg@bitmath.org>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/5] Input: misc - replace strlcat() with strscpy()
Date: Mon, 19 Oct 2026 09:48:26 +0200	[thread overview]
Message-ID: <atXHuHxCqqkIuV2w@debian> (raw)
In-Reply-To: <20261016170411.51025-3-shlomojune6@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9387 bytes --]

Hi Shihuang,

> Date: 2026-10-17 01:04:08+0800
> From: Shihuang Liu <shlomojune6@gmail.com>
>
> The ati_remote2, cm109, ims-pcu, keyspan_remote, powermate and
> yealink drivers build the physical path by appending a constant
> "/input0" suffix with strlcat() after usb_make_path().
> 
> In preparation for removing the deprecated strlcat() API[1],
> replace it with strnlen() followed by strscpy() into the remainder
> of the buffer, as commit 34b228b739f5 ("HID: usbhid: replace
> strlcat with better alternatives") did for the usbhid drivers.
> 
> Link: https://github.com/KSPP/linux/issues/370 [1]
> Signed-off-by: Shihuang Liu <shlomojune6@gmail.com>
> ---
>
>  drivers/input/misc/ati_remote2.c    | 4 +++-
>  drivers/input/misc/cm109.c          | 4 +++-
>  drivers/input/misc/ims-pcu.c        | 8 ++++++--
>  drivers/input/misc/keyspan_remote.c | 4 +++-
>  drivers/input/misc/powermate.c      | 4 +++-
>  drivers/input/misc/yealink.c        | 4 +++-
>  6 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
> index 8db2dca84975c..929163f52177e 100644
> --- a/drivers/input/misc/ati_remote2.c
> +++ b/drivers/input/misc/ati_remote2.c
> @@ -767,6 +767,7 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
>  	struct usb_device *udev = interface_to_usbdev(interface);
>  	struct usb_host_interface *alt = interface->cur_altsetting;
>  	struct ati_remote2 *ar2;
> +	size_t len;
>  	int r;
>  
>  	if (alt->desc.bInterfaceNumber)
> @@ -823,7 +824,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
>  		goto fail3;
>  
>  	usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
> -	strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
> +	len = strnlen(ar2->phys, sizeof(ar2->phys));

Why strnlen(3)?  ar2->phys should be a string, right?  If it is not,
then we'd already have a buffer overread in strlcat(3), and then the
commit should be reporting a bug fix.  This should use strlen(3)
instead.

> +	strscpy(ar2->phys + len, "/input0", sizeof(ar2->phys) - len);

NAKing this.  This is precisely what strlcat(3)'s documentation in
OpenBSD says you shouldn't do:

	Since it is known how many characters were copied the first
	time, things can be sped up a bit by using a copy instead of an
	append:

		char *dir, *file, pname[PATH_MAX];
		size_t n;

		...

		n = strlcpy(pname, dir, sizeof(pname));
		if (n >= sizeof(pname))
			goto toolong;
		if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
			goto toolong;

	However, one may question the validity of such optimizations, as
	they defeat the whole purpose of strlcpy() and strlcat().  As a
	matter of fact, the first version of this manual page got it
	wrong.

<https://man.openbsd.org/strlcpy>

The right approach is to have a function that does the right thing.
There are two viable alternatives:

-  Write strscat().  It would take the strlen() internally, and so it
   would be unnecessarily inefficient.  Prefer the next one.

-  Write stpecpy().  It returns a pointer, which allows chaining easily.

Here's a viable implementation of stpecpy():

	char *
	stpecpy(char *dst, const char end[0], const char *restrict src)
	{
		ssize_t  dlen;

		if (dst == NULL)
			return NULL;

		dlen = strscpy(dst, src, end - dst);
		if (dlen < 0)
			return NULL;

		return dst + dlen;
	}

This would need to be accompanied by a seprintf() too, which would be
used by usb_make_path() to produce a pointer suitable for chaining.
I've been working on adding those.

If you want to keep it easy, I'd do strscat().  We can modify it later
to be more efficient.  After all, we already have the inefficiency of
calling strlcat(3) now.


Have a lovely day!
Alex

>  	strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
>  
> diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
> index 353d3c1d347d5..d3aee3c498702 100644
> --- a/drivers/input/misc/cm109.c
> +++ b/drivers/input/misc/cm109.c
> @@ -685,6 +685,7 @@ static int cm109_usb_probe(struct usb_interface *intf,
>  	struct input_dev *input_dev = NULL;
>  	int ret, pipe, i;
>  	int error = -ENOMEM;
> +	size_t len;
>  
>  	interface = intf->cur_altsetting;
>  
> @@ -766,7 +767,8 @@ static int cm109_usb_probe(struct usb_interface *intf,
>  
>  	/* find out the physical bus location */
>  	usb_make_path(udev, dev->phys, sizeof(dev->phys));
> -	strlcat(dev->phys, "/input0", sizeof(dev->phys));
> +	len = strnlen(dev->phys, sizeof(dev->phys));
> +	strscpy(dev->phys + len, "/input0", sizeof(dev->phys) - len);
>  
>  	/* register settings for the input device */
>  	input_dev->name = nfo->name;
> diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
> index b1a0edcc49b4e..697813fb11da8 100644
> --- a/drivers/input/misc/ims-pcu.c
> +++ b/drivers/input/misc/ims-pcu.c
> @@ -205,6 +205,7 @@ static int ims_pcu_setup_buttons(struct ims_pcu *pcu,
>  	struct input_dev *input;
>  	int i;
>  	int error;
> +	size_t len;
>  
>  	input = input_allocate_device();
>  	if (!input) {
> @@ -216,7 +217,8 @@ static int ims_pcu_setup_buttons(struct ims_pcu *pcu,
>  		 "IMS PCU#%d Button Interface", pcu->device_no);
>  
>  	usb_make_path(pcu->udev, buttons->phys, sizeof(buttons->phys));
> -	strlcat(buttons->phys, "/input0", sizeof(buttons->phys));
> +	len = strnlen(buttons->phys, sizeof(buttons->phys));
> +	strscpy(buttons->phys + len, "/input0", sizeof(buttons->phys) - len);
>  
>  	memcpy(buttons->keymap, keymap, sizeof(*keymap) * keymap_len);
>  
> @@ -286,6 +288,7 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
>  	struct ims_pcu_gamepad *gamepad;
>  	struct input_dev *input;
>  	int error;
> +	size_t len;
>  
>  	gamepad = kzalloc_obj(*gamepad);
>  	input = input_allocate_device();
> @@ -302,7 +305,8 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
>  		 "IMS PCU#%d Gamepad Interface", pcu->device_no);
>  
>  	usb_make_path(pcu->udev, gamepad->phys, sizeof(gamepad->phys));
> -	strlcat(gamepad->phys, "/input1", sizeof(gamepad->phys));
> +	len = strnlen(gamepad->phys, sizeof(gamepad->phys));
> +	strscpy(gamepad->phys + len, "/input1", sizeof(gamepad->phys) - len);
>  
>  	input->name = gamepad->name;
>  	input->phys = gamepad->phys;
> diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
> index 70cd6586459ef..f0f31f2823d57 100644
> --- a/drivers/input/misc/keyspan_remote.c
> +++ b/drivers/input/misc/keyspan_remote.c
> @@ -430,6 +430,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
>  	struct usb_keyspan *remote;
>  	struct input_dev *input_dev;
>  	int i, error;
> +	size_t len;
>  
>  	error = usb_find_int_in_endpoint(interface->cur_altsetting, &endpoint);
>  	if (error)
> @@ -482,7 +483,8 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
>  			 le16_to_cpu(udev->descriptor.idProduct));
>  
>  	usb_make_path(udev, remote->phys, sizeof(remote->phys));
> -	strlcat(remote->phys, "/input0", sizeof(remote->phys));
> +	len = strnlen(remote->phys, sizeof(remote->phys));
> +	strscpy(remote->phys + len, "/input0", sizeof(remote->phys) - len);
>  	memcpy(remote->keymap, keyspan_key_table, sizeof(remote->keymap));
>  
>  	input_dev->name = remote->name;
> diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
> index 754379d2625cf..dbf9f06f3059e 100644
> --- a/drivers/input/misc/powermate.c
> +++ b/drivers/input/misc/powermate.c
> @@ -299,6 +299,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
>  	struct input_dev *input_dev;
>  	int pipe, maxp;
>  	int error = -ENOMEM;
> +	size_t len;
>  
>  	interface = intf->cur_altsetting;
>  	if (interface->desc.bNumEndpoints < 1)
> @@ -334,7 +335,8 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
>  	pm->input = input_dev;
>  
>  	usb_make_path(udev, pm->phys, sizeof(pm->phys));
> -	strlcat(pm->phys, "/input0", sizeof(pm->phys));
> +	len = strnlen(pm->phys, sizeof(pm->phys));
> +	strscpy(pm->phys + len, "/input0", sizeof(pm->phys) - len);
>  
>  	spin_lock_init(&pm->lock);
>  
> diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
> index 560f895a00cda..1a3bebc8c3513 100644
> --- a/drivers/input/misc/yealink.c
> +++ b/drivers/input/misc/yealink.c
> @@ -812,6 +812,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
>  	struct yealink_dev *yld;
>  	struct input_dev *input_dev;
>  	int ret, pipe, i;
> +	size_t len;
>  
>  	interface = intf->cur_altsetting;
>  
> @@ -891,7 +892,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
>  
>  	/* find out the physical bus location */
>  	usb_make_path(udev, yld->phys, sizeof(yld->phys));
> -	strlcat(yld->phys,  "/input0", sizeof(yld->phys));
> +	len = strnlen(yld->phys, sizeof(yld->phys));
> +	strscpy(yld->phys + len, "/input0", sizeof(yld->phys) - len);
>  
>  	/* register settings for the input device */
>  	input_dev->name = nfo->name;
> -- 
> 2.43.0
> 
> 

-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-10-19  7:48 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-16 17:04 [PATCH 0/5] Input: replace strlcat() with strscpy() in USB input drivers Shihuang Liu
2026-10-16 17:04 ` [PATCH 1/5] Input: joystick - replace strlcat() with strscpy() Shihuang Liu
2026-10-16 19:17   ` Dmitry Torokhov
2026-10-17  8:19     ` Greg KH
2026-10-18 16:02       ` Shihuang Liu
2026-10-19  7:51       ` Alejandro Colomar
2026-10-19  8:44         ` Greg KH
2026-10-19 16:40           ` Alejandro Colomar
2026-10-16 17:04 ` [PATCH 2/5] Input: misc " Shihuang Liu
2026-10-19  7:48   ` Alejandro Colomar [this message]
2026-10-19 17:08     ` Shihuang Liu
2026-10-16 17:04 ` [PATCH 3/5] Input: mouse " Shihuang Liu
2026-10-16 17:04 ` [PATCH 4/5] Input: tablet " Shihuang Liu
2026-10-17 22:11   ` David Laight
2026-10-16 17:04 ` [PATCH 5/5] Input: touchscreen " Shihuang Liu

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=atXHuHxCqqkIuV2w@debian \
    --to=alx+linux-hardening@kernel.org \
    --cc=Henk.Vergonet@gmail.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marcus.folkesson@gmail.com \
    --cc=rydberg@bitmath.org \
    --cc=shlomojune6@gmail.com \
    --cc=syrjala@sci.fi \
    /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

all inboxes | Powered by JetHome®