From: Thomas Gleixner <tglx@linutronix.de>
To: Jinjie Ruan <ruanjinjie@huawei.com>,
linux-kernel@vger.kernel.org,
"Peter Zijlstra (Intel)" <peterz@infradead.org>,
Christophe Leroy <christophe.leroy@csgroup.eu>,
Josh Poimboeuf <jpoimboe@kernel.org>
Subject: Re: [PATCH] static_call: Fix a wild-memory-access bug in static_call_del_module()
Date: Tue, 03 Sep 2024 22:01:45 +0200 [thread overview]
Message-ID: <87y1487bh2.ffs@tglx> (raw)
In-Reply-To: <0f339f49-bb8d-e28d-c9d6-8f16bd62995d@huawei.com>
On Mon, Sep 02 2024 at 20:01, Jinjie Ruan wrote:
> On 2023/9/15 16:21, Jinjie Ruan wrote:
>>
>> diff --git a/kernel/static_call_inline.c b/kernel/static_call_inline.c
>> index 639397b5491c..e7aa70d33530 100644
>> --- a/kernel/static_call_inline.c
>> +++ b/kernel/static_call_inline.c
>> @@ -256,8 +256,10 @@ static int __static_call_init(struct module *mod,
>> }
>>
>> site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
>> - if (!site_mod)
>> + if (!site_mod) {
>> + key->mods = NULL;
>> return -ENOMEM;
You fail to explain what setting key->mods to NULL prevents and why the
same problem does not happen when the kzalloc() five lines further down
fails.
Actually if you read the comment below carefully then you might find the
reason why the current code explodes and you might figure out why you
can't set the pointer to NULL.
>> + }
>>
>> /*
>> * When the key has a direct sites pointer, extract
>> @@ -422,7 +424,7 @@ static void static_call_del_module(struct module *mod)
>> ;
>>
>> if (!site_mod)
>> - continue;
>> + break;
Now why does this "fix" things?
The unmodified kernel crashes dereferencing key->mods. That means there
is garbage in key->mods. But that garbage is not garbage:
struct static_call_key {
void *func;
union {
/* bit 0: 0 = mods, 1 = sites */
unsigned long type;
struct static_call_mod *mods;
struct static_call_site *sites;
};
};
key->mods is actually key->sites, which holds the static call sites of
the key. It has bit 0 set.
As that code does not expect anything else than a valid static_call_mod
pointer it dereferences it unconditionally and crashes. See?
So why can't you set the pointer to NULL?
If that key is builtin and has actual builtin usage sites, then you
destroy the key. If the memory allocation fail was temporary then a
subsequent update of that static call will find no call site and the
kernel happily invokes the previous function.
Now that the root cause is properly analyzed, the proper fix is
obvious. See uncomplied below.
It does not need to do anything vs. the other kzalloc() fail because
that is harmless. The key has key->mods set, but key->mods->mod and
key->mods->next are both NULL in that case. So the inner loop breaks out
and continues to the next site which has the uninitialized one. If all
keys were already converted to mods _before_ this fail then the loop
simply iterates further, but will nowhere find a site_mod->mod == mod.
Thanks,
tglx
---
--- a/kernel/static_call_inline.c
+++ b/kernel/static_call_inline.c
@@ -411,6 +411,17 @@ static void static_call_del_module(struc
for (site = start; site < stop; site++) {
key = static_call_key(site);
+
+ /*
+ * If the key was not updated due to a memory allocation
+ * failure in __static_call_init() then treating key::sites
+ * as key::mods in the code below would cause random memory
+ * access and #GP. In that case all subsequent sites have
+ * not been touched either, so stop iterating.
+ */
+ if (static_call_key_sites(key))
+ break;
+
if (key == prev_key)
continue;
next prev parent reply other threads:[~2024-09-03 20:01 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-15 8:21 [PATCH] static_call: Fix a wild-memory-access bug in static_call_del_module() Jinjie Ruan
2023-09-15 9:01 ` Peter Zijlstra
2024-09-02 12:01 ` Jinjie Ruan
2024-09-02 12:06 ` Christophe Leroy
2024-09-02 12:07 ` Jinjie Ruan
2024-09-02 12:14 ` Christophe Leroy
2024-09-03 20:01 ` Thomas Gleixner [this message]
2024-09-03 22:58 ` [PATCH] static_call: Handle module init failure correctly " Thomas Gleixner
2024-09-04 3:32 ` Jinjie Ruan
2024-09-04 7:08 ` Thomas Gleixner
2024-09-04 8:00 ` Thomas Gleixner
2024-09-04 8:17 ` Peter Zijlstra
2024-09-04 9:08 ` [PATCH] static_call: Replace pointless WARN_ON() in static_call_module_notify() Thomas Gleixner
2024-09-06 14:41 ` [tip: locking/urgent] " tip-bot2 for Thomas Gleixner
2024-09-04 8:03 ` [PATCH] static_call: Handle module init failure correctly in static_call_del_module() Jinjie Ruan
2024-09-04 8:51 ` Thomas Gleixner
2024-09-04 9:50 ` Jinjie Ruan
2024-09-05 3:34 ` Jinjie Ruan
2024-09-05 9:44 ` Thomas Gleixner
2024-09-06 23:24 ` Luis Chamberlain
2024-09-19 9:53 ` Luis Chamberlain
2024-09-24 7:22 ` Mike Rapoport
2024-11-08 8:12 ` Christophe Leroy
2024-11-08 15:49 ` Luis Chamberlain
2024-11-08 16:09 ` Daniel Gomez
2024-11-08 16:22 ` Daniel Gomez
2024-09-04 9:09 ` [PATCH v2] " Thomas Gleixner
2024-09-04 9:19 ` Jinjie Ruan
2024-09-06 14:41 ` [tip: locking/urgent] " tip-bot2 for Thomas Gleixner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87y1487bh2.ffs@tglx \
--to=tglx@linutronix.de \
--cc=christophe.leroy@csgroup.eu \
--cc=jpoimboe@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=ruanjinjie@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox