Received: by 2002:a05:6a10:c604:0:0:0:0 with SMTP id y4csp3767172pxt; Tue, 10 Aug 2021 10:50:47 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwOuripilahR1yy6A9Y1mEfxTF9AqnT59nTta+wSk+Ek+JPaVpwkncyQ7vnL/rr4ZLL525X X-Received: by 2002:a02:a40f:: with SMTP id c15mr29007527jal.38.1628617847306; Tue, 10 Aug 2021 10:50:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1628617847; cv=none; d=google.com; s=arc-20160816; b=S+3DT/YwSpjH0JCkHSJuh//wcdFdbMpncQlsF8mQctHApiSUDfqp1qbeZaH1N0l//o 4zk38KLo6ZGecAvj0+e8PWkuV8MM9uh9aNFB+dirHf0PzpXsJPTkLyU/UoZCGRXDpUmc 0AOx6RqoQW7wIJgydfJHX79KYeyfvsl0hmum6e4mavJlGGn6vvOrk+YfO6VZHTmsLHFU XpWg92qnQtWR3B0Z9y9sMVvQi8nbKJAXB3TpFjBhxE3wnOkURXHpaHjzabxqMRfHTdCC x4/PbBGZDx8w7ooMdELbiJ2Imw2xMQocqW3C6YmnwsTMwnCmKFNxywNMWjoZIAGxitGx E9pA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=wDUDcdIo/pQEa3q6v5ndM8gLV1Q5s5H6olXuzzDwQHo=; b=CvubVe3I8Y0YeDZYvt2e4uBmRZarrI89/WtpKBo6tqnOx0TxeWDeRntF/kkGQmv84E G8FNP7W/+x2IthKg6ZpGGYTuovxpUZxtS1m7ww7oIrkBGe64kk+2MVcZjo7YVb7KaehD dXgcyt4Nkw3CyNwns4IIw6h/6cISIyk5THFKRqxpac8PYZ2fCw7f1wqkoMUr4sfaZaSY gf/7ZVICBM4drhNmptRirGzke/n8siR0Vfrx3O0Jg6vnsrTghAiNlRbVHn3iTRmL5U5v teJTjZbIBUnuR3h+/vH7SlbPQdERquB8rataSGXz37Pu8EiBF/yMuqJXGGWQG7wEeVZh ABzw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=1oi5S2yA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s1si21459071ios.1.2021.08.10.10.50.36; Tue, 10 Aug 2021 10:50:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=1oi5S2yA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235941AbhHJRsL (ORCPT + 99 others); Tue, 10 Aug 2021 13:48:11 -0400 Received: from mail.kernel.org ([198.145.29.99]:51962 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236497AbhHJRox (ORCPT ); Tue, 10 Aug 2021 13:44:53 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id DED2D61158; Tue, 10 Aug 2021 17:39:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1628617198; bh=Gkv8usg/hRL6/6cAr9d4ZngDvOLRKk8GTGE5ck5X+dU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1oi5S2yAiCwgTGIXhPafgZOq6g9SAlL8DYrpiLJpjmn1HjaPm9kENOxHwkTqHTZ/S LLo1fV/0yKu+QrX1Qw3g7NoQL/081JphnkQpQmgcLzdmkirhXnCSz5ydwqV2Udo620 ajxK7rFiFZ/IWxXccTUEF6fAMAn1J9LR5SldKuIs= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Pavel Skripkin , syzbot+5872a520e0ce0a7c7230@syzkaller.appspotmail.com, syzbot+cc699626e48a6ebaf295@syzkaller.appspotmail.com Subject: [PATCH 5.10 089/135] staging: rtl8712: error handling refactoring Date: Tue, 10 Aug 2021 19:30:23 +0200 Message-Id: <20210810172958.783707656@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210810172955.660225700@linuxfoundation.org> References: <20210810172955.660225700@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Pavel Skripkin commit e9e6aa51b2735d83a67d9fa0119cf11abef80d99 upstream. There was strange error handling logic in case of fw load failure. For some reason fw loader callback was doing clean up stuff when fw is not available. I don't see any reason behind doing this. Since this driver doesn't have EEPROM firmware let's just disconnect it in case of fw load failure. Doing clean up stuff in 2 different place which can run concurently is not good idea and syzbot found 2 bugs related to this strange approach. So, in this pacth I deleted all clean up code from fw callback and made a call to device_release_driver() under device_lock(parent) in case of fw load failure. This approach is more generic and it defend driver from UAF bugs, since all clean up code is moved to one place. Fixes: e02a3b945816 ("staging: rtl8712: fix memory leak in rtl871x_load_fw_cb") Fixes: 8c213fa59199 ("staging: r8712u: Use asynchronous firmware loading") Cc: stable Reported-and-tested-by: syzbot+5872a520e0ce0a7c7230@syzkaller.appspotmail.com Reported-and-tested-by: syzbot+cc699626e48a6ebaf295@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin Link: https://lore.kernel.org/r/d49ecc56e97c4df181d7bd4d240b031f315eacc3.1626895918.git.paskripkin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/hal_init.c | 30 +++++++++++++++-------- drivers/staging/rtl8712/usb_intf.c | 48 ++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 37 deletions(-) --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -29,21 +29,31 @@ #define FWBUFF_ALIGN_SZ 512 #define MAX_DUMP_FWSZ (48 * 1024) +static void rtl871x_load_fw_fail(struct _adapter *adapter) +{ + struct usb_device *udev = adapter->dvobjpriv.pusbdev; + struct device *dev = &udev->dev; + struct device *parent = dev->parent; + + complete(&adapter->rtl8712_fw_ready); + + dev_err(&udev->dev, "r8712u: Firmware request failed\n"); + + if (parent) + device_lock(parent); + + device_release_driver(dev); + + if (parent) + device_unlock(parent); +} + static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) { struct _adapter *adapter = context; if (!firmware) { - struct usb_device *udev = adapter->dvobjpriv.pusbdev; - struct usb_interface *usb_intf = adapter->pusb_intf; - - dev_err(&udev->dev, "r8712u: Firmware request failed\n"); - usb_put_dev(udev); - usb_set_intfdata(usb_intf, NULL); - r8712_free_drv_sw(adapter); - adapter->dvobj_deinit(adapter); - complete(&adapter->rtl8712_fw_ready); - free_netdev(adapter->pnetdev); + rtl871x_load_fw_fail(adapter); return; } adapter->fw = firmware; --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -594,36 +594,30 @@ static void r871xu_dev_remove(struct usb { struct net_device *pnetdev = usb_get_intfdata(pusb_intf); struct usb_device *udev = interface_to_usbdev(pusb_intf); + struct _adapter *padapter = netdev_priv(pnetdev); - if (pnetdev) { - struct _adapter *padapter = netdev_priv(pnetdev); + /* never exit with a firmware callback pending */ + wait_for_completion(&padapter->rtl8712_fw_ready); + usb_set_intfdata(pusb_intf, NULL); + release_firmware(padapter->fw); + if (drvpriv.drv_registered) + padapter->surprise_removed = true; + if (pnetdev->reg_state != NETREG_UNINITIALIZED) + unregister_netdev(pnetdev); /* will call netdev_close() */ + r8712_flush_rwctrl_works(padapter); + r8712_flush_led_works(padapter); + udelay(1); + /* Stop driver mlme relation timer */ + r8712_stop_drv_timers(padapter); + r871x_dev_unload(padapter); + r8712_free_drv_sw(padapter); + free_netdev(pnetdev); - /* never exit with a firmware callback pending */ - wait_for_completion(&padapter->rtl8712_fw_ready); - pnetdev = usb_get_intfdata(pusb_intf); - usb_set_intfdata(pusb_intf, NULL); - if (!pnetdev) - goto firmware_load_fail; - release_firmware(padapter->fw); - if (drvpriv.drv_registered) - padapter->surprise_removed = true; - if (pnetdev->reg_state != NETREG_UNINITIALIZED) - unregister_netdev(pnetdev); /* will call netdev_close() */ - r8712_flush_rwctrl_works(padapter); - r8712_flush_led_works(padapter); - udelay(1); - /* Stop driver mlme relation timer */ - r8712_stop_drv_timers(padapter); - r871x_dev_unload(padapter); - r8712_free_drv_sw(padapter); - free_netdev(pnetdev); + /* decrease the reference count of the usb device structure + * when disconnect + */ + usb_put_dev(udev); - /* decrease the reference count of the usb device structure - * when disconnect - */ - usb_put_dev(udev); - } -firmware_load_fail: /* If we didn't unplug usb dongle and remove/insert module, driver * fails on sitesurvey for the first time when device is up. * Reset usb port for sitesurvey fail issue.