From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oo1-f42.google.com (mail-oo1-f42.google.com [209.85.161.42]) (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 5C54B3CB90A for ; Fri, 17 Jul 2026 08:07:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.42 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784275645; cv=none; b=XA/sfSBixtjHDQkIlpPPZ2UG5d0z7PqbUWN/uALVpS9FjzsauYpoAH3YuLw1vyKXDzMjDzkeFZh3bdUX9brGpDpN+rrQ+WCy1RrgQ6uKsvsKvF6cQmdGakHpsqMWM6N+CG4oeZPt4yhOWIkimTNC5XUfqBp9d6MnqrEHUtcD+Zc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784275645; c=relaxed/simple; bh=L+2PIl9c91cGPKqFh5rawFvpSlD16Mcp4ipH690q0yU=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=ODxXjxmsfnFeaxO5JHVmKqkDyyElaV5DTYFhZ64VezG3pKkRjzSR0yWdWOHpqaZdskQGcZQ4tiZEECgDdsW0dgAL+H8qJ4xEhXIYaCh6de1ysjsN0r6hAoAEngaolJhhBsyXKVqfEm399ckLLKP5EhJQsB7FxaqBVd4R0OVIQZk= 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=cVq0Iacr; arc=none smtp.client-ip=209.85.161.42 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="cVq0Iacr" Received: by mail-oo1-f42.google.com with SMTP id 006d021491bc7-6a183eb9689so2422662eaf.1 for ; Fri, 17 Jul 2026 01:07:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784275641; x=1784880441; 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=bUD8b/O4I8LwhV5Q1VRQ5q+jG0xHp0fGcr6yD3Cz0hU=; b=cVq0IacrErL/Zb/LfUZklGwsbXFjfjXseBYZkhQJ4m5/Xe5NpHOQg8o9Y3QG6tCvju y3AD6G2lIEIFutgEbWFlitiL9MdeKo9yvslvPpIbCLS5fROPD4ogYYF3YarxE648aKTR SW7p0FFvzN8Ua1udnJ3f6tEsZzQtomGgB0pSqpEssfTkI6gPfzCbM55gUoSTWP4WKKm4 QccO2h08jRuxXfEpjrnQqygIucaqk4hFzlw4FALuT/torxoN6lu/ZtUVNxoONzCl1gX4 u+9RIWppcUa+pUOJvqwPLff/4np+mLAAdVJTZNk6XnXcB4r/OgwAGw3Vfrmg0xNIzOCX f+ew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784275641; x=1784880441; 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=bUD8b/O4I8LwhV5Q1VRQ5q+jG0xHp0fGcr6yD3Cz0hU=; b=aEXLj7sk9knScwxqm7SWr9RBb/EMBlogj0nWqzau2pJCudwvdTFS0f73TSQszxC8tw X7M2Ue1KRRJNjUTgLvz8dVl/dsX6OvwynaGzBNjVWmvsp1te0p/kr+Fbo9cEBPiNSwzL 59aOQOZgKR7wbAFElclINpKDfH+ZIA/mQOIljWCbafd5MoYm8aYlWYUufRr/c0udbG+z PEfyPPRIWwZCuat7R4ksN803+XUhjNEQK9kWNzggKfzcvl0Cj21x4UUhjQ7aInTHAPOF WPcboUPbfwrRvMA25d0coWWBndoiHEYeAC+JumvVqWgmmqp83GSZixgJZtwJ9O6DifAz 7R4A== X-Forwarded-Encrypted: i=1; AHgh+RoktS9idE92bFkpeNIPKyUzyh2N08rsL79HaffRBKPbmxRCaiS7fovSaN3Iy/Tom5CLmBJKm4MK8sLkC8Q=@vger.kernel.org X-Gm-Message-State: AOJu0Yzrz/TPG0uaEF4dasofUtrozx8E4unOzzqwHJCJ+iLFgWQzfPjE otUvdDjGsKqLcJVd7RAKtkEqoS/kwSQEmlG8TjeDghPSVDWKhkMmRzYmb6so0g== X-Gm-Gg: AfdE7clYCS+jpxUWedpcV9ZBwGgG58QFm0F0v+hmoOQ/any26vrRhhBGUHjUWpmZl6u ZKkM2k0bUwQC5PJlNuhWpEi3O3l7miaDPZVFqeMxZYX5oW5tzJXj5sSq3cMlJEvJ3mN/Sc2bjyj P68MGFdaosVaCeCzz8zx3GLLzQ2WR3eVnV7bjRGyfHF/QlYRbyQFMuxqh7RtbkEN7TVUaJIpx// wDVb7xFRp+s9G2FeWiiT4xyg/MapcP3atN9ABLl6KSaIkAokAxS5Grk3q+GxreyNBDtXm09j0IN cF3VhIxx3JCl26YB5wOrLgdgs5+g/5YycYLPlFI4guy9YA2zfFvRO8yPVmlSUfl1GJoif88neYh LbCsc8dhh9eTeM7GqA5v1xgFAlwZI2j8UlhIErSOLnnuxG+mOLxL8roDH04a7bQ3Dha8LMVzBLp gAQ34SySPqRJfT X-Received: by 2002:a05:6820:1523:b0:6a3:f5e9:8e45 with SMTP id 006d021491bc7-6a53669164emr611027eaf.1.1784275640951; Fri, 17 Jul 2026 01:07:20 -0700 (PDT) Received: from capidev ([2806:264:548c:900d:4433:c2f3:888d:435c]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4568da4ab47sm923890fac.0.2026.07.17.01.07.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jul 2026 01:07:20 -0700 (PDT) From: Diego Fernando Mancera Gomez To: Matthieu CASTET , Stanislaw Gruszka Cc: Chas Williams <3chas3@gmail.com>, Greg Kroah-Hartman , Mauricio Faria de Oliveira , linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-atm-general@lists.sourceforge.net, linux-kernel@vger.kernel.org, Diego Fernando Mancera Gomez , syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com Subject: [PATCH] usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect Date: Fri, 17 Jul 2026 02:07:04 -0600 Message-ID: <20260717080704.1264-1-diegomancera.dev@gmail.com> X-Mailer: git-send-email 2.54.0.windows.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Antivirus: Norton (VPS 260717-0, 16/7/2026), Outbound message X-Antivirus-Status: Clean uea_probe() distinguishes a pre-firmware device from a post-firmware one using the USB id (UEA_IS_PREFIRM()), and stores a different object as the interface data in each case: a 'struct completion' for a pre-firmware device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a post-firmware one. uea_disconnect() instead tells the two apart by the number of interfaces of the active configuration (a pre-firmware device exposes a single interface, ADI930 has 2 and eagle has 3), and casts the interface data accordingly. Because the two handlers use different criteria, a crafted device that advertises a pre-firmware id together with a multi-interface descriptor (or a post-firmware id with a single interface) makes them disagree: the small 'struct completion' stored by uea_probe() is then passed to usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes instance->serialize, reading past the end of the allocation: BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 ... __mutex_lock+0x152a/0x1b80 usbatm_usb_disconnect+0x70/0x820 uea_disconnect+0x133/0x2c0 usb_unbind_interface+0x1dd/0x9e0 ... which belongs to the cache kmalloc-96 of size 96 The buggy address is located 0 bytes to the right of allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) Reject such inconsistent descriptors in uea_probe() so that both handlers always make the same pre/post-firmware decision. Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") Signed-off-by: Diego Fernando Mancera Gomez --- drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 4e71ed679a76..4266a0cb7e3b 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -2549,6 +2549,7 @@ static struct usbatm_driver uea_usbatm_driver = { static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *usb = interface_to_usbdev(intf); + bool single_iface = usb->config->desc.bNumInterfaces == 1; int ret; uea_dbg(usb, "ADSL device found with vid (%#X) pid (%#X) Rev (%#X): %s\n", @@ -2557,6 +2558,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) le16_to_cpu(usb->descriptor.bcdDevice), chip_name[UEA_CHIP_VERSION(id)]); + /* + * uea_probe() decides between the pre-firmware and post-firmware case + * from the USB id and stores a different object as interface data in + * each case: a struct completion for a pre-firmware device, a struct + * usbatm_data for a post-firmware one. uea_disconnect() instead tells + * the two apart by the number of interfaces (a pre-firmware device + * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted + * device advertising a pre-firmware id together with a multi-interface + * descriptor (or the other way around) makes the two disagree, so that + * usbatm_usb_disconnect() treats the small completion object as a + * struct usbatm_data and reads out of bounds. Reject such inconsistent + * descriptors so both paths make the same decision. + */ + if (UEA_IS_PREFIRM(id) != single_iface) + return -ENODEV; + usb_reset_device(usb); if (UEA_IS_PREFIRM(id)) { -- 2.43.0