From nobody Mon Sep 28 07:22:51 2026 Received: from mail-pg1-f171.google.com (mail-pg1-f171.google.com [209.85.215.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E1ED31E83D for ; Tue, 25 Aug 2026 03:13:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787627607; cv=none; b=KLTQsSt4nT/uN5NHOaI1885venoiI9gexEJo3eYzw2aueRo//aTGGr+Kedph1cZG0MpT72MZo6i7Yt9di2KYVDcctD1mu+YrJH0ZHlkCZQw0Q/pyIaFHVMzEd3oimTlDiCPpAXwqSxLp3EmYYwUyaymkgQ8WYOrpPUjVQsM7ers= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787627607; c=relaxed/simple; bh=2FG4VSNlriZzq0sRBZUYXW1ETfdvWmGFvhJSmbFSe6c=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=hyEOhYuMufQNLk1LdbVdQZmBDcsvvgbEXnCHPvn4UrVx95VIQePbac5WDa5dUZb39WlOxbsUXrlFrzfp//UFIWYJQ8Y2cn5Zpgq0dKXqFsrs+Plr7efQm7WgmRgViUUe98UVQijTYQGhlzN2oMnv8eUdVXMvgOTiySZVsana3Dg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=T66ofBwH; arc=none smtp.client-ip=209.85.215.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="T66ofBwH" Received: by mail-pg1-f171.google.com with SMTP id 41be03b00d2f7-c96c92c0980so2534069a12.3 for ; Mon, 24 Aug 2026 20:13:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787627606; x=1788232406; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=5rcS3VvqecExKBxgTW3DxuIW6wOmPXi4Xwjd2qsZ9Sk=; b=T66ofBwHpBTscLvuIHvdRM8vU2x9ApNw1pZpSO+Wu2Gy8rETOsHAbH3YDhJXc46lFy esKVmUHV7eaHyqVEFzkRmiTdRAEWsdvyH8qkN7kxKI9nbQpq0SiHGMCXMVY6bb+Db+g8 ecXyJ9ahv7Xe8WCzCFCO7h2lya/CVLsalo5VB79J7697arpHf45aTMjbP6q3A9lx4u3+ 9ACkH3Lsn68ZClKWbSbjc8j0l8E8YJ5El07SFx8vj30O4wxj8ZV6YRVUsjbmy0PKz0xW MUqxaq9JY0efKLvX1znxSg4Xls55nvQQYDpfoVw1O7sGHQ7y5pN45oYJbTL3XlmpBBxq voQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787627606; x=1788232406; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5rcS3VvqecExKBxgTW3DxuIW6wOmPXi4Xwjd2qsZ9Sk=; b=TK5CoR/lA+Nn296XniystVrySdijhrdJdQx9x+RnPUKAWsCU6nZvwJQV/mOdfB3c4d qbZn74H/3y8IkfYNKSo3VeCjgPf2ol4tZqeM4uU7oJ2y63Kk2hq9ezYw2ozrLxK5XC6v WxjPBcOdlDPVuCOGPl7kgL6cZYE+sj7QwA3GXA1tCvJnUDimbXAytfNrijn2cmYU9SRm fJyKhFn1t31AM9/NMHfhi8ayBDF35Q0qiVCE6smxRgBmtqHJU7senA510qlpHPZuiaJi PVU8FT/wZ0NcCPpnZWU5SRnugt7s7R/JYWHxfxFmc2L2Q+G1Wu9bzatle4cny6wDM8kt 3e/Q== X-Forwarded-Encrypted: i=1; AHgh+RqLotW7usNTBND68UsKlqhlp5GF+SQqS0pZ5vixVV4WceVNvPZeb0O33yXpiS+ZavWc0LYzO7Z9gjHXtXM=@vger.kernel.org X-Gm-Message-State: AFuF++l6DMuIYvtEcsbyrkZaTQnhZzMqNweOmz8pc+EBR8f9894PHSRB jHzVDyhX254gGIr9tv+v9XMnQ3khrcIpMuAuTMDdnK1sApXuODgxGp0l X-Gm-Gg: AR+sD13vDQpfUYUN7g06YMu4/0ZM/64tN4cvgcXXMnYIn326z3zgLGNVVjJF7fACIdK DLfJEFM9hBmNzy40rsfrDEW1L4l6UiREH7kjfgPTjHG/qfLEl1M2SNQD15GdLTaL2TW1M8IGc4p akVCxM52KiFdUbVMmzFaUbUDSiqYOD2MDS1QPGrjTyZMGowAUymuUjCewtEn8sCHXDEdUqofN12 cDuIVjtHGqQG+AswFn36fLt95xepOlUlGk38ZOM1i5TWEVju8QoegVHV3xKQvB5wxm48Nhec59w xRHAmuQfmIG5vvpJRv5KF/C6FkELlcWnnt4NNNw3eWUZQMZFfbKR+xZSdNKbyymnsqJlW0Sl4b2 DJ3h7DEDIzDjMCaqTenKxmuQ1BucXjTlVfASMG+oGc4NZlqPCs0ln+3oGGB+CvJNSuqeS8Qs+vV KS/77zO0IQCdAzdgBFJo88DNBQJOm3f1DcTtOn5hOsnO5se3QmqIy22sBL2vGj2nkcm19HogMQk fxk3eEGu7adQFHs7ZSKKY8t0f8cixTStLXz6jkW9ezdq7lI99ZG+2Ut3tT0n49mNO7oDXFEukNI xai8i1AWO15L1udG5I77B5OG X-Received: by 2002:a17:90b:3d47:b0:38f:240d:b857 with SMTP id 98e67ed59e1d1-396462feb46mr6907050a91.2.1787627605537; Mon, 24 Aug 2026 20:13:25 -0700 (PDT) Received: from LAPTOP-UUUVNN1I.localdomain (bb119-74-6-224.singnet.com.sg. [119.74.6.224]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39645b0723esm1926097a91.1.2026.08.24.20.13.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2026 20:13:25 -0700 (PDT) From: Wei Jie Law <98lawweijie@gmail.com> To: Dmitry Torokhov Cc: Andrew Duggan , Christopher Heiny , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH] Input: synaptics-rmi4 - fix input_dev->name use-after-free on unplug Date: Tue, 25 Aug 2026 11:13:15 +0800 Message-ID: <20260825031315.51860-1-98lawweijie@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" rmi_driver_probe() reuses the transport driver's input device when it has one, and then renames it out of memory owned by the RMI device: if (rmi_dev->xport->input) { data->input =3D rmi_dev->xport->input; ... name =3D devm_kasprintf(&rmi_dev->dev, GFP_KERNEL, "Synaptics %s", device_name); if (!name) return; input->name =3D name; In the borrowed case the name outlives its allocation. hid-rmi is the transport that hits it: rmi_input_configured() hands us its hidinput device, and rmi_remove() then tears the RMI device down first: rmi_unregister_transport_device(&hdata->xport); hid_hw_stop(hdev); The first line unbinds this driver, so devres frees the name. The second reaches input_unregister_device(), whose device_del() emits the KOBJ_REMOVE uevent, and input_dev_uevent() does if (dev->name) INPUT_ADD_HOTPLUG_VAR("NAME=3D\"%s\"", dev->name); so vsnprintf() walks the freed string and copies it into the uevent that is broadcast to userspace. With slub_debug=3DFZPU the remove event carries NAME=3D"kkkkkkkkkkkkkkkkkkkkkkk\xa5\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb..." i.e. POISON_FREE, POISON_END, the redzone and the SLUB tracking metadata past the end of the object - the read runs to the first NUL, so it leaves the object as well. BUG: KASAN: slab-use-after-free in string+0x2a9/0x330 Read of size 1 at addr ffff88810a379d31 by task name/8056 [...] string+0x2a9/0x330 vsnprintf+0x5ec/0x1680 add_uevent_var+0x165/0x390 input_dev_uevent+0x14c/0x750 dev_uevent+0x26e/0x6e0 kobject_uevent_env+0x4ed/0x11b0 device_del+0x5ac/0x940 input_unregister_device+0x88/0xc0 hidinput_disconnect+0x144/0x3e0 hid_disconnect+0xf7/0x160 hid_hw_stop+0x13/0x70 hid_device_remove+0xc4/0x220 [...] Allocated by task 7810: devm_kasprintf+0xb0/0xe0 rmi_driver_probe+0x3e0/0xbf0 [rmi_core] rmi_register_transport_device+0x19e/0x3e0 [rmi_core] rmi_input_configured+0x184/0x2e0 [hid_rmi] Freed by task 8056: release_nodes+0xf0/0x260 devres_release_all+0x106/0x170 device_unbind_cleanup+0x16/0x1a0 device_release_driver_internal+0x3f9/0x550 rmi_unregister_transport_device+0x34/0x50 [rmi_core] rmi_remove+0xd0/0x100 [hid_rmi] This is not limited to the RMI_DEVICE_HAS_PHYS_BUTTONS models: any RMI4 sensor reaches it, because rmi_init_functions() runs inside rmi_input_configured() and F11/F12/F30 call input_set_capability() on the borrowed device, so hidinput_connect() finds it populated and registers it. 11 to 14 reports per three unplugs here. The same string is read on the add side too. rmi_register_transport_device() returns 0 whenever device_add() succeeded, so a probe failure of this driver - rmi_enable_sensor() failing on a register read is enough, and a HID device that stops answering can arrange that - does not stop the transport: devres frees the name, and hidinput_connect() then goes on to call input_register_device(), which prints the name and emits KOBJ_ADD. BUG: KASAN: slab-use-after-free in string+0x2a9/0x330 [...] input_register_device+0x710/0xe10 hidinput_connect+0x1466/0x2a50 [...] Freed by task 4394: release_nodes+0xf0/0x260 devres_release_all+0x106/0x170 device_unbind_cleanup+0x16/0x1a0 really_probe+0x388/0x930 Moving the allocation onto the input device does not help - device_del() releases devres before it emits the uevent - so put the name back to a string with static storage duration when this driver lets go of an input device it does not own, both on remove and on the probe error paths. That means writing to the borrowed device after hidinput_connect() may already have thrown it away: if none of the RMI functions populated it, hidinput_connect() calls hidinput_cleanup_hidinput() and frees it while data->input still points there. Take a reference for as long as we keep the pointer, which also stops rmi_process_interrupt_requests() from input_sync()ing a freed device. Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI= 4 devices") Cc: stable@vger.kernel.org Signed-off-by: Wei Jie Law <98lawweijie@gmail.com> --- drivers/input/rmi4/rmi_driver.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_drive= r.c index 5d49a9021c7d..8696a6aa0fa9 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -369,6 +369,24 @@ static void rmi_driver_set_input_name(struct rmi_devic= e *rmi_dev, input->name =3D name; } =20 +/* + * Let go of an input device that belongs to the transport driver. It out= lives + * us, but rmi_driver_set_input_name() pointed its name at devres memory of + * ours that is freed as soon as we are done - input_register_device() and= both + * the add and the remove uevent print that name - so put the name back to= a + * string with static storage duration before dropping the reference. + */ +static void rmi_driver_put_input(struct rmi_device *rmi_dev, + struct rmi_driver_data *data) +{ + if (!data->input || data->input !=3D rmi_dev->xport->input) + return; + + data->input->name =3D SYNAPTICS_INPUT_DEVICE_NAME; + input_put_device(data->input); + data->input =3D NULL; +} + static int rmi_driver_set_irq_bits(struct rmi_device *rmi_dev, unsigned long *mask) { @@ -1026,6 +1044,8 @@ static int rmi_driver_remove(struct device *dev) rmi_f34_remove_sysfs(rmi_dev); rmi_free_function_list(rmi_dev); =20 + rmi_driver_put_input(rmi_dev, data); + irq_domain_remove(data->irqdomain); data->irqdomain =3D NULL; =20 @@ -1231,7 +1251,7 @@ static int rmi_driver_probe(struct device *dev) * One example is some HID touchpads report "pass-through" * button events are not reported by rmi registers. */ - data->input =3D rmi_dev->xport->input; + data->input =3D input_get_device(rmi_dev->xport->input); } else { data->input =3D devm_input_allocate_device(dev); if (!data->input) { @@ -1287,6 +1307,7 @@ static int rmi_driver_probe(struct device *dev) err_destroy_functions: rmi_free_function_list(rmi_dev); err: + rmi_driver_put_input(rmi_dev, data); return retval; } =20 --=20 2.43.0