Static Detection of Unsafe DMA Accesses in Device Drivers
Total Page:16
File Type:pdf, Size:1020Kb
Static Detection of Unsafe DMA Accesses in Device Drivers Jia-Ju Bai Tuo Li Kangjie Lu Shi-Min Hu Tsinghua University Tsinghua University University of Minnesota Tsinghua University Abstract devices, Direct Memory Access (DMA) is designed to reduce Direct Memory Access (DMA) is a popular mechanism CPU involvement for hardware I/O. The OS enables DMA for improving hardware I/O performance, and it has been by mapping hardware registers to an area of system memory, widely used by many existing device drivers. However, DMA which is called DMA buffer, and then the OS can directly accesses can be unsafe, from two aspects. First, without proper access the hardware registers by accessing the DMA buffer. synchronization of DMA buffers with hardware registers and Many existing device drivers have used DMA to improve CPU cache, the buffer data stored in CPU cache and hardware performance, but DMA accesses can be unsafe, even though registers can be inconsistent, which can cause unexpected IOMMU has been used to guarantee their accessed memory hardware behaviors. Second, a malfunctioning or untrusted addresses are valid. First, the driver should access the DMA hardware device can write bad data into system memory, buffer only when the buffer has been properly synchronized which can trigger security bugs (such as buffer overflow and with hardware registers and CPU cache. Otherwise, the ac- invalid-pointer access), if the driver uses the data without cessed data stored in hardware registers and CPU cache can correct validation. To detect unsafe DMA accesses, some be inconsistent, which can cause unexpected behaviors of the key challenges need to be solved. For example, because each hardware device. For short, we call such a problem as inconsis- DMA access is implemented as a regular variable access in tent DMA access. Second, considering that a hardware device the driver code, identifying DMA accesses is difficult. can be malfunctioning [27,55] or untrusted [28,53,65], it can In this paper, we propose a static-analysis approach named write bad data into DMA buffers, and thus the driver should SADA, to automatically and accurately detect unsafe DMA perform correct validation of the data from DMA buffers accesses in device drivers. SADA consists of three basic before using it. Otherwise, security bugs (such as buffer over- steps. First, SADA uses a field-based alias analysis to identify flow and invalid-pointer access) can be triggered at runtime. DMA accesses, according to the information of DMA-buffer For short, we call such a problem as unchecked DMA access. creation. Second, SADA uses a flow-sensitive and pattern- To mitigate the security risks from DMA accesses, several based analysis to check the safety of each DMA access, to recent works [45, 51, 52] perform driver fuzzing and have detect possible unsafe DMA accesses. Finally, SADA uses found some security bugs caused by the bad data from DMA an SMT solver to validate the code-path condition of each buffers. Specifically, they create a simulated device to gener- possible unsafe DMA access, to drop false positives. We have ate and mutate hardware inputs (including the data from DMA evaluated SADA on the driver code of Linux 5.6, and found buffers), and test whether the driver can correctly handle these 284 real unsafe DMA accesses. Among them, we highlight inputs. But they still have some limitations in detecting unsafe that 121 can trigger buffer-overflow bugs and 36 can trigger DMA accesses. First, they require associated simulated de- invalid-pointer accesses causing arbitrary read or write. We vices to actually run the tested drivers, and implementing such have reported these unsafe DMA accesses to Linux driver simulated devices often requires much manual work. Second, developers, and 105 of them have been confirmed. their code coverage is limited to generated test cases, causing that many real unsafe DMA accesses are missed. Finally, they 1 Introduction cannot detect inconsistent DMA accesses, because they do not consider the synchronization of DMA buffers. A modern operating system (OS) controls different kinds of Static analysis is effective in achieving high code cover- peripheral hardware devices, including Ethernet controllers, age and reducing false negatives. But using static analysis sound cards, storage adapters and so on. To improve the perfor- to detect unsafe DMA accesses in the Linux driver code is mance of data communication between the OS and hardware still challenging. First, as each DMA access is implemented as a regular variable access in the driver code, it is difficult The rest of this paper is organized as follows. Section2 to statically identify DMA accesses. Second, as the Linux introduces the background and our study of DMA. Section3 kernel code base is very large and complex, performing static analyzes the challenges of static detection of unsafe DMA analysis of it is also difficult. Third, static analysis can report accesses. Section4 introduces our solution techniques. Sec- many false positives due to lacking exact runtime information tion5 presents SADA in detail. Section6 shows our evalua- of the driver. To our knowledge, there is no systematic static tion. Section7 makes a discussion about SADA and unsafe approach of detecting unsafe DMA accesses at present. DMA accesses. Section8 introduces related work, and Sec- In this paper, we propose a static-analysis approach named tion9 concludes this paper. SADA (Static Analysis of DMA Accesses), to automatically and accurately detect unsafe DMA accesses in device drivers. 2 Background and Study of DMA Overall, SADA consists of three basic steps. First, consider- ing that DMA accesses and DMA mapping creation may be In this section, we introduce DMA and its problems in existing performed in different driver functions, SADA uses a field- research, then reveal the security risks of DMA accesses, and based alias analysis to identify DMA accesses according to finally study DMA in Linux device drivers. the information of DMA mapping creation, because our study of the Linux driver code finds that about 87% of created DMA buffers are stored in data structure fields in the driver code. 2.1 DMA Architecture Second, SADA uses a flow-sensitive and pattern-based analy- Direct Memory Access (DMA) is a popular mechanism that sis to check the safety of each DMA access, to detect possible allows peripheral hardware devices to communicate data with unsafe DMA accesses. Specifically, to detect inconsistent system memory without CPU involvement. Without DMA, DMA accesses, SADA checks whether each DMA access when the data is transfered between a hardware device and is performed with proper synchronization of DMA buffers system memory, a CPU is typically fully occupied for the by analyzing code context. To detect unchecked DMA ac- entire duration of the data transfer, and thus this CPU is un- cess, SADA uses a static taint analysis to check whether the available to perform other tasks. With DMA, a CPU just accessed data from DMA buffers can cause possible inse- initiates the data transfer and then hands over the actual data cure influence on data flow or control flow. For example, if transfers to the DMA controller (DMAC) , so the CPU can a variable stored in a DMA buffer is used as an array index focus on other tasks. Once the data transfer finishes, the CPU without any check, a buffer-overflow bug can occur. Finally, will receive an interrupt from the DMA controller to wrap up SADA uses an SMT solver Z3 [66] to validate the code-path the data transfer. In this way, the CPU performs only the min- feasibility of each possible unsafe DMA access, to drop false imum jobs, namely initialization and finalization of the data ones. In this way, the overhead introduced by the SMT solver transfers, which thus improves hardware I/O performance. can be reduced compared to the traditional way of validating code-path condition while analyzing the whole driver code. CPU Cache We have implemented SADA with LLVM [33]. Data Synchronization Overall, we make the following technical contributions: System Memory DMA Buffer • By studying DMA in device drivers, we reveal the se- Device 1 DMA Transfer curity risks of DMA accesses from two aspects: 1) they DMA Controller can cause unexpected hardware behaviors; and 2) they Device 2 …… Hardware I/O can trigger security bugs (such as buffer overflow and Device N invalid-pointer access) caused by the bad data from mal- functioning or untrusted hardware devices. Figure 1: The DMA architecture. • We propose a practical static-analysis approach named Figure1 shows the architecture of DMA in modern com- SADA, to effectively detect unsafe DMA accesses in puter systems. To enable DMA, a DMA buffer is allocated device drivers. SADA incorporates multiple techniques and mapped to system memory and hardware registers. When to ensure the precision and effectiveness of the detection. the CPU wants to read hardware registers, it directly reads To our knowledge, SADA is the first systematic static the DMA buffer in system memory and synchronizes the data approach to detect unsafe DMA accesses. into the CPU cache. Similarly, when the CPU wants to write • We evaluate SADA on Linux 5.6, and find 284 real hardware registers, it directly writes to the DMA buffer in unsafe DMA accesses. Among them, we highlight that system memory and synchronizes the data into hardware reg- 121 can trigger buffer-overflow bugs and 36 can trigger isters. To reduce programming complexity, each DMA access invalid-pointer accesses causing arbitrary read or write. is implemented as a regular variable access in the driver code, We have reported these unsafe DMA accesses to Linux such as data = dma_buf->data (reading a DMA buffer) driver developers, and 105 of them have been confirmed. and dma_buf->data = data (writing a DMA buffer).