Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp3451103pxv; Sun, 18 Jul 2021 23:50:02 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxWC0YkMp4/PaZZjU2rbrSvVsCmskROTM1VQs6soCogo/OTaLxjRYE6tR3P9+3LTYLS72+4 X-Received: by 2002:a17:906:1c43:: with SMTP id l3mr25893553ejg.291.1626677401908; Sun, 18 Jul 2021 23:50:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626677401; cv=none; d=google.com; s=arc-20160816; b=h1b9ciJPdzuWvOqmFBdGGqfH0ilSUhMh2Uhi1MUQVxZtizjvepbflPy5wRAd7ghCdW 47vG9ulLeozNNtv8MzDB2+939155qaEqtZk88sQfRVZ7AIVVl/KrPxuE2v9ikVfNZ17N TcTvTjoJnbgCA82Welhn5eK4PLeJgPkz8qMPpvkvnLVg3uM39zrw4wTp3seEaJ1hdzGn IQh7eUL6wNYcrWRpj5fWkjXUXf5auimhn4VGA+xWQNd05l36Yp+tYTvAUeRPx2Lz7Y7j ECOHET/BVenJobLDoZCvOgvetzbBXynOh9HpY3HG2IjOte9dcW8ediMIRaVbhTKM0jAc qoxA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from; bh=YYlhNZ+z8aWfK+Dqox+j2D0kFeVBRSaFFMjVC+/pmKw=; b=C+hvQYG7X+OtzkSEbra6FLtqTgOSvvVbXAx87aAgy+3PXkkCHKqiIpiibqlgD21qNS ut8hwr1lH8UKXkfO4+AyYKRyADgXKDQoDWN9AQ1jWScE3F7OHF3RebegEJyHPE+1Ibbk BMPL4ITgflEDh7c0nmpXzn35qigOE9N7/RdR35u03x97fJH1bpnDNhP2hyBepKy3wvb8 u3GwkaDVufTEELl9lgumv75lKNYaVxCu5/8rEJGpkL31A+NWRzViwehsjWo8lUALqEAv 7mvIRVLvRU46bUEsSs2RKmdlg5JaQTkXSCN7MSHuD3N4rGZAgSSmwbIZIoahM1o7ymEt b1lA== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t5si18934767eds.212.2021.07.18.23.49.38; Sun, 18 Jul 2021 23:50:01 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233717AbhGSGv2 (ORCPT + 99 others); Mon, 19 Jul 2021 02:51:28 -0400 Received: from szxga01-in.huawei.com ([45.249.212.187]:7031 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233048AbhGSGv2 (ORCPT ); Mon, 19 Jul 2021 02:51:28 -0400 Received: from dggemv703-chm.china.huawei.com (unknown [172.30.72.54]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4GSsjG5KGdzYcny; Mon, 19 Jul 2021 14:42:42 +0800 (CST) Received: from dggpemm500006.china.huawei.com (7.185.36.236) by dggemv703-chm.china.huawei.com (10.3.19.46) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Mon, 19 Jul 2021 14:48:26 +0800 Received: from thunder-town.china.huawei.com (10.174.179.0) by dggpemm500006.china.huawei.com (7.185.36.236) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Mon, 19 Jul 2021 14:48:26 +0800 From: Zhen Lei To: Luis Chamberlain , Greg Kroah-Hartman , "Rafael J . Wysocki" , linux-kernel CC: Zhen Lei Subject: [PATCH v2 1/1] firmware: fix theoretical UAF race with firmware cache and resume Date: Mon, 19 Jul 2021 14:45:31 +0800 Message-ID: <20210719064531.3733-2-thunder.leizhen@huawei.com> X-Mailer: git-send-email 2.26.0.windows.1 In-Reply-To: <20210719064531.3733-1-thunder.leizhen@huawei.com> References: <20210719064531.3733-1-thunder.leizhen@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.174.179.0] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To dggpemm500006.china.huawei.com (7.185.36.236) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This race was discovered when I carefully analyzed the code to locate another firmware-related UAF issue. It can be triggered only when the firmware load operation is executed during suspend. This possibility is almost impossible because there are few firmware load and suspend actions in the actual environment. CPU0 CPU1 __device_uncache_fw_images(): assign_fw(): fw_cache_piggyback_on_request() <----- P0 spin_lock(&fwc->name_lock); ... list_del(&fce->list); spin_unlock(&fwc->name_lock); uncache_firmware(fce->name); <----- P1 kref_get(&fw_priv->ref); If CPU1 is interrupted at position P0, the new 'fce' has been added to the list fwc->fw_names by the fw_cache_piggyback_on_request(). In this case, CPU0 executes __device_uncache_fw_images() and will be able to see it when it traverses list fwc->fw_names. Before CPU1 executes kref_get() at P1, if CPU0 further executes uncache_firmware(), the count of fw_priv->ref may decrease to 0, causing fw_priv to be released in advance. Move kref_get() to the lock protection range of fwc->name_lock to fix it. Fixes: ac39b3ea73aa ("firmware loader: let caching firmware piggyback on loading firmware") Signed-off-by: Zhen Lei Acked-by: Luis Chamberlain --- drivers/base/firmware_loader/main.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 4fdb8219cd08..2f267b8d2fd9 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -165,7 +165,7 @@ static inline int fw_state_wait(struct fw_priv *fw_priv) return __fw_state_wait_common(fw_priv, MAX_SCHEDULE_TIMEOUT); } -static int fw_cache_piggyback_on_request(const char *name); +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv); static struct fw_priv *__allocate_fw_priv(const char *fw_name, struct firmware_cache *fwc, @@ -707,10 +707,8 @@ int assign_fw(struct firmware *fw, struct device *device) * on request firmware. */ if (!(fw_priv->opt_flags & FW_OPT_NOCACHE) && - fw_priv->fwc->state == FW_LOADER_START_CACHE) { - if (fw_cache_piggyback_on_request(fw_priv->fw_name)) - kref_get(&fw_priv->ref); - } + fw_priv->fwc->state == FW_LOADER_START_CACHE) + fw_cache_piggyback_on_request(fw_priv); /* pass the pages buffer to driver at the last minute */ fw_set_page_data(fw_priv, fw); @@ -1257,11 +1255,11 @@ static int __fw_entry_found(const char *name) return 0; } -static int fw_cache_piggyback_on_request(const char *name) +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv) { - struct firmware_cache *fwc = &fw_cache; + const char *name = fw_priv->fw_name; + struct firmware_cache *fwc = fw_priv->fwc; struct fw_cache_entry *fce; - int ret = 0; spin_lock(&fwc->name_lock); if (__fw_entry_found(name)) @@ -1269,13 +1267,12 @@ static int fw_cache_piggyback_on_request(const char *name) fce = alloc_fw_cache_entry(name); if (fce) { - ret = 1; list_add(&fce->list, &fwc->fw_names); + kref_get(&fw_priv->ref); pr_debug("%s: fw: %s\n", __func__, name); } found: spin_unlock(&fwc->name_lock); - return ret; } static void free_fw_cache_entry(struct fw_cache_entry *fce) @@ -1506,9 +1503,8 @@ static inline void unregister_fw_pm_ops(void) unregister_pm_notifier(&fw_cache.pm_notify); } #else -static int fw_cache_piggyback_on_request(const char *name) +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv) { - return 0; } static inline int register_fw_pm_ops(void) { -- 2.25.1