CVE-2021-47128
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
15/03/2024
Last modified:
13/03/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
bpf, lockdown, audit: Fix buggy SELinux lockdown permission checks<br />
<br />
Commit 59438b46471a ("security,lockdown,selinux: implement SELinux lockdown")<br />
added an implementation of the locked_down LSM hook to SELinux, with the aim<br />
to restrict which domains are allowed to perform operations that would breach<br />
lockdown. This is indirectly also getting audit subsystem involved to report<br />
events. The latter is problematic, as reported by Ondrej and Serhei, since it<br />
can bring down the whole system via audit:<br />
<br />
1) The audit events that are triggered due to calls to security_locked_down()<br />
can OOM kill a machine, see below details [0].<br />
<br />
2) It also seems to be causing a deadlock via avc_has_perm()/slow_avc_audit()<br />
when trying to wake up kauditd, for example, when using trace_sched_switch()<br />
tracepoint, see details in [1]. Triggering this was not via some hypothetical<br />
corner case, but with existing tools like runqlat & runqslower from bcc, for<br />
example, which make use of this tracepoint. Rough call sequence goes like:<br />
<br />
rq_lock(rq) -> -------------------------+<br />
trace_sched_switch() -> |<br />
bpf_prog_xyz() -> +-> deadlock<br />
selinux_lockdown() -> |<br />
audit_log_end() -> |<br />
wake_up_interruptible() -> |<br />
try_to_wake_up() -> |<br />
rq_lock(rq) --------------+<br />
<br />
What&#39;s worse is that the intention of 59438b46471a to further restrict lockdown<br />
settings for specific applications in respect to the global lockdown policy is<br />
completely broken for BPF. The SELinux policy rule for the current lockdown check<br />
looks something like this:<br />
<br />
allow : lockdown { };<br />
<br />
However, this doesn&#39;t match with the &#39;current&#39; task where the security_locked_down()<br />
is executed, example: httpd does a syscall. There is a tracing program attached<br />
to the syscall which triggers a BPF program to run, which ends up doing a<br />
bpf_probe_read_kernel{,_str}() helper call. The selinux_lockdown() hook does<br />
the permission check against &#39;current&#39;, that is, httpd in this example. httpd<br />
has literally zero relation to this tracing program, and it would be nonsensical<br />
having to write an SELinux policy rule against httpd to let the tracing helper<br />
pass. The policy in this case needs to be against the entity that is installing<br />
the BPF program. For example, if bpftrace would generate a histogram of syscall<br />
counts by user space application:<br />
<br />
bpftrace -e &#39;tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }&#39;<br />
<br />
bpftrace would then go and generate a BPF program from this internally. One way<br />
of doing it [for the sake of the example] could be to call bpf_get_current_task()<br />
helper and then access current->comm via one of bpf_probe_read_kernel{,_str}()<br />
helpers. So the program itself has nothing to do with httpd or any other random<br />
app doing a syscall here. The BPF program _explicitly initiated_ the lockdown<br />
check. The allow/deny policy belongs in the context of bpftrace: meaning, you<br />
want to grant bpftrace access to use these helpers, but other tracers on the<br />
system like my_random_tracer _not_.<br />
<br />
Therefore fix all three issues at the same time by taking a completely different<br />
approach for the security_locked_down() hook, that is, move the check into the<br />
program verification phase where we actually retrieve the BPF func proto. This<br />
also reliably gets the task (current) that is trying to install the BPF tracing<br />
program, e.g. bpftrace/bcc/perf/systemtap/etc, and it also fixes the OOM since<br />
we&#39;re moving this out of the BPF helper&#39;s fast-path which can be called several<br />
millions of times per second.<br />
<br />
The check is then also in line with other security_locked_down() hooks in the<br />
system where the enforcement is performed at open/load time, for example,<br />
open_kcore() for /proc/kcore access or module_sig_check() for module signatures<br />
just to pick f<br />
---truncated---
Impact
Base Score 3.x
5.50
Severity 3.x
MEDIUM
Vulnerable products and versions
CPE | From | Up to |
---|---|---|
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.6 (including) | 5.10.43 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.11 (including) | 5.12.10 (excluding) |
cpe:2.3:o:linux:linux_kernel:5.13:rc1:*:*:*:*:*:* | ||
cpe:2.3:o:linux:linux_kernel:5.13:rc2:*:*:*:*:*:* | ||
cpe:2.3:o:linux:linux_kernel:5.13:rc3:*:*:*:*:*:* | ||
cpe:2.3:o:linux:linux_kernel:5.13:rc4:*:*:*:*:*:* |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/acc43fc6cf0d50612193813c5906a1ab9d433e1e
- https://git.kernel.org/stable/c/ff40e51043af63715ab413995ff46996ecf9583f
- https://git.kernel.org/stable/c/ff5039ec75c83d2ed5b781dc7733420ee8c985fc
- https://git.kernel.org/stable/c/acc43fc6cf0d50612193813c5906a1ab9d433e1e
- https://git.kernel.org/stable/c/ff40e51043af63715ab413995ff46996ecf9583f
- https://git.kernel.org/stable/c/ff5039ec75c83d2ed5b781dc7733420ee8c985fc