Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp3127872yba; Sat, 18 May 2019 09:50:06 -0700 (PDT) X-Google-Smtp-Source: APXvYqwz/F3Nw1nBA16OvkTQLUaKPxac72HS/gckLZZLu/XmWVtCtkIueTMxZJs9fCXCHAFl6v7K X-Received: by 2002:a63:4852:: with SMTP id x18mr50738818pgk.14.1558198206361; Sat, 18 May 2019 09:50:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1558198206; cv=none; d=google.com; s=arc-20160816; b=g3KDKASISoa3/jHOogccuFFuSS8Qv0pmHTc7fuYUEoVFBKyp1QYZZRDSx/8OxgJ6Ur 6ktA4OEkKRhVMEttFAJuXtlmjXhOrlQNNSPPvFu0z05OXsONqE41LLBLmjGRVJh6+DuQ x2Xtmjmd6N8t1j/WX90nQqLYPAN+to0U8EBk2A8kbv0bOuhkMD4SuVxpavvsms/QHSSL Md0h2+LUtewgqirsrbhCeFpykL9fRsdXhLPNdd6pDm2BNd/fmVTMoaisqPw0YUPLqiuL yY63pdssCst9dzBDh93ttOG9BhZ4T1+zQkMpfJ2/yAiJSEmHEevs6fv4ANuAL2hsyquL duWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:in-reply-to :subject:cc:to:from:date; bh=UyeHCMiLD1yI+rLb+/EgV8JH1nPyHKVm9vGQkqDd2Ds=; b=wxfVvRH0qN+LoaRZD+CKu30dcP/HaKAgP+N/HL8uBpeZwo+rzJ2PH657BVwVyyE9yU VLOXVcIS6yU6LqiFgIs0zOnK8m4bCw9GvQLYVqfcurQxL32SIr+gVpZarFaVJEX9wFp/ srrFj7mumuy6ZPRQ7tBcMpU+wJzzG7nFOrE6zsW70mpdO2xJUmZJ6cv+LBIMaUGHOKY0 0zEtCyjO8TrY4PtP/Ln1+MYJy9alpBliKVNUYdehOQkR4COhd4qP8VqBDky3Any0VWGD 42lNh190LiqcWTx79+F4yzXUs5Ha7Z0WPARXqdN81VF5rMTufURzaWetTaIOrwF2iF9Z wW4g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 90si7609603pla.323.2019.05.18.09.49.49; Sat, 18 May 2019 09:50:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729750AbfERQcL (ORCPT + 99 others); Sat, 18 May 2019 12:32:11 -0400 Received: from netrider.rowland.org ([192.131.102.5]:54603 "HELO netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1729623AbfERQcK (ORCPT ); Sat, 18 May 2019 12:32:10 -0400 Received: (qmail 10095 invoked by uid 500); 18 May 2019 12:32:09 -0400 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 18 May 2019 12:32:09 -0400 Date: Sat, 18 May 2019 12:32:09 -0400 (EDT) From: Alan Stern X-X-Sender: stern@netrider.rowland.org To: syzbot cc: andreyknvl@google.com, , , , , , , , , , Subject: Re: KASAN: use-after-free Read in p54u_load_firmware_cb In-Reply-To: <000000000000add98105892b73ec@google.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, 18 May 2019, syzbot wrote: > Hello, > > syzbot has tested the proposed patch but the reproducer still triggered > crash: > KASAN: slab-out-of-bounds Read in p54u_load_firmware_cb > > usb 6-1: Direct firmware load for isl3887usb failed with error -2 > p54u_load_firmware_cb: priv->udev = ffff88809ad5bb80 > usb 6-1: Firmware not found. > ================================================================== > BUG: KASAN: slab-out-of-bounds in p54u_load_firmware_cb+0x3c9/0x45f > drivers/net/wireless/intersil/p54/p54usb.c:937 > Read of size 8 at addr ffff88809abab588 by task kworker/1:8/5526 If you look at the full console log, you'll see that this address is different from all the addresses printed out earlier. Not what you would expect. Which makes me wonder: Suppose a disconnect occurs before the firmware loader callback runs? p54_disconnect() will get stuck waiting for the priv->fw_load_wait completion to fire. But when the callback runs, the first thing it does is activate the completion. So now p54_disconnect() can finish doing its thing, including deallocating all the private data structures. Then when p54u_load_firmware_cb() tries to read the contents of priv, it ends up accessing deallocated memory! The patch below tries to do things the right way. Alan Stern #syz test: https://github.com/google/kasan.git usb-fuzzer drivers/net/wireless/intersil/p54/p54usb.c | 37 +++++++++++------------------ 1 file changed, 15 insertions(+), 22 deletions(-) Index: usb-devel/drivers/net/wireless/intersil/p54/p54usb.c =================================================================== --- usb-devel.orig/drivers/net/wireless/intersil/p54/p54usb.c +++ usb-devel/drivers/net/wireless/intersil/p54/p54usb.c @@ -33,6 +33,8 @@ MODULE_ALIAS("prism54usb"); MODULE_FIRMWARE("isl3886usb"); MODULE_FIRMWARE("isl3887usb"); +static struct usb_driver p54u_driver; + /* * Note: * @@ -921,9 +923,9 @@ static void p54u_load_firmware_cb(const { struct p54u_priv *priv = context; struct usb_device *udev = priv->udev; + struct usb_interface *intf = priv->intf; int err; - complete(&priv->fw_wait_load); if (firmware) { priv->fw = firmware; err = p54u_start_ops(priv); @@ -932,23 +934,19 @@ static void p54u_load_firmware_cb(const dev_err(&udev->dev, "Firmware not found.\n"); } - if (err) { - struct device *parent = priv->udev->dev.parent; - - dev_err(&udev->dev, "failed to initialize device (%d)\n", err); - - if (parent) - device_lock(parent); + complete(&priv->fw_wait_load); + /* + * At this point p54u_disconnect may have already freed + * the "priv" context. Do not use it anymore! + */ + priv = NULL; - device_release_driver(&udev->dev); - /* - * At this point p54u_disconnect has already freed - * the "priv" context. Do not use it anymore! - */ - priv = NULL; + if (err) { + dev_err(&intf->dev, "failed to initialize device (%d)\n", err); - if (parent) - device_unlock(parent); + usb_lock_device(udev); + usb_driver_release_interface(intf, &p54u_driver); + usb_unlock_device(udev); } usb_put_dev(udev); @@ -1011,8 +1009,6 @@ static int p54u_probe(struct usb_interfa skb_queue_head_init(&priv->rx_queue); init_usb_anchor(&priv->submitted); - usb_get_dev(udev); - /* really lazy and simple way of figuring out if we're a 3887 */ /* TODO: should just stick the identification in the device table */ i = intf->altsetting->desc.bNumEndpoints; @@ -1053,10 +1049,8 @@ static int p54u_probe(struct usb_interfa priv->upload_fw = p54u_upload_firmware_net2280; } err = p54u_load_firmware(dev, intf); - if (err) { - usb_put_dev(udev); + if (err) p54_free_common(dev); - } return err; } @@ -1072,7 +1066,6 @@ static void p54u_disconnect(struct usb_i wait_for_completion(&priv->fw_wait_load); p54_unregister_common(dev); - usb_put_dev(interface_to_usbdev(intf)); release_firmware(priv->fw); p54_free_common(dev); }