Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp764031pxb; Mon, 16 Aug 2021 17:38:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw0jw2X8Qzqece+RQYNj7vYcRbXK21sCUL9/oXBZa3cEkmmW+kWNDDuUcsoCkyiRRGrUXlk X-Received: by 2002:a05:6402:42ce:: with SMTP id i14mr952390edc.345.1629160684124; Mon, 16 Aug 2021 17:38:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629160684; cv=none; d=google.com; s=arc-20160816; b=wHx7Wbid0kDX+Q5Nm5zOtZNZ39SsVyt6oxR8qScQGwP0e/FWyZw7ImWCWJljZlj/J2 YbkVXBW3RJyQ48nINV+M1oLgplLsWD9dAWL25lFMXvnCFOd2IvF83L0AZ4rpvK8PHML7 1LJmHy1vaA+SSEPeQ5xQvMGCU19i8DuhSr+QeJ/43kF4vVk8dFW7d3b+1IMwU1NfX2cv pb3sD8nxvKsruDNFAGgf5Aw4whrrjAw78T8PI65aKxIxgEXbERTZ61fai0p6DaVdsjor 2urM3cXAwCSAzs4XDW/uM9AwPd3OV/28fwRzDvfkNPNTX2eVeygmiGXTe80Zt3pQKnaa vWqw== 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 :dkim-signature; bh=MTXh5XaNUXCwR8WW37D/bsN7TQ2ZqC7dGhBeYKCkHxQ=; b=uAN0UJTqRlMz3HBkV8LzRttenWlMV6XSOZfYHnSayB0rX3L1IftBa2DvZ37DVw9tUn TZncNupkutgep9mj1WQ4XGfYTDm08r1iWsxyx2uPA3XGGiIYmljlJ8sLHOoBjhXmtRJF RG4vBGvTkvNrj1EQT8ewTS8KpbA05WuaEdTBjPWqyhpP0Xhh8ipE5/vZrbJnvNJJnlww TPiiXNi4wEFkZRf9/CZnKP7T/eyH9hQTNFl+1czJ11wNqVIn+tyM23xPbKLHEP5qF7sB Q7NS6nwVq/zvi1CxxHSL2aAHb9JoKk6mcDk7BPNimQj9WnE7a9UhE2tq8BFDkIJe1XXU 3zGQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=FzWdUVsj; 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=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r9si482781eje.250.2021.08.16.17.37.41; Mon, 16 Aug 2021 17:38:04 -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=@kernel.org header.s=k20201202 header.b=FzWdUVsj; 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=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236365AbhHQAgh (ORCPT + 99 others); Mon, 16 Aug 2021 20:36:37 -0400 Received: from mail.kernel.org ([198.145.29.99]:35224 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235819AbhHQAgV (ORCPT ); Mon, 16 Aug 2021 20:36:21 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id E66DF60FA0; Tue, 17 Aug 2021 00:35:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1629160548; bh=3LtPGqVFszrceez7FmDhpht4gkC4FP08zQUorIghOx0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FzWdUVsjRhdBar22kP5ualhaYvIq6OhpUPLnayQkrJIACXW436cfS4l/X3YcTKy18 81jInayEfnsQxW73jev6pUY19cWpcmiNIz5vKfM31FgxPCZYXpaqM7xcNYtVIw++bn +MTaiPDOc1pFW26tdhjY2jPxR80C2sN5iYlEKorhO4R9yr081RXwEdYaylQ5adQLkC LY3xAim53Bsi+FBBFYaXOIpi8uaMypvdD4ZHcQtt6/9tOpyEt2f2TPgRtOy71uQOiy 8oUfMVBizR6m0Aafccpir9O6YeLBIy4TeMGFBOqvQuEoDuwwL6e5DC4OJS+k4xzRR0 jLsdRcgAvUEog== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Kefeng Wang , Hannes Frederic Sowa , Daniel Borkmann , "David S . Miller" , Eric Dumazet , Minmin chen , Sasha Levin Subject: [PATCH AUTOSEL 5.13 08/12] once: Fix panic when module unload Date: Mon, 16 Aug 2021 20:35:32 -0400 Message-Id: <20210817003536.83063-8-sashal@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210817003536.83063-1-sashal@kernel.org> References: <20210817003536.83063-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kefeng Wang [ Upstream commit 1027b96ec9d34f9abab69bc1a4dc5b1ad8ab1349 ] DO_ONCE DEFINE_STATIC_KEY_TRUE(___once_key); __do_once_done once_disable_jump(once_key); INIT_WORK(&w->work, once_deferred); struct once_work *w; w->key = key; schedule_work(&w->work); module unload //*the key is destroy* process_one_work once_deferred BUG_ON(!static_key_enabled(work->key)); static_key_count((struct static_key *)x) //*access key, crash* When module uses DO_ONCE mechanism, it could crash due to the above concurrency problem, we could reproduce it with link[1]. Fix it by add/put module refcount in the once work process. [1] https://lore.kernel.org/netdev/eaa6c371-465e-57eb-6be9-f4b16b9d7cbf@huawei.com/ Cc: Hannes Frederic Sowa Cc: Daniel Borkmann Cc: David S. Miller Cc: Eric Dumazet Reported-by: Minmin chen Signed-off-by: Kefeng Wang Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- include/linux/once.h | 4 ++-- lib/once.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/once.h b/include/linux/once.h index 9225ee6d96c7..ae6f4eb41cbe 100644 --- a/include/linux/once.h +++ b/include/linux/once.h @@ -7,7 +7,7 @@ bool __do_once_start(bool *done, unsigned long *flags); void __do_once_done(bool *done, struct static_key_true *once_key, - unsigned long *flags); + unsigned long *flags, struct module *mod); /* Call a function exactly once. The idea of DO_ONCE() is to perform * a function call such as initialization of random seeds, etc, only @@ -46,7 +46,7 @@ void __do_once_done(bool *done, struct static_key_true *once_key, if (unlikely(___ret)) { \ func(__VA_ARGS__); \ __do_once_done(&___done, &___once_key, \ - &___flags); \ + &___flags, THIS_MODULE); \ } \ } \ ___ret; \ diff --git a/lib/once.c b/lib/once.c index 8b7d6235217e..59149bf3bfb4 100644 --- a/lib/once.c +++ b/lib/once.c @@ -3,10 +3,12 @@ #include #include #include +#include struct once_work { struct work_struct work; struct static_key_true *key; + struct module *module; }; static void once_deferred(struct work_struct *w) @@ -16,10 +18,11 @@ static void once_deferred(struct work_struct *w) work = container_of(w, struct once_work, work); BUG_ON(!static_key_enabled(work->key)); static_branch_disable(work->key); + module_put(work->module); kfree(work); } -static void once_disable_jump(struct static_key_true *key) +static void once_disable_jump(struct static_key_true *key, struct module *mod) { struct once_work *w; @@ -29,6 +32,8 @@ static void once_disable_jump(struct static_key_true *key) INIT_WORK(&w->work, once_deferred); w->key = key; + w->module = mod; + __module_get(mod); schedule_work(&w->work); } @@ -53,11 +58,11 @@ bool __do_once_start(bool *done, unsigned long *flags) EXPORT_SYMBOL(__do_once_start); void __do_once_done(bool *done, struct static_key_true *once_key, - unsigned long *flags) + unsigned long *flags, struct module *mod) __releases(once_lock) { *done = true; spin_unlock_irqrestore(&once_lock, *flags); - once_disable_jump(once_key); + once_disable_jump(once_key, mod); } EXPORT_SYMBOL(__do_once_done); -- 2.30.2