From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f178.google.com (mail-dy1-f178.google.com [74.125.82.178]) (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 60E9E36A355 for ; Wed, 10 Jun 2026 23:22:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781133759; cv=none; b=mat43kmikxWQdyi9138Hj6v5xPXDs2K+aJJB4SfKpwEs+uXXlJ2uvyCrMlvuLWkYTpVnfZpWKBopy13gMV44wf362E5Vw/yHP1+vZ4JlThBRwAb81WqeVEyEI6U4+sTcqwB0t61juwmEliqOwL8b2Y8WW7Rw1Pbpm6Aw2uZOicQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781133759; c=relaxed/simple; bh=Qb9fwjWXWQbQ4G5fxMsW4pWxfQnE9Z3sgY1oqF/NeBI=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=SPSnOtJfKghzQlhOM6hLEBx0U+AImMKfh13aDePgASFDk4rv01wan7M/uxuLvRnskwQhkEa2cIPWe0Pl1rOzGYCvd93U98MOeBWAUhPQzf1Nt9r4lQq0Nz7L7qLMU3Zgb0JM8C59Dg2TPe8j1MMm2dj0ORap3kB/OAU+FqHZ4aU= 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=nf222bsX; arc=none smtp.client-ip=74.125.82.178 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="nf222bsX" Received: by mail-dy1-f178.google.com with SMTP id 5a478bee46e88-3075ce9c05aso2083231eec.1 for ; Wed, 10 Jun 2026 16:22:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781133757; x=1781738557; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=anl/tIPqzLKNrSthWVK3ftWFNeblmDRtjXLgHKj0shc=; b=nf222bsXZxy8SKR7hik3YYDnjjQ9X9LZ6w1n8nD4GwkfJ5W8AbiT0M0/ktjfZbgXxe RwkUe9aCl00Ufl0xjgQLxJCmIDFOaLLXpmq/pRPTQ8T8X9Q7qYY1n6l8STEOVbq0c4ai 1AfmLoVnvLetp5vuD5XBAUgsuioJ9+SJROGehqaD0/n4Iis84nTP6l4KO9VgLXsLzu8S ID1IrbqlYg00IsTcairplEMMDy6XIX1+0RSbMzh7gOlZ2MCuzfGlbagqBRE4yNH4kY29 QMIrCBGOG1ASScvluB8EmFRKALDimyl/LPREGCCIoLHOWzvQgrIi8eA3XsMjvdP2S0Ha G2cQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781133757; x=1781738557; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=anl/tIPqzLKNrSthWVK3ftWFNeblmDRtjXLgHKj0shc=; b=ss+2ILqqcbHQJgFJfIAz55ygzTHnKW3LmzArFE5eq+Cocixc1BaGepueE35qOKwF5M 3xtijsQ7/QlCku7cymfdekzNSzprhPVRKwRKXRQNj+/3Cu7gahblxjYXCke+0KPYqqNU /zU+fXqHQ6HiUZxXU4O7HBopmzG5o0ishvHVWCMTuR4wAYfUwd1cGZHRIYbgUb8IOwOX gLmzgiaOtSZhscKgBKNh8NUV2DK2dP4ECYVFBU3Y/S0E2Wsnr5yYUZ0vK21UTWfiSlCR +Ji4rPP+YWaYeOuSdOyF+Hoq+jIJNPdio1DNXBlPY4kmcWt0mMyt8cJLvtrK2S2pxnu5 ex/A== X-Forwarded-Encrypted: i=1; AFNElJ96amtboLE2/DjyQauC4EkTdnzD/ndElUnNNGDc/MpkidbgQff4TULH4e9Hh3ChH1JNn4SjbfdFiGaGOTA=@vger.kernel.org X-Gm-Message-State: AOJu0YzluCnCT9cvKChaKNziCwg5fcNpMYoRY8lJkRc2dMObzQFrr7/F Ljbw77Wu5raIoei9JtfIzZVCOgRDyxaUpYdKNTM9/ZxD2R+DtrG1o4a3 X-Gm-Gg: Acq92OE56zJ18ICkButIzVCbhqLB/nh2KVwtbGvvGObbPtECXjM0HqlOvlnFdy0NNP0 g6LnzM0d2pxrz94z5fCh+MxZs2qENxVE/0t+XmlGLpSfC8U0Sq7aHMsTsXw24mvDOmBliQrIISM JLN2crI17u6DuenZg3eP8keGsZp2arBxWRmkZtYN7MIFZ0fwilSi08wHc2I2YZDjXWHQgLJNvrg 4NvJMasSUVpYxxjdRJUxRrGRWP1XdvwE/9eh7dWeQ+H8nDTkXRAeGgEoR8p7NsRlYhGZNN42/zX kqOU17z2bNTKFq+pqD5m6Dab57N2cJOzBcdoqWHJkjm4Dvew823Iv1psHHaBnF44xrghs60Kvo2 9x3qKOEgA4/pW3XnpICbx5RyXLozpWjS0kQxRumpAgm/3rz1mvMUbF6NeuVpX99ZkXRs5gP+NRm z2k6hs1WDrgPIFgfIAkwamFf2VZuAmIe5ymx2oY7DNPkNYhEVYJdrJvdSEWIQxnnyurTuzcZq7h lU= X-Received: by 2002:a05:7300:324d:b0:304:e566:e000 with SMTP id 5a478bee46e88-30804bc1171mr325050eec.31.1781133757533; Wed, 10 Jun 2026 16:22:37 -0700 (PDT) Received: from google.com ([2a00:79e0:2ebe:8:ae0e:e075:91c8:6570]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3074df75ff6sm28869773eec.26.2026.06.10.16.22.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Jun 2026 16:22:36 -0700 (PDT) Date: Wed, 10 Jun 2026 16:22:34 -0700 From: Dmitry Torokhov To: Lee Jones Cc: Ping Cheng , Jason Gerecke , Jiri Kosina , Benjamin Tissoires , Peter Hutterer , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v3 1/4] HID: wacom: Fix Use-After-Free in wacom_intuos_pad Message-ID: References: <20260609121353.3743782-1-lee@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260609121353.3743782-1-lee@kernel.org> On Tue, Jun 09, 2026 at 01:13:37PM +0100, Lee Jones wrote: > wacom_intuos_pad() accesses wacom->shared->touch_input locklessly > inside the interrupt handler context. If the Touch sibling device > is disconnected, wacom_remove_shared_data() clears 'touch_input' > outside any lock, creating a Time-of-Check to Time-of-Use (TOCTOU) > race condition where a preempted reader in interrupt context > dereferences the freed pointer, leading to a Use-After-Free. > > Resolve this by introducing RCU protection for the touch_input > pointer: > > - Annotate 'touch_input' in wacom_shared struct with __rcu > - Wrap all lockless readers in wacom_wac.c with rcu_read_lock() and > rcu_dereference() using a unified wacom_report_touch_mute() > helper > - Update writers in wacom_sys.c using rcu_assign_pointer() > - Call synchronize_rcu() in wacom_remove_shared_data() to ensure > all active RCU readers have finished before the input device is > freed > > Also wrap wacom_set_shared_values() and touch/pen assignments in > wacom_add_shared_data() inside the wacom_udev_list_lock to serialize > concurrent probe assignments, and verify that 'shared->touch == hdev' > before setting touch_input to prevent concurrent sibling probe state > desynchronization. > > Finally, advertise the SW_MUTE_DEVICE capability on Touch input > devices prior to registration in wacom_setup_touch_input_capabilities() > to prevent invalid post-registration capability modifications. > > Fixes: 961794a00eab ("Input: wacom - add reporting of SW_MUTE_DEVICE events") > Signed-off-by: Lee Jones > --- > > v1 -> v2: Split and use RCU as per Dmitry's review > v2 -> v3: Sashiko fixes > > drivers/hid/wacom_sys.c | 41 ++++++++++++++---------- > drivers/hid/wacom_wac.c | 70 ++++++++++++++++++++++------------------- > drivers/hid/wacom_wac.h | 2 +- > 3 files changed, 63 insertions(+), 50 deletions(-) > > diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c > index 2220168bf116..7ba589826548 100644 > --- a/drivers/hid/wacom_sys.c > +++ b/drivers/hid/wacom_sys.c > @@ -877,10 +877,16 @@ static void wacom_remove_shared_data(void *res) > data = container_of(wacom_wac->shared, struct wacom_hdev_data, > shared); > > - if (wacom_wac->shared->touch == wacom->hdev) > - wacom_wac->shared->touch = NULL; > - else if (wacom_wac->shared->pen == wacom->hdev) > - wacom_wac->shared->pen = NULL; > + scoped_guard(mutex, &wacom_udev_list_lock) { > + if (wacom_wac->shared->touch == wacom->hdev) { > + wacom_wac->shared->touch = NULL; > + rcu_assign_pointer(wacom_wac->shared->touch_input, NULL); > + } else if (wacom_wac->shared->pen == wacom->hdev) { > + wacom_wac->shared->pen = NULL; > + } > + } > + > + synchronize_rcu(); > > kref_put(&data->kref, wacom_release_shared_data); > wacom_wac->shared = NULL; > @@ -909,6 +915,11 @@ static int wacom_add_shared_data(struct hid_device *hdev) > list_add_tail(&data->list, &wacom_udev_list); > } > > + if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) > + data->shared.touch = hdev; > + else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) > + data->shared.pen = hdev; > + > mutex_unlock(&wacom_udev_list_lock); > > wacom_wac->shared = &data->shared; > @@ -917,11 +928,6 @@ static int wacom_add_shared_data(struct hid_device *hdev) > if (retval) > return retval; > > - if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) > - wacom_wac->shared->touch = hdev; > - else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) > - wacom_wac->shared->pen = hdev; > - > return retval; > } > > @@ -2345,9 +2351,15 @@ static void wacom_release_resources(struct wacom *wacom) > > static void wacom_set_shared_values(struct wacom_wac *wacom_wac) > { > + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); > + > + mutex_lock(&wacom_udev_list_lock); Why not guard(mutex)(&wacom_udev_list_lock); > + > if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) { > - wacom_wac->shared->type = wacom_wac->features.type; > - wacom_wac->shared->touch_input = wacom_wac->touch_input; > + if (wacom_wac->shared->touch == wacom->hdev) { > + wacom_wac->shared->type = wacom_wac->features.type; > + rcu_assign_pointer(wacom_wac->shared->touch_input, wacom_wac->touch_input); > + } > } > > if (wacom_wac->has_mute_touch_switch) { > @@ -2361,12 +2373,7 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac) > wacom_wac->shared->is_touch_on = true; > } > > - if (wacom_wac->shared->has_mute_touch_switch && > - wacom_wac->shared->touch_input) { > - set_bit(EV_SW, wacom_wac->shared->touch_input->evbit); > - input_set_capability(wacom_wac->shared->touch_input, EV_SW, > - SW_MUTE_DEVICE); > - } > + mutex_unlock(&wacom_udev_list_lock); > } > > static int wacom_parse_and_register(struct wacom *wacom, bool wireless) > diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c > index da1f0ea85625..495960227b8d 100644 > --- a/drivers/hid/wacom_wac.c > +++ b/drivers/hid/wacom_wac.c > @@ -510,6 +510,22 @@ static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac) > } > } > > +static void wacom_report_touch_mute(struct wacom_wac *wacom_wac, bool mute) > +{ > + struct input_dev *touch_input; > + > + if (!wacom_wac->shared) > + return; Can this happen? I think callers already check this or simply dereference. > + > + rcu_read_lock(); guard(rcu)(); > + touch_input = rcu_dereference(wacom_wac->shared->touch_input); > + if (touch_input) { > + input_report_switch(touch_input, SW_MUTE_DEVICE, mute); > + input_sync(touch_input); > + } > + rcu_read_unlock(); > +} > + Thanks. -- Dmitry