In the Linux kernel, a vulnerability has been discovered and resolved within the handling of inner maps in map arrays and map htabs when working with the Berkeley Packet Filter (BPF) subsystem. Improper de-allocation of inner maps after updating or deleting operations in the map led to potential use-after-free issues that may have compromised the system's stability and security.

The vulnerability was assigned identifier CVE-2023-52447 by the Common Vulnerabilities and Exposures (CVE) project. This article will discuss the details of the vulnerability, share the code snippet where the fix was applied, and provide links to relevant references.

Exploit Details

During the update or removal of an inner map, the related map might still be accessed by non-sleepable programs or sleepable programs. In such cases, when the last reference counter for an inner map is released, the map should be freed using the appropriate .map_free() callback function.

However, the bpf_map_fd_put_ptr() function called bpf_map_put() to decrease the map reference counter directly, which, in turn, led to the freeing of the inner map by the ops->map_free() function in a kworker (kernel-based worker thread) in most cases. Additionally, the majority of these .map_free() callbacks lacked the necessary synchronization to ensure that all active BPF programs completed their operations before allowing the actual memory deallocation, which resulted in a use-after-free scenario.

The Fix

To address this vulnerability, the Linux kernel developers introduced a new function, bpf_map_free_deferred(), which defers the inner map's freeing process until after the elapse of both one RCU (Read-Copy-Prepare) grace period and one task trace RCU grace period after the inner map had been removed from the outer map.

Here is the relevant code snippet where this fix was applied

static void bpf_map_free_deferred(struct bpf_map *map)
{
    if (map->inner_map_meta) {
        bpf_map_area_free(map->inner_map_meta);
        bpf_map_area_free(map);
    } else {
        call_rcu(&map->rcu, bpf_map_rcu_free);
    }
}

With this fix, the bpf_map_free_deferred() function is invoked when releasing the last reference counter of a BPF map. This ensures that proper synchronization is in place and prevents potential use-after-free problems.

For a more in-depth understanding of the vulnerability and the fix, see the following references

1. Linux Kernel Git Commit: bpf: Defer the free of inner map when necessary
2. BPF and its Application to Linux Networking
3. Common Vulnerabilities and Exposures (CVE) Project

In conclusion, the Linux kernel's vulnerability CVE-2023-52447 was discovered and resolved, effectively addressing a use-after-free issue within the handling of inner maps in map arrays and map htabs for the BPF subsystem. The introduction of the bpf_map_free_deferred() function ensures that proper synchronization is maintained and the inner maps are correctly deallocated, enhancing the overall stability and security of the Linux kernel.

Timeline

Published on: 02/22/2024 17:15:08 UTC
Last modified on: 03/14/2024 19:46:43 UTC