PolyRhythm
-
Install / Use
/learn @WUSTL-CSPL/PolyRhythmREADME
PolyRhythm README
About PolyRhythm
PolyRhythm is a three-phase attack template that combines primitives across multiple architectural and kernel-based channels:
- Phase 1 uses an offline genetic algorithm (GA) to tune attack parameters based on the target hardware and OS platform
- Phase 2 performs an online search for regions of the attack parameter space where contention is most likely
- Phase 3 runs the attack primitives, using online reinforcement learning (RL) to adapt to dynamic execution patterns in the victim task.
More details about PolyRhythm can be found in the following paper:
A. Li, M. Sudvarg, H. Liu, Z. Yu, C. Gill, N. Zhang. "PolyRhythm: Adaptive Tuning of a Multi-Channel Attack Template for Timing Interference." IEEE Real-Time Systems Symposium (RTSS), 2022
Getting Started
To retrieve and build PolyRhythm:
$ git clone -b rtss2022artifact-01 https://github.com/WUSTL-CSPL/PolyRhythm
$ cd PolyRhythm
$ mkdir build && cd build
$ cmake .. && make
PolyRhythm can be run with an RL model that dynamically selects attack primitives to target specific contention channels. Communication between the model and attack threads is via shared memory regions; the model's Python scripts use a C-extension to use the memory. To build the extension:
$ cd ../RL_DDPG/C-extension
$ make
Running Specified Attack Primitives
The polyrhythm binary produced by the build process takes one or more sets of parameters of the following pattern:
<primitive> <nthreads> <param1> <param2> <param3> <param4> <online>
This tells it to launch nthreads instances of the primitive with the given parameters.
The parameter online takes the value 0 or 1 to specify whether to run Phase 2, the online contention region search.
Some primitives take fewer than 4 parameters, or ignore the online option. In this case, arguments must still be passed to the command-line, but are ignored (0 values can be used).
Primitives and corresponding parameters are listed below:
Cache Attack
Name: cache
Targets shared cache resources, attempting to cause delays in miss status holding registers or the writeback buffer even when isolation techniques such as cache coloring or partitioning are in use. Allocates an array then iteratively writes to array elements.
Parameters:
stride(iteration step as a multiple of the cache line size)size(array size, in kB)- (
empty) - (
empty) online: online attack attempts to find an eviction set
Note: PolyRhythm assumes the target platform uses a 64 Byte cache line. To change this, set the CACHE_LINE constant in src/Cache_Attacks.c
Memory Bandwidth
Name: memory
Targets shared memory resources that constrain memory bandwidth, e.g., the bus and memory controller. Generates a high volume of requests to main memory.
Parameters:
nthreads(number of threads to launch per PolyRhythm attack instance)size(array size, as a multiple of the last-level cache size)pattern(access pattern, 0: read, 1: write)- (
empty) online: online attack attempts to find a memory region that overlaps with victim usage
Note: Requires defining the last level cache size by setting the LLC_CACHE_SIZE constant in include/Attacks.h
DRAM Row Buffer
Name: row_buffer
Targets the DRAM row buffer, attempting to evict victim data held in the buffer, increasing memory request latency. Allocates two arrays, swaps and modifies values between them.
Parameters:
stride(iteration step size, for sequential access)size(array size, as a multiple of the last-level cache size)pattern(0: iterate sequentially over array, 1: access array elements at random)- (
empty) online: online attack attempts to find a DRAM row region that overlaps with victim usage
Note: Requires defining the last level cache size by setting the LLC_CACHE_SIZE constant in include/Attacks.h
TLB Page Eviction
Name: tlb
Attempts to evict victim page entries from the translation lookaside buffer (TLB). Maps memory pages, zeroes the mapped region, then marks each page read-only, copies contents to the stack, then unmaps the page.
Parameters:
pages(number of pages to map for each iteration)- (
empty) - (
empty) - (
empty) online: not supported
Note: PolyRhythm assumes the target platform uses a 4kB page size. To change this, set the PAGE_SIZE constant in include/Attacks.h
Network I/O
Name: network
Attempts to cause contention in the network driver stack (not the network interface itself) by flooding the local loopback address with UDP traffic.
Parameters:
size(packet size, in Bytes)domain(address family to target, 0: ipv4, 1: unix, 2: ipv6)- (
empty) - (
empty) online: online attack iterates over open ports, finding the port/domain combination that generates the most contention
Block Device I/O
Name: disk_io
Attempts to cause contention in the block device driver stack by producing a large number of I/O operations. This should overwhelm the I/O scheduler and cause contention in the request queues. Opens a file, sets file system advice to POSIX_FADV_RANDOM, then generates a large number of short writes.
Parameters:
filesize(size of the file, as a multiple of page size)writesize(size of string written in each operation, in Bytes)stride(iteration step size, for sequential access)pattern(0: iterate sequentially over array, 1: access array elements at random)online: not supported
Note: PolyRhythm assumes the target platform uses a 4kB page size. To change this, set the PAGE_SIZE constant in include/Attacks.h
Fork Bomb
Name: spawn
Continuously forks new processes (each with its own address space) to cause contention in the scheduler, process data structure allocator, IPC endpoint queues, etc.
Parameters:
nthreads(Number of threads to spawn)- (
empty) - (
empty) - (
empty) online: not supported
Example
To have PolyRhythm launch two instances of the cache attack with a stride of 1 cache line, over an 835kB region, using online search for contention regions; and launch once instance of the DRAM row buffer attack, using an interation step of size 1, a region 15 times the size of the LLC, and sequential access, use the following command:
./polyrhythm
cache 2 1 835 0 0 1
row_buffer 1 1 15 0 0 0
Tuning Platform-Specific Parameters
PolyRhythm uses an offline genetic algorithm (GA) to tune attack parameters based on the target hardware and OS platform. This requires you to have root access to a copy of the target platform, but does not require a copy of the victim workloads that will ultimately be attacked. The GA runs polyrhythm to tune each primitive independently, finding the parameters that maximize its interference potential (measured using various performance counters) over a representative victim task that aggregates several benchmarks from the stress-ng suite. By running several instances of polyrhythm with guessed parameters at each generation, the GA can converge to an optimal set of parameters for each primitive.
To perform the tuning:
1. Turn on hardware events
$ sudo -i
### Allow use of (almost) all events by all users
$ echo -1 > /proc/sys/kernel/perf_event_paranoid
### Exit su
$ exit
2. Retrieve and build the victim workloads
CortexSuite
CortexSuite, previously known as the San Diego Vision Benchmark Suite (SD-VBS), is a "suite of diverse vision applications drawn from the vision domain." More information can be found in the paper:
S. Thomas, C. Gohkale, E. Tanuwidjaja, T. Chong, D. Lau, S. Garcia, and M. B. Taylor, “Cortexsuite: A synthetic brain benchmark suite,” in 2014 IEEE International Symposium on Workload Characterization (IISWC). IEEE, 2014, pp. 76–79.
It can be retrieved from https://cseweb.ucsd.edu/groups/bsg/
To retrieve:
$ git clone https://bitbucket.org/taylor-bsg/cortexsuite.git
PolyRhythm uses the disparity benchmark as a victim workload when training. To build:
### Go the directory of disparity
$ cd cortexsuite/vision/benchmarks/disparity/data/sqcif
$ make c-run
### Troubleshooting:
### make fails on some versions of Linux (including the VM)
### because of the gmake system
### When it fails, run:
$ make c-run -n
### This will tell you the failed compilation command
### Copy the command, manually append -lm, then run it directly
### After the command completes, the build should be done
You will need to update the GA/utils.py to reflect the installation path for the disparity benchmark.
stress-ng
stress-ng is designed to stress various resources on a system, based on runtime selections. This makes it easy to launch synthetic workloads that are heavily constrained to a given resource (e.g., cache, main memory, disk, network, etc.).
Documentation for stress-ng is available from: https://wiki.ubuntu.com/Kernel/Reference/stress-ng
It can be retrieved from: https://github.com/ColinIanKing/stress-ng
To retrieve and build:
$ git clone https://github.com/ColinIanKing/stress-ng
$ cd stress-ng
$ make
You will need to update the GA/utils.py to reflect the installation path for stress-ng.
3. Launch the GA to tune parameters.
Note: Make sure you have updated GA/utils.py with the correct paths to the victim workloads.
To run the GA:
$ cd ~/PolyRhythm/GA
$ python3 main.py
This tunes each primitive independently. The GA takes the additional arguments:
--channel: Tune an individual primitive. Values match the names listed above for each primitive.--ncores: The number of cores on the target system. Defaults to 4. Launches one victim thread, thenncores-1attacker instances.--params: Outputs parameters to the given filename. Values are then used by the dynamic
