CVE-2021-47128 in Linuxinfo

Summary

by MITRE • 03/15/2024

In the Linux kernel, the following vulnerability has been resolved:

bpf, lockdown, audit: Fix buggy SELinux lockdown permission checks

Commit 59438b46471a ("security,lockdown,selinux: implement SELinux lockdown") added an implementation of the locked_down LSM hook to SELinux, with the aim to restrict which domains are allowed to perform operations that would breach lockdown. This is indirectly also getting audit subsystem involved to report events. The latter is problematic, as reported by Ondrej and Serhei, since it can bring down the whole system via audit:

1) The audit events that are triggered due to calls to security_locked_down() can OOM kill a machine, see below details [0].

2) It also seems to be causing a deadlock via avc_has_perm()/slow_avc_audit() when trying to wake up kauditd, for example, when using trace_sched_switch() tracepoint, see details in [1]. Triggering this was not via some hypothetical
corner case, but with existing tools like runqlat & runqslower from bcc, for example, which make use of this tracepoint. Rough call sequence goes like:

rq_lock(rq) -> -------------------------+ trace_sched_switch() -> | bpf_prog_xyz() -> +-> deadlock selinux_lockdown() -> | audit_log_end() -> | wake_up_interruptible() -> | try_to_wake_up() -> | rq_lock(rq) --------------+

What's worse is that the intention of 59438b46471a to further restrict lockdown settings for specific applications in respect to the global lockdown policy is completely broken for BPF. The SELinux policy rule for the current lockdown check looks something like this:

allow : lockdown { };

However, this doesn't match with the 'current' task where the security_locked_down() is executed, example: httpd does a syscall. There is a tracing program attached to the syscall which triggers a BPF program to run, which ends up doing a bpf_probe_read_kernel{,_str}() helper call. The selinux_lockdown() hook does
the permission check against 'current', that is, httpd in this example. httpd has literally zero relation to this tracing program, and it would be nonsensical having to write an SELinux policy rule against httpd to let the tracing helper pass. The policy in this case needs to be against the entity that is installing the BPF program. For example, if bpftrace would generate a histogram of syscall counts by user space application:

bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'

bpftrace would then go and generate a BPF program from this internally. One way of doing it [for the sake of the example] could be to call bpf_get_current_task()
helper and then access current->comm via one of bpf_probe_read_kernel{,_str}()
helpers. So the program itself has nothing to do with httpd or any other random app doing a syscall here. The BPF program _explicitly initiated_ the lockdown check. The allow/deny policy belongs in the context of bpftrace: meaning, you want to grant bpftrace access to use these helpers, but other tracers on the system like my_random_tracer _not_.

Therefore fix all three issues at the same time by taking a completely different approach for the security_locked_down() hook, that is, move the check into the program verification phase where we actually retrieve the BPF func proto. This also reliably gets the task (current) that is trying to install the BPF tracing program, e.g. bpftrace/bcc/perf/systemtap/etc, and it also fixes the OOM since we're moving this out of the BPF helper's fast-path which can be called several millions of times per second.

The check is then also in line with other security_locked_down() hooks in the system where the enforcement is performed at open/load time, for example, open_kcore() for /proc/kcore access or module_sig_check() for module signatures just to pick f ---truncated---

Once again VulDB remains the best source for vulnerability data.

Analysis

by VulDB Data Team • 03/13/2025

The vulnerability CVE-2021-47128 represents a critical flaw in the Linux kernel's security architecture, specifically within the interaction between the Berkeley Packet Filter (BPF) subsystem, SELinux lockdown mechanisms, and the audit subsystem. This issue stems from improper implementation of the locked_down LSM (Linux Security Module) hook within SELinux, creating a cascade of operational failures that can lead to system instability and potential denial of service conditions. The vulnerability was introduced in commit 59438b46471a which aimed to implement SELinux lockdown functionality but inadvertently created a fundamental flaw in how permission checks are performed during BPF program execution. The core technical problem manifests when BPF programs attempt to access kernel memory through helper functions like bpf_probe_read_kernel, triggering a chain of events that can cause system-wide deadlocks and out-of-memory conditions.

The operational impact of this vulnerability is severe and multifaceted, affecting system stability through both deadlock conditions and memory exhaustion scenarios. The audit subsystem becomes overwhelmed when security_locked_down() is called during BPF helper execution, leading to potential OOM (Out of Memory) conditions that can crash entire systems. Additionally, the deadlock occurs through a complex call sequence involving rq_lock, trace_sched_switch, bpf_prog_xyz, selinux_lockdown, audit_log_end, and wake_up_interruptible functions, creating a circular dependency that prevents system responsiveness. This issue is particularly dangerous because it affects widely-used tools like bcc's runqlat and runqslower tracepoints, which are legitimate debugging utilities that trigger the vulnerability path. The flaw also breaks the intended security model for SELinux lockdown, where the permission check is incorrectly performed against the wrong task context, making it impossible to properly enforce security policies for BPF programs.

The root cause of this vulnerability lies in the flawed implementation approach that attempts to perform lockdown checks during BPF helper execution rather than during program verification. The original implementation incorrectly applies SELinux policy rules against the 'current' task that initiated the syscall, rather than the entity that actually installed the BPF program, creating an absurd security model where httpd would need to be granted permissions to allow tracing programs to function. This violates fundamental security principles and creates a mismatch between the intended security policy and actual program execution context. The fix addresses this by moving the security_locked_down() check into the BPF program verification phase, where the correct task context (the program installer) can be properly identified and validated against appropriate security policies. This approach aligns with other kernel security mechanisms like open_kcore() and module_sig_check() which perform enforcement at load/open time rather than runtime, ensuring that security decisions are made in appropriate contexts. The solution also resolves the performance issues by removing the lockdown check from BPF helper fast paths, which can be invoked millions of times per second, thereby preventing both the OOM conditions and the deadlock scenarios.

This vulnerability demonstrates the critical importance of proper security model implementation in kernel subsystems and aligns with CWE-362 (Concurrent Execution using Shared Resource with Improper Synchronization) and CWE-707 (Improper Neutralization of Input During Web Page Generation) categories. The fix represents a significant improvement in kernel security architecture by ensuring that BPF program security checks occur at the appropriate time and in the correct context, preventing both the denial of service conditions and the fundamental policy enforcement failures. The mitigation approach follows ATT&CK framework concepts related to privilege escalation and defense evasion by ensuring that security controls are properly enforced rather than creating conditions that can be exploited to cause system instability. The resolution fundamentally improves the security posture by moving from runtime checks that can be abused to compile-time checks that properly enforce the intended security model, thereby protecting against both accidental and malicious exploitation of the BPF subsystem.

Reservation

03/04/2024

Disclosure

03/15/2024

Moderation

accepted

CPE

ready

EPSS

0.00176

KEV

no

Activities

very low

Sources

Want to stay up to date on a daily basis?

Enable the mail alert feature now!