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 &amp; runqslower from bcc, for<br /> example, which make use of this tracepoint. Rough call sequence goes like:<br /> <br /> rq_lock(rq) -&gt; -------------------------+<br /> trace_sched_switch() -&gt; |<br /> bpf_prog_xyz() -&gt; +-&gt; deadlock<br /> selinux_lockdown() -&gt; |<br /> audit_log_end() -&gt; |<br /> wake_up_interruptible() -&gt; |<br /> try_to_wake_up() -&gt; |<br /> rq_lock(rq) --------------+<br /> <br /> What&amp;#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&amp;#39;t match with the &amp;#39;current&amp;#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 &amp;#39;current&amp;#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 &amp;#39;tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }&amp;#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-&gt;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&amp;#39;re moving this out of the BPF helper&amp;#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---

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:*:*:*:*:*:*