Rowhammer and RowPress: Implementation and Evaluation on AMD Zynq SoCs
Rowhammer and RowPress: Implementation and Evaluation on AMD Zynq SoCs
Introduction
The rapid increase in memory density over the last few decades has led to the discovery of the Rowhammer vulnerability in 2014 and the RowPress vulnerability in 2023. These vulnerabilities arise from insufficient electrical isolation between DRAM memory cells, potentially causing bit flip errors when DRAM rows are accessed in specific patterns.
While much research has focused on x86 architectures, this bachelor thesis explores the feasibility and impact of implementing Rowhammer attacks on ARM-based systems, specifically the AMD Zynq SoCs. The thesis examines the architecture, memory management, and caching policies of ARM systems to evaluate their resilience or susceptibility to Rowhammer. Although the Rowhammer attack is already well-documented and extensively researched, there is limited literature available on RowPress.
Research Objectives
The primary objective of this research is to evaluate the viability of Rowhammer and RowPress vulnerabilities on AMD Zynq SoCs. Key objectives include:
- Understanding the architectural differences between x86 and ARM in the context of DRAM vulnerabilities.
- Implementing Rowhammer on ARM-based SoCs and evaluating its effectiveness.
- Investigating the viability of RowPress on the Zynq SoC platform.
- Comparing the ARM-based findings with existing x86-based research.
DRAM Architecture
A typical DRAM module is hierarchically organized and consists of multiple banks, each containing rows and columns of memory cells. A memory cell is made up of a capacitor and a transistor. Each cell is at the intersection of two perpendicular wires, the horizontal wordline and the vertical bitline. The voltage in the wordlines can be used to read data from any given row. For example, when the voltage of a wordline for a specific row is raised, all access-transistors of the corresponding cells are activated, connecting the capacitors storing the bit to the vertical bitlines. This allows the cell charge representing the stored data to flow into the row buffer. The row buffer acts similar to a cache, accelerating repeated access to a given memory row. The image below visualizes the DRAM architecture.
DRAM memory is accessed in the following steps:
- Translate physical address to memory location: This is done by the memory controller using translation functions.
- Activate/Open row: Increasing the voltage of the calculated row connects the capacitors to their connected bitlines, causing the binary data stored in the capacitors to move to the row buffer, of which each bank has one.
- Read or modify data: Once in the row buffer, the data can be read or modified as needed.
- Close row: By lowering the voltage of the wordline, the row is closed. Once the row buffer has been cleared, another row can be opened after the memory controller issues the PRECHARGE command.
DRAM cell capacitors lose their charge over time. For this reason, DRAM cell charge needs to be refreshed at regular intervals. This is done by reading row data to the buffer and writing the same data back to the row. The interval at which DRAM must be refreshed depends on several factors, including the specific standard of DRAM used and operating temperature. The most recent DRAM standards, DDR5 and LPDDR5, implement a refresh interval of 32 ms, while the previous standards, DDR3 and DDR4, had standard refresh intervals of 64 ms.
Rowhammer Attack
Rowhammer is a vulnerability that exploits the electrical interference between DRAM cells. By rapidly and repeatedly activating specific rows (aggressor rows), nearby rows (victim rows) encounter electrical interference, potentially causing bit flips.
For a conventional Rowhammer attack to succeed, three main requirements must be satisfied:
- Memory accesses must not be served by the cache: If repeated memory accesses required for Rowhammer are handled by either the CPU cache or the row buffer, the DRAM hardware is never reached, making it impossible to cause bit flips. This requirement can generally be satisfied by evicting data from the cache or not putting data into the cache in the first place.
- Memory access must be fast: Depending on the refresh rate of the used memory controller, there is a very limited timeframe during which bit flips can be caused before the charge of the DRAM cells is refreshed.
- Memory access must be highly targeted: Rowhammer usually relies on being able to access very specific DRAM rows located in close proximity to each other. Therefore, it is important to understand the memory mapping functions involved in translating physical addresses into the actual location on the memory module.
Rowhammer attacks can be classified into different patterns:
- Single-sided Rowhammer: Repeated access to one row adjacent to the target row.
- Double-sided Rowhammer: Accessing two rows on either side of the target row, increasing the likelihood of bit flips.
Double-sided Rowhammer is the most common variant.
Rowhammer has been widely studied on x86 systems, and advanced exploits have been developed.
RowPress Attack
RowPress is a more recent attack method discovered in 2023. Unlike Rowhammer, which relies on high-frequency row activations, RowPress induces bit flips by keeping a memory row open for extended periods (referred to as tAggON). The prolonged activation of an aggressor row can destabilize adjacent rows and cause data corruption. There is currently very little research on RowPress, and existing studies have only been done on highly specialized testing hardware.
ARM Architecture and Memory Access
ARM architectures, such as those used in the Zynq SoCs, differ from x86 in several key areas, particularly in memory access and cache management. ARM processors typically use a different set of instructions for cache maintenance, and direct memory access is handled differently. Furthermore, ARM-based systems often have more constrained memory controllers and may employ different policies for handling row activations, which affects the feasibility of attacks like Rowhammer and RowPress.
Methodology
AMD Zynq SoC Overview
The AMD Zynq-7000 SoC is an embedded development platform with a dual-core ARM Cortex-A9 processor and programmable logic (FPGA). The specific model used in this thesis, the Digilent Zybo Z7-20, includes 1 GB of DDR3L DRAM.
Development Environment
The development environment used for this research consists of AMD’s Vivado for hardware design and Vitis for program development. The hardware design created using Vivado includes the Zynq Processing System (Zynq PS) and the default DRAM memory configuration. Altering the DRAM parameters would not have aided in the experiments. The program, written in C, controls the memory access patterns and performs the Rowhammer tests.
DRAM Address Mapping
Understanding the specific DRAM address mapping functions is important for successfully targeting specific rows in a Rowhammer or RowPress attack. The address mapping functions translate a physical address to the exact location of the associated data on the DRAM module. By analyzing the Technical Reference Manual and configuration files, the exact address bits used for row, bank, and column mapping were identified.
The following addressing information was obtained from the documentation:
- Bank: 3 address bits required to address the 8 banks, these bits are 12,13, and 14.
- Row: 15 address bits required to address the rows, 15-29.
- Column: 10 address bits required to address the columns, 2-11.
Based on this information, a function was implemented that receives bank, row, and column as int parameters, and returns a pointer to the address corresponding to the DRAM location. See the code snippet below:
void* getAddress(int bank, int row, int column) {
bank &= 0x7;
row &= ((1 << (ROW_BITS - 1)) - 1) | (1 << (ROW_BITS - 1));
column &= 0x3FF;
uint32_t address = (bank << 12) | (row << ROW_START) | (column << COLUMN_START);
return ((uintptr_t)address >= (uintptr_t)(&__rowhammer_space_start) && (uintptr_t)address <= (uintptr_t)(&__rowhammer_space_end)) ? (void*)address : NULL;
}
Cache Management
One of the primary challenges in implementing Rowhammer on ARM systems is ensuring that memory accesses bypass the CPU caches and directly reach DRAM. Unlike x86 systems, ARM does not have a universal instruction like `clflush` for cache flushing. In this study, cache flushing was achieved using the Xilinx SDK's cache maintenance functions, and in some of the experiments, the data cache was completely disabled to ensure uncached memory access during the attacks. In the below code, the aggressor rows are hammered, and the caches are flushed after each access. This low-level access to the cache management functions was very helpful, as it relieved the need for complex cache eviction strategies.
void performRowhammer(void* neighborRow1, void* neighborRow2, int iterations) {
for (int i = 0; i < iterations; i++) {
readAddress(neighborRow1);
Xil_DCacheFlushLine(neighborRow1);
readAddress(neighborRow2);
Xil_DCacheFlushLine(neighborRow2);
}
}
Test Setup for Rowhammer
The Rowhammer test on the Zynq-7000 was designed to simulate a double-sided hammering pattern. First, specific memory locations were initialized with a known data pattern. Then, the aggressor rows surrounding a target row were repeatedly accessed for a large number of iterations, while cache flushes ensured that accesses were handled by DRAM, not the CPU cache. After hammering, the target and adjacent rows were checked for bit flips by comparing their data to the original pattern.
The Rowhammer program contains the following steps:
- Iterate over and initialize memory columns: For each row of a bank, all columns are initialized with a 32-bit data pattern of alternating bit values.
- Flush and invalidate caches: The L1 and L2 caches are flushed, invalidated, and disabled to prevent the CPU cache from serving subsequent memory requests.
- Iterate over rows and calculate aggressor row addresses: A for-loop is used to iterate over the number of rows, with the current row being the victim row. As this is supposed to be a double-sided Rowhammer pattern, addresses to two neighboring aggressor rows are calculated.
- Repeatedly activate aggressor rows: The calculated addresses are accessed repeatedly for a specified number of iterations, thus essentially performing the Rowhammer attack.
- Check surrounding rows for bit flips: After a pair of aggressor rows has been hammered, the contents of the surrounding rows is checked for bit flips by comparing the actual value read from memory to the expected data pattern used for initialization.
Below is a pseudocode representation of the actual source code:
for each bank
for each row
for each column
address = calculate_address(bank, row, column)
if address is not NULL
initialize column = init_pattern
end if
end for
end for
disable_caches()
for each row
address1 = calculate_address(bank, row - 1, 0)
address2 = calculate_address(bank, row + 1, 0)
for rowhammer_iterations
activate row of address1
activate row at address2
end for
for each check_row from row - 2 to row + 2
for each column
check_address = get_address(bank, check_row, column)
if read from address does not equal init_pattern
print "Bit flip found"
end if
end for
end for
end for
end for
Test Setup for RowPress
As discussed in the theory section, the RowPress mechanism is fundamentally different from Rowhammer. Instead of inducing data errors by rapidly activating aggressor rows, RowPress works by keeping a single row open for an extended period, leading to bit flips.
Implementation Challenges
RowPress relies on specialized FPGA hardware, which poses challenges when implementing it on platforms like the Zynq-7000. The following issues arise when applying RowPress to such platforms:
- Aggressor Row-On Time (tAggON): RowPress requires a DRAM row to remain open for a longer time, disturbing nearby rows and causing bit flips.
- Memory Controller Behaviour: The memory controller is responsible for controlling how long a row stays open, which is more critical in RowPress compared to Rowhammer.
- Timing Constraints: Lower clock speeds make precise timing difficult, affecting the effectiveness of RowPress.
- Limited Control over Memory Controller Settings: The Zynq-7000 platform offers limited flexibility to adjust critical DRAM timing parameters, unlike more advanced FPGA hardware.
RowPress on the Zynq-7000 Platform
While it is difficult to create an ideal RowPress testing environment on the Zynq-7000, specific access patterns may be used to prolong row-open times. For example, accessing a row and then switching to a different cache block within the same row may cause the memory controller to keep the row open longer.
Building on the existing Rowhammer code, addresses mapped to the same row can be generated. Memory requests to different cache blocks within the same row may prompt the memory controller to keep the row open for subsequent accesses. To verify this, the following steps can be taken:
- Flush all cache blocks of a DRAM row from the CPU caches using appropriate instructions.
- Access a different row so the memory controller closes the previous row.
- Measure the CPU cycles needed to access each cache block of the row being tested.
A noticeable latency difference between the first and subsequent accesses indicates that the row remains open longer, effectively increasing tAggON.
The success of this approach depends on the row buffer management policy used by the memory controller. The main policies include:
- Closed-Page Policy: Closes a DRAM row immediately after a read or write operation.
- Fixed Open-Page Policy: Keeps a row open for a fixed duration after an operation.
- Adaptive Open-Page Policy: Dynamically adjusts how long a row remains open based on the system's activity.
To increase row-open time, the memory controller must use an adaptive open-page policy. On the Zybo Z7-20, it is possible to verify that the controller follows this policy, as indicated by certain control bits in the configuration files.
Profiling the system to synchronize RowPress patterns with DRAM refresh cycles can help maintain longer row activation times. Similar to Rowhammer, understanding DRAM address translation is crucial to targeting specific memory locations.
Results
Rowhammer Results
Despite implementing double-sided hammering and flushing the CPU caches, no bit flips were observed during the Rowhammer tests on the Zynq-7000 platform. The potential reasons are manifold, and they are outlined in the thesis.
RowPress Results
The RowPress implementation faced even more significant challenges. The limited configurability of the memory controller on the Zynq-7000 meant that row-open time could not be extended as needed for RowPress. Further testing with hardware that provides more control over memory timing is required to evaluate RowPress effectively.
Conclusion
Rowhammer and RowPress are critical vulnerabilities in DRAM that have been primarily explored on x86 systems. This research aimed to implement these vulnerabilities on ARM-based systems using the AMD Zynq SoC platform. While the Rowhammer and RowPress implementations on the Zynq-7000 did not result in observable bit flips, the research highlights the difficulty of replicating these attacks on ARM architectures. The findings suggest that further research is needed, particularly with more flexible hardware setups that allow better control over memory access patterns and timing.
Future Work
Future research should focus on testing Rowhammer and RowPress on a wider variety of ARM-based platforms and exploring more sophisticated methods for managing memory access and timing. Additionally, hardware that allows for finer control over memory controllers, such as FPGAs with more advanced DRAM interfaces, would be beneficial for testing these vulnerabilities.
References
- H. Luo, A. Olgun et al., "RowPress: Amplifying Read Disturbance in Modern DRAM Chips," in Proceedings of the 50th Annual International Symposium on Computer Architecture (ISCA), 2023.
- Y. Kim, R. Daly et al., "Flipping bits in memory without accessing them: An experimental study of DRAM disturbance errors," in Proc. 41st Int. Symp. Comput. Archit. (ISCA), 2014, pp. 361–372, doi: 10.1109/ISCA.2014.6853210.
- D. Gruss and C. Maurice, "Rowhammer Attacks: A Walkthrough Guide," in Proc. RuhrSec 2017, Graz University of Technology, 2017. [Online]. Available: https://www.tugraz.at. [Accessed: Sept. 16, 2024].
- Z. Zhang, Z. Zhan, D. Balasubramanian, X. Koutsoukos, and G. Karsai, "Triggering Rowhammer Hardware Faults on ARM: A Revisit," in Proceedings of the 2018 Workshop on Attacks and Solutions in Hardware Security (ASHES '18), Toronto, Canada, 2018, pp. 24-33. doi: 10.1145/3266444.3266454.
