CVE-2022-49236
Severity CVSS v4.0:
Pending analysis
Type:
CWE-416
Use After Free
Publication date:
26/02/2025
Last modified:
25/03/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
bpf: Fix UAF due to race between btf_try_get_module and load_module<br />
<br />
While working on code to populate kfunc BTF ID sets for module BTF from<br />
its initcall, I noticed that by the time the initcall is invoked, the<br />
module BTF can already be seen by userspace (and the BPF verifier). The<br />
existing btf_try_get_module calls try_module_get which only fails if<br />
mod->state == MODULE_STATE_GOING, i.e. it can increment module reference<br />
when module initcall is happening in parallel.<br />
<br />
Currently, BTF parsing happens from MODULE_STATE_COMING notifier<br />
callback. At this point, the module initcalls have not been invoked.<br />
The notifier callback parses and prepares the module BTF, allocates an<br />
ID, which publishes it to userspace, and then adds it to the btf_modules<br />
list allowing the kernel to invoke btf_try_get_module for the BTF.<br />
<br />
However, at this point, the module has not been fully initialized (i.e.<br />
its initcalls have not finished). The code in module.c can still fail<br />
and free the module, without caring for other users. However, nothing<br />
stops btf_try_get_module from succeeding between the state transition<br />
from MODULE_STATE_COMING to MODULE_STATE_LIVE.<br />
<br />
This leads to a use-after-free issue when BPF program loads<br />
successfully in the state transition, load_module&#39;s do_init_module call<br />
fails and frees the module, and BPF program fd on close calls module_put<br />
for the freed module. Future patch has test case to verify we don&#39;t<br />
regress in this area in future.<br />
<br />
There are multiple points after prepare_coming_module (in load_module)<br />
where failure can occur and module loading can return error. We<br />
illustrate and test for the race using the last point where it can<br />
practically occur (in module __init function).<br />
<br />
An illustration of the race:<br />
<br />
CPU 0 CPU 1<br />
load_module<br />
notifier_call(MODULE_STATE_COMING)<br />
btf_parse_module<br />
btf_alloc_id // Published to userspace<br />
list_add(&btf_mod->list, btf_modules)<br />
mod->init(...)<br />
... ^<br />
bpf_check |<br />
check_pseudo_btf_id |<br />
btf_try_get_module |<br />
returns true | ...<br />
... | module __init in progress<br />
return prog_fd | ...<br />
... V<br />
if (ret
Impact
Base Score 3.x
7.80
Severity 3.x
HIGH
Vulnerable products and versions
CPE | From | Up to |
---|---|---|
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.12 (including) | 5.15.33 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.16 (including) | 5.16.19 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.17 (including) | 5.17.2 (excluding) |
To consult the complete list of CPE names with products and versions, see this page