Linux Input/HID development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Denis Benato" <denis.benato@linux.dev>
Cc: dmitry.torokhov@gmail.com, linux-input@vger.kernel.org
Subject: Re: [PATCH 12/12] HID: asus: add support for btn remapping
Date: Thu, 13 Aug 2026 15:12:55 +0000	[thread overview]
Message-ID: <20260813151256.1BCCC1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260813144736.2477941-13-denis.benato@linux.dev>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Use-After-Free (UAF) in sysfs store functions due to manual lockless deallocation of button mappings.
- [High] Sysfs attributes are exposed before `gamepad_mode` initialization, causing a reproducible NULL pointer dereference.
- [Medium] Hardware update errors are silently swallowed for non-Ally X devices, and the software cache is permanently corrupted on failure.
- [Medium] Button remapping sysfs attributes are entirely inaccessible for devices lacking turbo support.
- [Medium] Time-of-Check to Time-of-Use (TOCTOU) race condition in `button_remap_store` bypasses validation.
--

--- Patch [12]: [PATCH 12/12] HID: asus: add support for btn remapping ---
commit d94c33db2e53bcd63e5e7044bbdf330bf4916ffa
Author: Denis Benato <denis.benato@linux.dev>
Subject: HID: asus: add support for btn remapping

Add support for buttons remapping: the ability to assign different
button events to each one of the physical button on the device.

[ ... ]

> diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
> index 359832395afec..5b744dba98d3e 100644
> --- a/drivers/hid/hid-asus.c
> +++ b/drivers/hid/hid-asus.c

[ ... ]

> @@ -2528,29 +3311,78 @@ static struct ally_btn_turbo_attr *ally_btn_turbo_attr_create(struct hid_device
> +static ssize_t button_remap_show(struct device *dev,
> +				 struct device_attribute *attr, char *buf)
> +{
> +	struct hid_device *hdev = to_hid_device(dev);
> +	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
> +	struct ally_handheld *ally = drvdata->rog_ally;
> +	struct button_remap_attr *btn_attr = to_button_remap_attr(attr);
> +	struct ally_config *cfg;
> +	enum ally_button_id button_id = btn_attr->button_id;
> +	enum btn_pair_index pair_idx;
> +	bool is_first;
> +	struct button_pair_map *pair;
> +	struct button_map *btn_map;
> +	int ret;
> +
> +	if (!ally || !ally->config)
> +		return -ENODEV;
> +
> +	cfg = ally->config;
> +
> +	ret = get_button_pair_info(button_id, &pair_idx, &is_first);
> +	if (ret < 0)
> +		return ret;
> +
> +	guard(mutex)(&cfg->config_mutex);
> +	pair = &((struct ally_button_mapping
> +			  *)(cfg->button_mappings))[cfg->gamepad_mode]
> +			.button_pairs[pair_idx - 1];
> +	btn_map = is_first ? &pair->first : &pair->second;
> +
> +	if (btn_attr->is_macro) {
> +		if (btn_map->macro->type == BTN_TYPE_NONE)

[Severity: High]
Could btn_map->macro be NULL here during device initialization?

When ally_create_button_attributes() registers the sysfs groups,
cfg->gamepad_mode is 0 by default. It is not set to 1 (Gamepad) until later
in the probe sequence.

If a user reads the remap or macro sysfs files before cfg->gamepad_mode is
updated, this will index cfg->button_mappings[0]. Since only indexes 1 and 2
are populated by ally_set_default_gamepad_mapping() and
ally_set_default_keyboard_mapping(), the pointers in index 0 remain
uninitialized. Dereferencing btn_map->macro->type would then cause a kernel
panic.

> +			return sysfs_emit(buf, "NONE\n");
> +		else
> +			return sysfs_emit(buf, "%s\n", btn_map->macro->name);
> +	} else {
> +		if (btn_map->remap->type == BTN_TYPE_NONE)
> +			return sysfs_emit(buf, "NONE\n");
> +		else
> +			return sysfs_emit(buf, "%s\n", btn_map->remap->name);
> +	}
> +}

[ ... ]

> +static ssize_t button_remap_store(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buf, size_t count)
> +{

[ ... ]

> +	ret = get_button_pair_info(button_id, &pair_idx, &is_first);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Validate that the remap target is allowed for this button/mode */
> +	if (!ally_remap_code_valid(button_id, cfg->gamepad_mode, code))
> +		return -EINVAL;
> +
> +	scoped_guard(mutex, &cfg->config_mutex) {
> +		/* Access the mapping for current gamepad mode */
> +		pair = &((struct ally_button_mapping
> +				  *)(cfg->button_mappings))[cfg->gamepad_mode]

[Severity: Medium]
Is there a Time-of-Check to Time-of-Use (TOCTOU) race condition here?

The validation function ally_remap_code_valid() reads cfg->gamepad_mode
locklessly. If a concurrent sysfs write to gamepad_mode_store() alters the
mode right before cfg->config_mutex is acquired, an invalid mapping could
bypass the checks and be written to the new mode's configuration.

> +				.button_pairs[pair_idx - 1];
> +		btn_map = is_first ? &pair->first : &pair->second;
> +
> +		if (btn_attr->is_macro)
> +			btn_map->macro = (struct btn_code_map *)code;
> +		else
> +			btn_map->remap = (struct btn_code_map *)code;
> +
> +		/* Update pair index */
> +		pair->pair_index = pair_idx;
> +
> +		/*
> +		 * Send mapping to device with the caveat that first generation
> +		 * devices require individual button pair updates.
> +		 */
> +		if (cfg->is_ally_x) {
> +			ret = ally_set_button_mapping(hdev, ally, pair);
> +			if (ret < 0)
> +				return ret;
> +		} else {
> +			mode_map = &((struct ally_button_mapping
> +					 *)(cfg->button_mappings))[cfg->gamepad_mode];
> +			for (i = 0; i < 9; i++) {
> +				mode_map->button_pairs[i].pair_index = i + 1;
> +				ret = ally_set_button_mapping(hdev, ally,
> +					&mode_map->button_pairs[i]);
> +				if (ret < 0)
> +					break;
> +			}
> +		}
> +	}
> +
> +	return count;
> +}

[Severity: Medium]
For non-Ally X devices, if ally_set_button_mapping() fails, this loop breaks
but then unconditionally returns count (success) instead of ret.

Also, earlier in this block, the software cache is updated:

    if (btn_attr->is_macro)
        btn_map->macro = (struct btn_code_map *)code;
    else
        btn_map->remap = (struct btn_code_map *)code;

If the hardware update fails, does this mean the software cache is now
permanently desynchronized from the actual hardware state?

[ ... ]

> @@ -2528,29 +3311,78 @@ static struct ally_btn_turbo_attr *ally_btn_turbo_attr_create(struct hid_device
>  static int ally_create_button_attributes(struct hid_device *hdev, struct ally_config *cfg)
>  {
>  	struct ally_btn_sysfs_entry *entries;
> +	struct ally_button_mapping *mappings;
>  	int i, ret;
>  
> -	if (!cfg->turbo_support)
> -		return 0;
> -

[Severity: Medium]
Even though this check is removed here, does the caller (ally_config_create())
still restrict the creation of these attributes based on cfg->turbo_support?

If ally_create_button_attributes() is only called when cfg->turbo_support is
true, then devices without turbo support will not have access to the button
remapping sysfs attributes either.

>  	entries = devm_kcalloc(&hdev->dev, ALLY_BTN_MAX, sizeof(*entries), GFP_KERNEL);

[ ... ]

> @@ -2598,8 +3439,16 @@ static void ally_remove_button_attributes(struct hid_device *hdev, struct ally_c
>  	for (i = 0; i < ALLY_BTN_MAX; i++) {
>  		sysfs_remove_group(&hdev->dev.kobj, &entries[i].group);
>  		kfree(entries[i].turbo_attr);
> +		kfree(entries[i].remap_attr);
> +		kfree(entries[i].macro_attr);
> +	}
> +
> +	if (cfg->button_mappings) {
> +		devm_kfree(&hdev->dev, cfg->button_mappings);
> +		cfg->button_mappings = NULL;
>  	}

[Severity: High]
Can this cause a use-after-free if sysfs files are accessed concurrently?

The teardown path frees cfg->button_mappings manually using devm_kfree()
without holding cfg->config_mutex.

If a user writes to gamepad_mode_store() or button_remap_store() right as
this is being freed, it could lead to memory corruption or a kernel panic,
as those functions dereference cfg->button_mappings.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260813144736.2477941-1-denis.benato@linux.dev?part=12

      reply	other threads:[~2026-08-13 15:12 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-13 14:47 [PATCH 00/12] HID: asus: add support for ROG Ally handhelds Denis Benato
2026-08-13 14:47 ` [PATCH 01/12] HID: asus: reinitialize the device after exiting a sleep state Denis Benato
2026-08-13 14:55   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 02/12] HID: asus: add support for ROG Ally handhelds Denis Benato
2026-08-13 15:00   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 03/12] HID: asus: add gamepad configuration Denis Benato
2026-08-13 14:59   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 04/12] HID: asus: add vibration strength configuration Denis Benato
2026-08-13 14:56   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 05/12] HID: asus: add joysticks inner and outer range configuration Denis Benato
2026-08-13 15:02   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 06/12] HID: asus: add triggers " Denis Benato
2026-08-13 14:58   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 07/12] HID: asus: add joysticks anti-deadzone configuration Denis Benato
2026-08-13 15:02   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 08/12] HID: asus: add support for response curve Denis Benato
2026-08-13 14:59   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 09/12] HID: asus: add support to force feedback Denis Benato
2026-08-13 15:10   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 10/12] HID: asus: add support for gamepad mode Denis Benato
2026-08-13 15:10   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 11/12] HID: asus: add support for turbo buttons Denis Benato
2026-08-13 15:10   ` sashiko-bot
2026-08-13 14:47 ` [PATCH 12/12] HID: asus: add support for btn remapping Denis Benato
2026-08-13 15:12   ` 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=20260813151256.1BCCC1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=denis.benato@linux.dev \
    --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