
Educational case study and exploit development walkthrough for CVE-2022-0185, a Linux kernel heap-based buffer overflow enabling local privilege escalation. Includes POC, QEMU debugging, and Ubuntu exploit with detailed technical analysis.
This case study is a result of an assignment of ECE 9069: Introduction to Hacking : https://whisperlab.org/introduction-to-hacking/
CVE-2022-0185 is a heap-based buffer overflow flaw was found in the way the legacy_parse_param function in the Filesystem Context functionality of the Linux kernel verified the supplied parameters length. An unprivileged (in case of unprivileged user namespaces enabled, otherwise needs namespaced CAP_SYS_ADMIN privilege) local user able to open a filesystem that does not support the Filesystem Context API (and thus fallbacks to legacy handling) could use this flaw to escalate their privileges on the system. [1]
After this vulnerability was reported, patch has been released to fix this bug:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=722d94847de2
https://ubuntu.com/security/CVE-2022-0185#impact-score
There is a detailed writeup from the explorer: https://www.hackthebox.com/blog/CVE-2022-0185:_A_case_study
In this repository I will explain the basic steps and related background information to reproduce this vulnerability. Also, if there are anything you feel unclear, you can send me an exmail:[email protected] I am rather happy to answer the question.
The CVE-2022-0185 vulnerability was published on 02/11/2022, with a CVSS 3.x base score of 8.4 (High).[1] This vulnerability is a heap-based buffer overflow, caused by an unsigned integer underflow.
The vulnerability was introduced in the Linux v5.1 kernel, affecting all Linux distributions with kernel versions higher than 5.1. For example, Ubuntu 20.04 LTS (focal) was vulnerable to this bug. However, a patch was released and is available since version 5.4.0-96.109 .[3]
Exploiting this vulnerability allows an unprivileged local user to escalate their privileges on the system, potentially compromising the entire system.[1] [2] Here is a detailed analysis of the CVSS score: Base Score: 8.4, indicating a significant security risk that requires immediate attention. Impact Score: 5.9, suggesting substantial potential damage if exploited. The high confidentiality, integrity, and availability values contribute to this score. Exploitability Score: 2.5, suggesting relatively high exploitability. The local Attack Vector, high integrity , and high availability values contribute to this score.
Table 1.1 and Table 1.2 provide more information on these scores and their components.
| CVSS v3.1 Severity | Value |
|---|---|
| Base Score | 8.4 HIGH |
| Impact Score | 5.9 |
| Exploitability Score | 2.5 |
Table 1.1 CVSS Severity Scores[1]
| CVSS v3.1 Metrics | Value |
|---|---|
| Attack Vector (AV) | Local |
| Privileges Required (PR) | None |
| User Interaction (UI) | None |
| Confidentiality (C) | High |
| Integrity (I) | High |
| Availability (A) | High |
Table 1.2 CVSS Vector[1]
There are two integer types in modern computers, signed and unsigned. The representation of signed number generally involves an operation called two’s complement.[4] “Two’s complement uses the binary digit with the greatest place value as the sign to indicate whether the binary number is positive or negative”[4]
Introducing the two’s complement will convert the calculation of subtraction into addition therefore simplify the design and implementation of CPU. The generate of two’s complement of an integer involves three steps:[4]
Fig 2.1.1.1 shows the converting process in a diagram with an actual example of converting “-6” to its two’s complement format.

Fig 2.1.1.2 Addition Using Two’s Complement
Figure 2.1.1.2 shows the process of adding the two's complement of '-6' to '+6'. This demonstrates how using two's complement allows addition to be used as a substitute for subtraction.

Fig 2.1.1.2 Addition Using Two’s Complement
From Section 2.1.1, we already understand what two's complement is. Now, let's take a look at the scenario of unsigned number underflow in computers. In modern computers, when using unsigned numbers, the most significant bit is not treated as a signed bit; instead, it is part of the unsigned number itself. This situation means that when performing subtraction with an unsigned number, we must be cautious, as it may lead to a condition known as unsigned number underflow.[5]
Fig 2.1.2.1 illustrates the situation of subtracting 6 from 5 for an 8-bit unsigned number. The final result is 255 due to the unsigned number wrapping around. When this underflow occurs in a conditional statement, it has the potential to disrupt the functionality of the statement.

Fig 2.1.2.1 Unsigned Number Underflow
In the Linux kernel, the Slab Allocator is a memory management mechanism used for efficient allocation and deallocation of small chunks of memory. It provides performance by maintaining several caches of Slabs, each containing fixed-size memory blocks. Typically, kmalloc-32 allocates 32 bytes of memory, it is a kmalloc-32 slab, whereas, kmalloc-4k allocate 4096 bytes of memory, it is a kmalloc-4k slab.[6]
Furthermore, slab allocation in the Linux kernel typically involves allocating memory from a contiguous address space within the kernel’s heap memory region. This contiguous address is managed by the kernel and is used to allocate memory for various kernel objects and data structures. Fig 2.2.1.1 shows the layout of slabs in LInux kernel memory.

Fig 2.2.1.1 Slab Allocator in Linux [7] (This author of this figure is https://leviathan.vip/)
If you want to reproduce the process with a self compiled linux kernel please read the following markdown files to get the background information:
Note:
All the markdown files as well as the code and script are in different folders of this repository, each folder comes with its own markdown file, read it before trying to do something!
In section 2.1, we explained how unsigned underflow works. Now, we will examine the kernel function that contains this vulnerability.