A file system is an organization of data and metadata on a storage device. It controls how the data is stored and retrieved, and its most important function is to manage user data. Finding a vulnerability in this is catastrophic!
The Linux kernel's seq_file interface produces virtual files. Each record must fit into the buffer size. When the node grows too big, the size is doubled. This size value is of type of size_t, which is a 64-bit unsigned integer.
This size value is passed to multiple functions that use an int, which is a signed 32-bit. This results in an insecure truncation and a insecure signed issue. This can lead to memory corrupt bugs when allocated the right buffer size for the information for the file node.
In order to trigger this, an attacker needs to create, mount and delete a directory structure whose path is larger than 1GB. Then, when looking at /proc/self/mountinfo, the code path deals with the insecure integer truncation.
The actual issue is that the function dentry_path expects a 32 bit signed integer. However, the truncation results in a negative value for the length of the buffer. When this buffer offset gets used, it writes the string //deleted to a specific offset.
When an attacker controls the system as well as they do on Linux, this primitive is enough to get things started to get deeper primitives. In order to exploit this, the authors created a small eBPF program that has been validated within the kernel. Once this has been validated, the vulnerability is triggered that overwrites instructions of the eBPF code, breaking the security guarantee. This is done multiple times.
This overwritten instruction transforms into an out of bounds information disclosure and a limited write. Using the out of bounds write, they turn the exploit into a full on arbitrary read/arbitrary write by using
ntf and map_push_elem.
It's truly amazing how such a simple bug (integer truncation) turns into a full Linux kernel privilege escalation. To me, this integer truncation issue is more likely in many more spots. Most of the time, compilers do not call this out. Great find and great research!