We have learnt double fetch vulnerabilities and how to exploit them in Pawnyable. In this paper, researchers present a systematic study of double fetch situations, bugs and vulnerabilities in Linux kernel.
The double fetch situation in kernel could be demonstrated as below:
1. Basic Information
|How Double-Fetch Situations turn into DoubleFetch Vulnerabilities: A Study of Double Fetches in the Linux Kernel
|Pengfei Wang, Jens Krinke, Kai Lu, Gen Li, Steve Dodier-Lazaro
|National University of Defense Technology & University College London
|2017 USENIX Security Symposium (26th)
2. Overview of Contributions
As the authors say, they present the first static systematic detection against potential double-fetch vulnerabilities in Linux kernel. Using a pattern-based analysis based on Coccinelle, they found 90 double-fetch situations in Linux kernel. They applied the refined patterns to Linux, FreeBSD and Android kernels, and found 6 double-fetch bugs, 3 of which are exploitable:
This paper also provides solution for anticipating double-fetch bugs and vulnerabilities, as well as an automatic patch solution for detected double-fetch bugs.
Because lots of double-fetch situations are in vairous drivers, previous dynamic approaches were unable to detect without access to the corresponding hardware.
3. Two-Phase Detection Process
The study is divided in two phases.
In the first phase, researchers analyse the Linux kernel source code using Coccinelle with a basic double-fetch pattern identifying functions which contain more than one invocation of a transfer function. They analyse the results manually to categorize the scenarios where there is a double fetch situation and when the situation is prone to be a bug or even vulnerability.
In the second phase, researchers generate more precise patterns based on the knowledge gained from the first phase, and conduct analysis on Linux, FreeBSD and Android.
The whole process is shown below:
3.1 Basic Pattern Matching Analysis
As we said, researchers use a simple pattern to matches situations in which a kernel function uses transfer functions to fetch data from the same user memory regin at least twice. For Linux the transfer functions are
copy_from_user() and other variants.
This pattern allows the destination and size of copy to be different, while the source of copy in user space must be the same one.
From the result we learn an interesting fact that 44% of Linux kernel source files are driver-related and 26% are related to non-x86 hardware architectures, which means that dynamic analysis for these parts of Linux kernel will be difficult because it is relatively hard to gather various devices and hardwares in different architectures.
3.2 Double Fetch Categorization
Based on the first analysis, researchers regard the data structures delivered between kernel and user space as messages, each of which consisting of a metadata header and a body. Then they categorize the double fetch situations into 3 categories:
- Type selection. If the message header is used for type selection and the header part of the second fetch would be used again, there could be a double-fecth bug or vulnerability.
- Size checking. The message header often records the data size. In a double-fetch situation, the message header is copied into kernel first to determine the message size, check the validity and allocate memory with the specific size. Then a second fetch follows. If the size of copy operation is determined by the message header from the second fetch, there will be something like OOB read/write.
- Shallow copy. Such a situation happens when a copied data buffer contains one or more pointers to another buffer in user space. Sometimes kernel code conducts recursive deep copy to transfer not only the data structure itself but also the related structures to which the inner pointers point.
3.3 Reﬁned Pattern Matching Analysis
Researchers added 5 more rules in the second phase to improve precision and discover edge cases:
- No pointer change. This rule is to make sure the source copy does not change between two fetches.
- Pointer aliasing. This rule is to identify different aliases pointing to the same source area.
- Explicit type conversion. This rule is to include cases where explicit type casting occurs but the source address is not changed.
- Combination of element fetch and pointer fetch. This rule is to identify different formats of fetch operations against the same source area.
- Loop involvement. This rule is to exclude the case where fetches in adjacent loops are regarded as a double-fetch situation.
The whole process for second phase is shown as below:
Researchers found 90 double-fetch situations in source code of Linux kernel v4.5, 6% of which are true bugs and 63% are located in drivers:
The refined analysis shows that there are 3 bugs in Android 6.0.1 (2 shared with Linux kernel, 1 unique) and no such bugs in FreeBSD:
This paper serves as a great resource for us to learn about double-fetch vulnerabilities. The main method used in this paper is pattern match analysis against source code, which is very intuitive.