# Adversarial Prefetch: New Cross-Core Cache Side Channel Attacks

Yanan Guo  Electrical and Computer Engineering Department, University of
Pittsburgh<EMAIL_ADDRESS>Andrew Zigerelli  Youtao Zhang  Department of
Computer Science, University of Pittsburgh  Jun Yang  Electrical and Computer
Engineering Department, University of Pittsburgh

###### Abstract

On modern x86 processors, data prefetching instructions can be used by
programmers to boost performance. Although good for performance, we found that
PREFETCHW, which is a data prefetching instruction to accelerate future write
operations, has two significant security flaws on Intel processors: first,
this instruction can execute on data with read-only permission; second, the
execution time of this instruction leaks the current coherence state of the
target data.

Based on these two design flaws, we build the first two cross-core cache
timing attacks that can work on private caches. Specifically, we first propose
two covert channel attacks that can achieve a 864KB/s transmission rate which
is higher than all existing cache covert channel attacks. Then we further
propose two side channel attacks that can be used to monitor the access
pattern of the victim running on the same processor. We demonstrate the
efficacy of our attacks by using them to leak private information from daily
applications. Finally, we show that our prefetch based attacks can be used in
transient execution attacks to leak more secrets within one speculative
window.

##  I Introduction

Modern processors often feature many microarchitectural structures that are
shared among applications. Although such resource sharing has offered
significant benefits to performance, it has also given adversaries the
potential to build covert channel or side channel attacks. When a security-
sensitive application is running on a hardware platform, its execution will
cause various state changes on the shared microarchitectural structures which
can be observed by the attackers located on the same platform. Thus, an
attacker can collect these changes and then derive private information related
to them, bypassing sandboxes and traditional privilege boundaries [17, 22,
23]. Cache timing covert channel and side channel attacks, or cache attacks
for short, have been demonstrated to be extremely potent [41, 19, 43, 27, 38,
11, 40, 20, 21, 29], and have gained more attention recently due to the
discovery of speculative execution attacks [24, 26, 32, 37, 35, 36, 33].
Different cache behaviors, such as hits and misses create significant timing
differences to the execution of an instruction. Software-level attackers are
able to use these timing variances to stealthily transfer data (in the covert
channel case) or infer some secrets from a victim (cryptographic keys for
example). Cache attacks can be divided into same-core attacks and cross-core
attacks.

Same-core attacks (e.g. [38, 43]) require the attacker and the victim to be
located on the same physical core in the processor such that the attack can
work on the private cache: the attacker evicts the victim’s data from the
private cache to the last level cache (LLC) and waits for the victim, if the
victim accesses the data and brings it back to the private cache, it will be
observed by the attacker using timing information (e.g. the attacker can
access this data again and determine whether it is already back in the private
cache by measuring the latency). Same-core attacks are very fast since all the
data accesses are on-chip cache accesses; however, they are also limited
because simultaneous multithreading (SMT) techniques are often required in
such attacks. In contrast, in cross-core attacks, the attacker can run on a
different core than the victim and target the LLC which is usually shared
among different cores: in most cross-core attacks, the attacker evicts the
victim’s data from the LLC to memory, and waits for the victim to bring it
back to the LLC. Although cross-core attacks are more practical, the attack
bandwidth is very limited since memory accesses are relatively slow.

To overcome the limitations in both same-core and cross-core attacks, we aim
at building a cross-core attack that can work on private cache. The attacker
evicts the victim’s data from the victim’s private cache to LLC, and lets the
victim bring it back to his private cache. However, it is very challenging to
achieve this attack since traditional cache eviction techniques cannot be used
in this scenario. First, the attacker cannot use CLFLUSH instruction to evict
the victim’ data from his private cache to LLC because CLFLUSH will evict all
the copies of a data block in the cache hierarchy to memory. Second, the
attacker cannot evict the victim’s data by building cache set conflicts as
done in Prime+Probe attack [43] since the attacker is not running on the
victim’s core.

Figure 1: The MESI protocol.

We address these challenges and build the cross-core L1 attack by manipulating
cache coherence states. In multi-core processors, a cache coherence protocol
is required to maintain data consistency among the copies of a data block in
different private caches. Modern processors use MESI protocol or its variants
[13, 8] for cache coherence. Unfortunately, MESI can be utilized by the
attacker to “remotely” evict the victim’s cache line from the private cache:
MESI is an invalidation on update protocol which means if the attacker writes
the victim’s data, the copy of this data in the victim’s private cache will be
invalidated (without invalidating the copy in LLC if it exists). However, in
cache attacks, the attacker cannot directly write the victim’s data.

In 2000, AMD released PREFETCHW which is a new instruction for data
prefetching. This is instruction has later been accpeted by Intel and is now
available on all Intel Xeon Scalable processors and recent desktop processors.
According to AMD [7], the function of this instruction is to prepare data for
future writes. Thus, different than other prefetch instructions that only move
the target data closer to CPU (e.g. PREFETCHT0), this instruction moves the
data to L1 data cache as well as setting the coherence state of the data to be
Modified. According to MESI, changing the coherence state of a data block to
Modified will invalidate all the copies of this data block in other private
caches since a data block in Modified state should be dirty. In this work, We
made two important observations on PREFETCHW: first, on Intel processors,
PREFETCHW can also work on data with read-only permission; second, on Intel
processors, the execution time of PREFETCHW is related to the current
coherence state of the target data. With these two observations, we conclude
that PREFETCHW can be used to manipulate cache coherence states to build
cross-core cache attacks on private cache.

Based on PREFETCHW, we first propose two covert channel attacks: Prefetch+Load
and Prefetch+Prefetch. In Prefetch+Load, the sender can send a bit by
prefetching a shared data block between the sender and receiver (for “1”) or
not prefetching (for “0”). The receiver receives the signal by loading the
data and timing the load to determine it is a private cache hit (for “0”) or
LLC hit (for “1”). In Prefetch+Prefetch, the sender transmits a bit by
loading/not loading the shared data, and the receiver receives the bit by
prefetching the data and timing the prefetch instruction to determine whether
the sender loaded. We show that as far as we know, these attacks achieve
higher transmission rate than all existing cache covert channel attacks.
Specifically, on a 3.4GHz Skylake processor, with less than 1% bit error rate,
the transmission rate can be 752KB/s for Prefetch+Load, and 743KB/s for
Prefetch+Prefetch.

We then modify the covert channel attacks and build the Prefetch+Reload and
Prefetch+Prefetch side channel attacks which can be used to leak the victim’s
access patterns, similar with previous cache attacks [41, 19, 27, 38, 11, 40,
43]. Prefetch+Prefetch can be directly used as a side channel attack by
letting the victim to be the sender, and the attacker to be the receiver. For
Prefetch+Reload, we modify Prefetch+Load to let the attacker own two threads
running on different cores. Then in this attack, the attacker first prefetches
and waits for the victim to access, and then reloads using a different thread.
Although when the attacker reloads, he will always get an LLC hit, the
coherence state of the target data when the LLC hit happens varies when the
victim loaded/did not load the data. The timing leakage used here is that the
execution time of an LLC hit can vary when the target data is in different
coherence states. We show that our attacks can be deployed on Intel processors
to leak secrets from real-world applications, and can also be used in
transient execution attacks which may make those attacks faster and more
powerful than before.

Responsible Disclosure. We disclosed the security vulnerability we found in
this paper to Intel on September 18th, 2021. Intel classified our attacks as
classical side channel attacks and decided not to put an embargo on the
publication since they believe the provided guidance on developing constant
time algorithms [4] can help prevent these attacks.

##  II Background and Related Work

###  II-A CPU Cache Architecture and Coherence Protocol

Cache Architecture. Most CPU caches on Modern x86 processors are divided into
L1, L2, and L3. L1 and L2 caches are very fast (less than 50 cycles on most
processors) but their sizes are limited. They are typically private to each
CPU core, and are thus often referred to as private caches. In contrast, the
L3 cache, also known as last-level cache (LLC), is a large but relatively slow
cache shared among CPU cores.

Additionally, caches are usually set-associative, meaning that they are
divided into cache sets and each cache set consists of multiple equivalent
cache ways. Each cache way can fit one cache line which is the basic unit for
cache transactions. The cache set a cache line is mapped to in each cache
level is determined by its address bits. When a CPU core performs a memory
request, it will first check whether the target cache line is present in the
L1 or L2 cache. It present, the request will result in a private cache hit. If
not, it will result in a private cache miss and further check whether the
target cache line is in the LLC. If the cache line is found in LLC, the
request finishes with an LLC hit. If not, the request will be forwarded to the
memory controller which can directly read/write data from/to DRAM devices.
Most x86 LLCs are inclusive, meaning the data present in private caches are
also present in the LLC. However, non-inclusive LLCs are used in recent
processors with Skylake-SP microarchitecture [9, 39].

Cache Coherence. In multi-core systems, a cache line could be present in
multiple private caches due to the data sharing among processes. A cache
coherence protocol is required to handle the data consistency among the copies
of a cache line in different private caches. Most modern x86 processors use
variants of the MESI cache coherence protocol [8, 13]. Here we use inclusive
cache as an example to introduce MESI protocol. On non-inclusive cache the
protocol is the same other than that a cache line in a private cache might not
be present in the LLC. With MESI, there are are four potential states for a
cache line in a private cache (and also in the LLC for inclusive cache):

  * •

Modified (M), in which the cache line is only present in one private cache and
is dirty, i.e. the copy of this cache line in LLC contains stale data, as
shown in Figure 1(a). In addition, when a cache line in a private cache is in
M state, the current core has read/write permission on this cache line.

  * •

Exclusive (E), in which the cache line is only present in one private cache,
and is clean (Figure 1(b)). The current core can read/write this cache line;
however, a write operation will change the state of this cache line to M.

  * •

Shared (S), in which the cache line is present in one or more private caches
and is clean, i.e. the data of this cache line’s copies in private caches all
match the data in the LLC. The current core can only read this cache line
(Figure 1(c)).

  * •

Invalid (I), in which the cache line is invalid, and thus the current core has
neither read nor write permission on it (Figure 1(d)).

With MESI protocol, a memory request from a CPU core will sometimes 1) change
the coherence state of the target cache line, and 2) take different amount of
time to finish with the target cache line staying in different coherence
states.

State Changing. First, as shown in the left part of Figure 2, when a CPU core
(core 1) is reading a cache line that is present in the LLC and the private
cache of another core (core 0) in M state, this read request will first miss
in its private cache and then hit in the LLC. Since the content of this cache
line in LLC is stale, LLC will fetch the data from the private cache (in core
0) that contains this cache line (step 1), change the coherence state of this
cache line in that private cache (in core 0) to S (step 2), update the content
of this cache line in the LLC (step 3), and then return the updated cache line
to the requesting core (core 1) as well as filling its private cache with a
copy of this cache line in S state (step 4). Thus, after serving this read
request, the target cache line is present in two private caches, and is in S
state in both caches, as shown in the right part of Figure 2.

Second, as shown in the right part of Figure 2, when a CPU core (core 0) is
trying to write a cache line that is S state in its private cache, this
private cache (in core 0) needs to send request to LLC to acquire write
permission before it can serve this write operation. As a result, the LLC will
send signal to other private cache(s) the cache line is present in (in core1)
to invalidate those copies (step 1), and then change the state of the cache
line in the private cache of the requesting core (core 0) to M so that the
requesting core can write this cache line its private cache (step 2). Thus,
after this write operation, the target cache line is only present in the
requesting core’s private cache, and is in M state, as shown in the left part
of Figure 2.

Timing Difference. As shown in Figure 3, if a CPU core (core 1) is reading a
cache line that is not present in its private but is present in LLC, (i.e. an
LLC hit), the total latency it takes to finish this read request can be
different when the cache line is in different coherence states: the LLC hit is
faster when the cache line is S state than when the cache line is in M state,
because data fetching (from another private cache) and state changing are
required in the latter. This has been observed by previous work [40] and has
been verified in our experiments. On an Intel Core i7-7700K processor, this
difference is about 30 cycles.

Figure 2: The illustration of cache coherence state changes: the state of an
LLC line is changed from M to S when a CPU core is loading it (from the left
to right), and the state is changed from S to M when a CPU core is writing it
(from the right to left); dashed lines are showing the request path of a
read/write operation.

Figure 3: The illustration of an LLC hit with the target cache line in M state
(left) and S state (right).

⬇

1void* thread0 (void* addr_d0, int expt_idx){

2 for(int i = 0; i < 3000; i++){

3 /* check the experiment index*/

4 if(expt_idx == 0){

5 /* executes prefetchw instruction*/

6 prefetchw(addr_d0);}

7 /*let thread1 execute 1 iteration*/

8 wait_for_thread1();

9 }}

10

11void* thread1 (void* addr_d0){

12 for(int i = 0; i < 3000; i++){

13 /*let thread0 execute 1 iteration*/

14 wait_for_thread0();

15 result = read_and_time(addr_d0);

16 }}

17

18

19int main() {

20 /* open and map a file as read-only*/

21 int fd = open(FILE_NAME, O_RDONLY);

22 int* addr_d0 = mmap(fd, PROT_READ, …);

23

24 /*pin thread0 on core0 and run thread0*/

25 /*pin thread1 on core1 and run thread1*/

26 …

lstlistingCode snippet for verifying Observation 1.

###  II-B Data Prefetching

Data prefetching is a technique to boost CPU performance by fetching data or
instructions and place them closer to the CPU (e.g. from the LLC to L1 cache)
before they are used. Data prefetching can be performed in two ways: 1)
hardware prefetching, which is implemented in cache hardware and can be done
transparently to users by cache itself; 2) software prefetching, which needs
to be explicitly done by the programmer/compiler. Recent x86 CPUs offer many
different instructions for software prefetching including PREFETCHT0,
PREFETCHT1, PREFETCH2, PREFETCHNTA, and PREFETCHW111Some CPU models use
PREFETCHWT1 instead of PREFETCHW. These instructions are treated like hints to
tell the processor that a memory location is very likely to be accessed soon
[18]. Programmers/compilers can use these instructions to load data into
certain level of cache, in order to accelerate future accesses on the data.

###  II-C Cache Side Channel Attacks

Most cache attacks can be classified using two criteria [15]: 1) based on the
type of microarchitectural resource they exploit, and 2) based on whether they
require the attacker and the victim to be located on same physical core.

Resource Type. According to the microarchitectural resource utilized by the
attacker, we can classify cache attacks into contention-based attacks and
eviction-based attacks. In contention-based attacks, the attacker and the
victim contend for some limited shared hardware resource (e.g. the ring
interconnect [28] and cache banks [42]). The attacker can passively monitor
the latency of accessing the shared resource to infer the victim’s usage on
it, which may be related to the victim’s secrets. Contention-based attacks are
relatively limited because the side effects of the victim’s execution is only
visible while the victim is executing. Once the victim’s program completes,
the side effects can no longer be observed.

⬇

1void* thread0 (void* addr_d0, int expt_idx){

2 for(int i = 0; i < 3000; i++){

3 /* check the experiment index*/

4 if(expt_idx == 0){

5 read(addr_d0);}

6 /*let thread1 execute 1 iteration*/

7 wait_for_thread1()

8 }}

9

10void* thread1 (void* addr_d0){

11 for(int i = 0; i < 3000; i++){

12 /*let thread0 execute 1 iteration*/

13 wait_for_thread0();

14 int t1 = rdtscp(); /* read time stamp*/

15 prefetchw(addr_d0);

16 int result = rdtscp()-t1;

17 }}

18

19int main() {

20 /* open and map a file as read-only*/

21 int fd = open(FILE_NAME, O_RDONLY);

22 int* addr_D0 = mmap(fd, PROT_READ, …);

23

24 /*pin thread0 on core0 and run thread0*/

25 /*pin thread1 on core1 and run thread1*/

26 …

lstlistingCode snippet for verifying Observation 2.

Instead, in eviction-based attacks [43, 19, 27, 20, 38, 11, 40], the attacker
sets the shared microarchitectural resource in a certain state, then lets the
victim execute (which will potential change the state of the shared resource),
and later check the state of the shared resource again to infer the victim’s
behavior and the secrets related to the behavior. For example, in
Flush+Reload, the attacker flushes the victim’s data (which is shared with the
attacker) into memory and then waits for the victim’s execution. Later, the
attacker accesses this data and times the access to determine it is in cache
or memory: if it is in cache, it means the victim accessed the data, otherwise
the victim did not access. Compared to contention-based attacks, eviction-
based attacks are more powerful because the side effects of the victim is not
undone even when the victim completes. In addition, eviction-based attacks
typically have fine-granularity leakage: most eviction-based attacks can
disclose the victim’s access at cache line or cache set level; however, many
contention-based attacks [42, 28] can only leak at cache bank/slice level. The
attacks proposed in this work are eviction-based attacks.

Co-location Type. Cache attacks can also be classified into same-core attacks
and cross-core attacks based on how the attacker and the victim are co-located
on the processor. First, same-core attacks where the attacker is running on
the same physical core with the victim can target private caches [43, 38]. The
attacker evicts the victim’s data to the LLC and waits for the victim to bring
it back to the private cache to learn the victim’s access. Such attacks are
fast since they do not create off-chip memory accesses. But most of those
attacks require simultaneous multithreading (SMT) which significantly limits
the attacks. Second, cross-core attacks where the attacker can be located on a
different core than the victim are more generic. However, right now those
attack can only work on LLC and are thus much slower than private cache
attacks. We are the first to propose the first cross-core attack that works on
private caches.

##  III Characterizing Data Prefetching

Among all the mentioned prefetch instructions, PREFETCHW (or PREFETCHWT1 on
some CPU models) is slightly different than others because it not only brings
the data closer to CPU (i.e. into higher-level cache), but also changes the
coherence state of the data: PREFETCHW places the target data cache line into
L1 cache222[7] states that PREFETCHW can only be used on data but not
instructions. Thus, the cache line will be brought into L1 Dcache. and sets
the coherence state of this cache line to be M. According to [7], the role of
PREFETCHW is to accelerate future writes on the target cache line. As
explained in Section II, since the CPU core can directly write an L1 cache
line iff the state of this cache line is E/M. Thus, PREFETCHW pre-sets the
coherence state of the target cache line to M so that future writes on this
cache line will likely have an L1 hit. Note that we believe the reason
PREFETCHW changes the cache line state to M instead of E is that writing a
cache line in E state results in changing the state to M and thus has higher
latency than writing a cache line in M state.

PREFETCHW is available on most recent Intel and AMD processors, including both
server and PC processors, significantly improving performance for some
applications when used appropriately. However, we make two observations about
PREFETCHW on Intel processors, which can be leveraged to create security
vulnerabilities.

  * Observation 1 PREFETCHW successfully executes on data with read-only permission.

We observe this by monitoring the coherence state changes of the data using
timing information. Specifically, as shown in Listing II-A, we run a program
with two threads (belonging to one process, named $thread_{0}$ and
$thread_{1}$), and pin them on different physical cores (using
pthread_attr_setaffinity_np [2]). We use mmap [1] to map part of a system file
(i.e. glibc) as a read-only data block (in cache line size) in this program
and name it $d_{0}$: both threads can only read $d_{0}$333If any threads try
to write $d_{0}$, it will trigger a fault and terminate the entire program..
Both $thread_{0}$ and $thread_{1}$ consist of a for loop with the same amount
of iterations. In each iteration, $thread_{0}$ first executes, then waits for
$thread_{1}$ to execute. After $thread_{1}$ finishes this iteration, they both
move to the next iteration and repeat this procedure again. We use
pthread_mutex_lock [3] to ensure that in each iteration $thread_{0}$ and
$thread_{1}$ execute sequentially.

We run the code in Listing II-A twice: in the first experiment (i.e. expt_idx
= 0 in line 3), in each iteration of the for loop, $thread_{0}$ performs
PREFETCHW on $d_{0}$, and then $thread_{1}$ loads $d_{0}$ as well as timing
the load. In the second experiment (i.e. expt_idx = 1 in line 3), in each
iteration $thread_{0}$ stays idle and then $thread_{1}$ still loads $d_{0}$
and times the load.

Figure 4 shows the timing results from $thread_{1}$ in both of the above
experiments on an Intel core i7-7700K processor. Note that the similar results
have been observed on other Intel processors that support PREFETCHW. As one
can observe, in experiment 0 where $thread_{0}$ prefetches $d_{0}$, it takes
around 90 cycles for $thread_{1}$ to load $d_{0}$ after the prefetching. In
contrast, in experiment 1 where $thread_{0}$ stays idle, it only takes around
30 cycles for $thread_{1}$ to load $d_{0}$. This timing difference is caused
by the state of $d_{0}$: in experiment 0, every time when $thread_{0}$
prefetches, it will load $d_{0}$ to its private cache and set the coherence
state of it to be M. According to MESI protocol explained in Section II, this
will disable the copy of $d_{0}$ in the private cache of $thread_{1}$.
Therefore, when $thread_{1}$ later loads $d_{0}$, it will have an LLC hit
(this load will further change the state of $d_{0}$ from M to S, as explained
in Section II). However, in experiment 1, since $thread_{0}$ is not
prefetching, when $thread_{1}$ loads $d_{0}$, it will very likely have an L1
hit, which is much faster than an LLC hit.

The above results indicate that Intel processors do not perform write
permission checks when executing PREFETCHW, or that the permission check only
happens after the cache coherence state has already been changed (i.e. the
check is too late). This does not cause any error in the architecture level,
because PREFETCHW only has microarchitectural effects: although it can get a
cache line ready for future writes, if later the program without write
permission to this cache line actually really tries to write it, it will still
trigger a fault and likely terminate the process. However, later we will show
that this microarchitectural change caused by the lack of permission check (or
a late check) enables powerful covert channel and side channel attacks. Note
that we also performed the prior experiments on AMD processors, but we do not
observe any timing differences when the target data is read-only.

Figure 4: Timing measurement results in $thread_{1}$ of Listing II-A.

Figure 5: Timing measurement results in $thread_{1}$ of Listing II-C.

  * Observation 2 The execution time of PREFETCHW is related to the coherence state of the target cache line.

line0: the shared cache line between the sender and receiver

message[n]: the n-bit long message to transfer on the channel

Th0: the timing threshold to distinguish private cache hit and LLC hit

————————————————————————————–

Sender Algorithm

————————————————————————————–

// Send 1 bit in each iteration.

for  _$i=0;$ $i<n;$ $i++$_ do

sync_with_receiver(__) ;

if  _$message[i]==1$_ then

Prefetch line0;

else

Do not prefetch;

————————————————————————————–

Receiver Algorithm

————————————————————————————–

// Detect 1 bit in each iteration.

for  _$i=0;$ $i<n;$ $i++$_ do

sync_with_sender(__) ;

Access line0 and time the access;

if  _$access\\_time >Th0$_ then

Received a bit “1”;

else

Received a bit “0”;

Algorithm 1 Prefetch+Load Covert Channel

We observe this through a similar program with the one discussed, as shown in
Listing II-C. We still use two threads pinned on different physical cores, and
let them execute sequentially in each iteration of a for loop. Again, we run
the program twice: in the first experiment (expt_idx = 0 in line 3),
$thread_{0}$ loads $d_{0}$, and then $thread_{1}$ performs PREFETCHW on
$d_{0}$ and times the prefetching in each iteration. In the second experiment,
in each iteration, $thread_{0}$ stays idle and $thread_{1}$ still prefetches
and times the prefetching.

Figure 5 shows the execution time of PREFETCHW observed by $thread_{1}$ on our
Intel core i7-7700K processor in both experiments: in the first experiment, it
takes around 120 cycles for PREFETCHW to finish; however, in the second
experiment it only takes around 70 cycles. This is because in the first
experiment, after $thread_{0}$ loads $d_{0}$, the state of $d_{0}$ will become
S, and a copy of $d_{0}$ is filled into the private cache of $thread_{0}$.
Then when $thread_{1}$ prefetches, it needs to change the state from S to M
which means it has to inform the LLC to invalidate the copy of $d_{0}$ in the
private cache of $thread_{0}$. However, in the second experiment, since
$thread_{0}$ stays idle, when $thread_{1}$ prefetches, $d_{0}$ is already in M
state. Thus, in this case PREFETCHW does not cause any state change and
finishes much faster.

TABLE I: The evaluated processors for the two observations. Processor | Frequency | Observ.1 | Observ.2
---|---|---|---
Intel Xeon Platinum 8151 | 3.4GHz | ✓ | ✓
Intel Xeon Platinum 8124M | 3.0GHz | ✓ | ✓
Intel Xeon Platinum 8175M | 2.5GHz | ✓ | ✓
Intel Xeon Platinum 8259CL | 2.5GHz | ✓ | ✓
Intel Xeon Platinum 8275CL | 3.0GHz | ✓ | ✓
Intel Xeon Platinum 8375C | 2.9GHz | ✓ | ✗
Intel Xeon Silver 4114 | 2.2GHz | ✓ | ✓
Intel i7-6700K | 3.4GHz | ✓ | ✓
Intel i7-6800K | 3.4GHz | ✓ | ✓
Intel i7-7700K | 4.2GHz | ✓ | ✓
Intel i9-10900X | 3.7GHz | ✓ | ✓

line0: the shared cache line between the sender and receiver

message[n]: the n-bit long message to transfer on the channel

Th0: the timing threshold to distinguish private cache hit and LLC hit

————————————————————————————–

Sender Algorithm

————————————————————————————–

// Send 1 bit in each iteration.

for  _$i=0;$ $i<n;$ $i++$_ do

sync_with_receiver(__) ;

if  _$message[i]==1$_ then

Load line0;

else

Do not load;

————————————————————————————–

Receiver Algorithm

————————————————————————————–

// Detect 1 bit in each iteration.

for  _$i=0;$ $i<n;$ $i++$_ do

sync_with_sender(__) ;

Prefetch line0 and time the prefetch;

if  _$prefetch\\_time >Th0$_ then

Received a bit “1”;

else

Received a bit “0”;

Algorithm 2 Prefetch+Prefetch Covert Channel

We have tested these two observations on many Intel processors including all
available 1st/2nd/3rd Generation Intel Xeon Salable Processors on AWS EC2, and
five Intel desktop/server processors we own. As shown in Table I, Observation
1 is proved to be valid on all of these processors, and Observation 2 is valid
on most of these processors other than Intel Xeon Platinum 8375C. On this
processor, there is no difference on the execution time of PREFETCHW when the
target data is different coherence states: PREFETCHW always takes around 70
cycles.

In general, we believe that Observation 1 should be valid on all Intel
processors that support PREFETCHW, and Observation 2 should be valid on most
of them. Note that all 1st/2nd/3rd Generation Intel Xeon Scalable Processors
and Intel Core i7/i9 processors (other than the early generations) support
PREFETCHW.

##  IV Prefetch-based Covert Channel Attacks

Based on the observations in Section III, we build two covert channel attacks:
Prefetch+Load and Prefetch+Prefetch. In this section, we first introduce the
threat model, then discuss about the detail of each attack.

###  IV-A Threat Model

We assume that the two essential parties in the attack, the sender and
receiver, are two user-level processes that are running on the same processor
with multiple CPU cores. We further assume that the sender and receiver can
launch themselves on certain physical cores (e.g. using taskset [6]) so that
they can run on different cores in the processor. Similar with previous covert
channel attacks [40, 38, 19, 41], we also assume that the sender and receiver
can share read-only data implicitly (e.g. via page deduplication or shared
library). In addition, the sender and receiver should agree on pre-defined
channel protocols, including the synchronization, core allocation, data
encoding, and error correction protocols. We do not require the LLC to be
inclusive, our attacks can work on both inclusive and non-inclusive caches.

Note that the sender cannot directly reveal secrets (e.g. by writing them to a
file that is accessible to the receiver), since the system security manager
can easily detect such activity and prevent the sender from doing that. Thus,
the sender seeks to covertly communicate with the receiver to leak the secrets
out.

###  IV-B Prefetch+Load Attack

We build the first covert channel attack, Prefetch+Load following Observation
1. Algorithm 1 shows the the protocol details. In this attack, the sender and
receiver first agree on the cache line used to transfer information. Then in
each iteration of the transmission, the sender transmits a bit “1” by
performing prefechw on the shared data, and a bit “0” by idling; the receiver
loads the same cache line and times the load to determine it is a LLC hit or
private cache hit: the receiver receives a bit “1” when having an LLC hit, and
receives a bit “0” when having a private cache hit.

Note that different than the experiments in Section III, the sender and
receiver cannot synchronize by using pthread_mutex_lock, since they do not
belong to the same process. Thus, we let the sender and receiver synchronize
the transmission using time stamp counters (TSCs), as done in prior covert
channel attacks [38, 40, 41, 19]. As a simple example, if the sender is
sending 1 bit per 1000 cycles,the sender can send each bit when the current
CPU cycle is very close to a multiple of 1000 (e.g. less than 100 cycles, i.e.
$current\\_cycle\mod 1000<100$); the receiver can perform the load to detect
the bit when the current CPU cycle is in between two consecutive multiples of
1000, i.e. $500<current\\_cycle\mod 1000<600$.

Different than most previous cross-core cache attacks that require repeatedly
evicting the target cache line to off-chip memory devices (e.g. Flush+Reload),
in Prefetch+Load the target cache line is always kept in LLC, and the sender
sends signals by invalidating/not-invalidating the copy of this cache line in
the receiver’s private cache, so that the receiver will have L1/LLC hit when
loading this cache line. Our attack method has two benefits:

  * •

Higher bandwidth. Off-chip memory accesses are much slower than cache accesses
which have become the bottleneck on the bandwidth of the existing cross-core
cache attacks. Later we will show that since our attack does not evict the
target cache line to memory, our attack can achieve much-higher bandwidth than
existing cross-core cache attacks. Note that high-bandwidth attacks are
important because they may strengthen transient execution based attacks. In
Section VI we will show that with our new attacks Spectre v1 [24] may leak
more data within one speculative window.

  * •

Stealthier. Many defenses have been proposed to prevent cross-core cache
attacks. And a lot of these defenses are built by detecting the attack through
monitoring each process’s cache miss rate (which can be done using performance
counters) [12, 10, 25]. Since our attack does not trigger any LLC miss, our
cache miss rates of both the sender and receiver are lower than existing
attacks, which means we may be able to deploy the attack even on platforms
with those defenses available.

As far as we know, this is the first attack that can achieve cross-core
private cache eviction without evicting the data all the way to memory.

###  IV-C Prefetch+Prefetch Attack

Our second attack, Prefetch+Prefetch is developed based on Observation 2. As
shown in Algorithm 2 in each iteration of the attack, the sender transmits “1”
by loading the shared cache line, and transmits “0” by idling. After this, the
receiver performs PREFETCHW on the shared cache line and times the prefetching
to receive the bit: when the sender sends “1”, it takes longer for the
receiver to prefetch than when the receiver receives “0”. As explained
earlier, this is because when the sender sends “1” and loads the shared data,
the coherence state of the data will be changed to S. Then later when the
receiver prefetches, it will need to change the state to M, which introduces
latency on the prefetch instruction.

Prefetch+Prefetch follows the same synchronization method with Prefetch+Load.
In addition, Prefetch+Prefetch also has higher bandwidth and is stealthier
than previous cross-core cache attacks that rely on evicting data to memory.

##  V Prefetch-Based Side Channel Attacks

###  V-A Basic Idea and Assumptions

In the mentioned Prefetch+Prefetch covert channel attack, the sender is
sending the signal by “accessing/not accessing the shared data”. Thus, this
attack can be directly applied as a side channel attack to leak a victim’s
access pattern on the shared data by letting the victim to be the sender, and
the attacker to be the receiver. This leakage (on the victim’s access pattern)
is same with the leakage in many previous cache attacks [19, 41, 27, 43, 20].
However, Prefetch+Load cannot be directly employed as a side channel attack
because in this attack the sender is transmitting the signal by
prefetching/not prefetching the shared data, i.e. all we can leak as a side
channel attack is the victim’s (sender’s) prefetching pattern on the shared
data, which is very limited. To achieve a more general attack scenario, we
slightly modify this attack and build a new side channel attack named
Prefetch+Reload where the attacker (receiver) prefetches the shared data to
pre-set the coherence state, and then wait for the victim (sender) to access
this data. Later the attacker (receiver) reload the data (using a different
thread on a different core, explained later) and uses the timing information
to learn the data’s current coherence state and whether the victim (sender)
loaded this data and thus changed the coherence state. Different than
Prefetch+Load, in Prefetch+Reload, the attacker needs to have two threads
running on different cores.

Threat Model. We assume a similar threat model with the one for the covert
channel attacks. First, the attacker and the victim are two independent
processes running on a multi-core processor at the same time, and the attacker
can share read-only data with the victim (e.g. through shared library). In
addition, the attacker runs at user level and is able to figure out which core
the victim is using (e.g. by checking the usage of each core) and launch his
thread(s) on different core(s) than the victim. Our attacks do not require
SMT, but enabling SMT has no harm on our attacks.

For Prefetch+Reload, we assume the attacker has two threads that can execute
simultaneously; but for Prefetch+Prefetch we still assume there is only one
thread in the attacker’s process, which is same with the setup in covert
channel attacks in Section IV.

Figure 6: The details of the steps in Prefetch+Reload.

###  V-B Prefetch+Reload Attack

In this attack, we assume that the attacker controls two threads named Trojan
and Spy. Trojan and Spy should be located on different cores which are also
both different than the victim’s core, i.e. Trojan, Spy, and the victim all
run on different cores with each other. As mentioned in Section II, the
execution time of an LLC hit can be different when the cache line is in M
state than when it is in S state. This can be utilized by the attacker to
create observable cache state changes on victim’s cache access: Before the
victim accesses the shared cache line (between the victim and attacker),
Trojan executes prefetchw on this line, bringing it into his private cache,
and this will change the state of the cache line to M as well as invalidating
the copies of this cache line in the victim’s and Spy’s private caches (if
they exist), as shown in step ① in Figure 6. Then if the victim accesses this
cache line, according to MESI protocol, the state will be changed from M to S,
and a copy of this cache line in S state will be filled into the victim’s
private cache (step ② in the left path in Figure 6).

This coherence state change caused by the victim’s access cannot be observed
by Trojan: if Trojan later accesses (reloads) this cache line, he will get a
private cache hit no matter the victim accessed it or not because the victim’s
access will not invalidate the copy of this cache line in Trojan’s private
cache. Unfortunately, when having a private cache hit for data load, we cannot
distinguish the cache line was in M state or in S state through timing
information. However, this state change caused by the victim is observable to
Spy: since Trojan’s prefetching invalidated the copy of this cache line in
Spy’s private cache, now if Spy accesses this cache line, he will have an LLC
hit; if the victim accessed this cache line before Spy, Spy should now have an
LLC hit in S state, otherwise he should have an LLC hit in E state. Spy can
determine this cache line was in S state or M state by timing this access
(step ② in Figure 6). Again, this is because an LLC hit on a cache line in M
state will cause coherence state changes and thus takes longer to finish than
an LLC hit on a cache line in S state. Based on this, we build
Prefetch+Reload. Similar with previous cache attacks, each iteration in this
attack contains three steps, as shown in Figure 6:

  1. Step 1:

Trojan performs PREFETCHW on the target cache line, which sets the coherence
state of this cache line to M.

  2. Step 2:

The attacker waits for the victim’s behavior: if the victim accesses this
cache line, its state will be changed from M to S.

  3. Step 3:

Spy accesses this cache line and times the access to determine it was in M
state or S state. If the state was M, then the victim did not access this
cache line; if it was S, then the victim did access.

By repeating the above three steps, the attacker can leak the victim’s access
pattern on the shared cache line and infer some secrets related to it. On an
Intel i7-7700K processor, when the victim accessed the target cache line,
Spy’s access takes about 60 cycles to finish; when the victim did not access,
Spy’s access takes about 90 cycles to finish.

###  V-C Prefetch+Prefetch Attack

Following the Prefetch+Prefetch covert channel attack, we can also build the
Prefetch+Prefetch side channel attack where the attacker learns the victim’s
access by timing the prefetching. Again, the attacker and receiver should be
running on different cores so that the victim’s access will cause coherence
state change. In contrast with the Prefetch+Reload side channel attack, each
iteration in this attack only has two steps:

  1. Step 1:

The attacker prefetches the target shared cache line using PREFETCHW, and
times this operation to learn whether the victim accessed this cache line in
the last iteration.

  2. Step 2:

The attacker waits for the victim’s behavior.

As explained earlier in Section III, in Step 1 above, if the victim accessed
this cache line, PREFETCHW executes slower; if the victim did not access
PREFETCHW executes faster.

(a) Intel Core i7-6700K

(b) Intel Core i7-7700K

(c) Intel Xeon Platinum 8124M

(d) Intel Xeon Platinum 8151

Figure 7: The raw transmission rate and bit-error-rate of prefetch based
covert channel attacks on various Intel processors, reported using the average
results of 100 trials.

##  VI Evaluation

In this section, we evaluate the proposed covert channel attacks and side
channel attacks on modern Intel processors. For covert channel attacks, we
evaluate their transmission rates and compare them to the transmission rates
of previous covert channel attacks. For side channel attacks, we show how they
can be used to leak information from daily applications. In addition, we also
demonstrate that how our proposed attacks strengthen speculative execution
based attacks.

TABLE II: Specifications of the tested processors. Model |  Core i7-6700K |  Core i7-7700K |  Xeon Platinum 8124 |  Xeon Platinum 8151
---|---|---|---|---
Microarchitecture | Broadwell | Kaby lake | Skylake | Skylake
Num of cores | 6 | 4 | N/A444We use Intel Xeon Scalable processors on Amazon AWS EC2 platform, and we leased four cores on both texted processors for our experiments. | N/A
Frequency | 3.4GHz | 4.2GHz | 3.0GHz | 3.4GHz
LLC type | Inclusive | Inclusive | Non-inclusive | Non-inclusive
OS | Ubuntu 20.04.1

###  VI-A Evaluation of Prefetch Based Covert Channel Attacks

We implement Prefetch+Load, Prefetch+Prefetch, and Prefetch+Reload on four
Intel processors including two desktop processors and two server processors.
Note that although Prefetch+Reload is introduced as a side channel attack in
Section V, it can be used as a covert channel attack by letting the sender to
be the victim, and the receiver to be the attacker. Thus, we also evaluate
this attack in this section. The specifications of the tested processors are
listed in Table II. The two tested desktop processors use inclusive LLCs, and
the server processors have non-inclusive LLCs.

We use one shared cache line between the sender and receiver to transmit
secrets. Note that using more shared cache lines or using channel coding
techniques such as Error Correction Code (ECC) may further improve the channel
capacity [19, 40]; however, here we do not include them so that we can show
conservative results (i.e. the lower bounds).

We evaluate the bit error rates of our attacks under different transmission
rates to find the maximum transmission rate with an acceptable bit error rate.
As shown in Figure 7, when the transmission bandwidth is relatively low, the
bit error rates of all the three attacks are very low on each processor: the
bit error rates are lower than 0.6%. But the error rates will start to
increase dramatically once the transmission rate hits certain threshold. With
increasing the transmission rate, the error rate of Prefetch+Reload always
starts to rise earlier than the other two attacks. This is because in this
attack, two data accesses are involved in each iteration; however, only one
data access is involved in each iteration of the other two attacks. In
addition, the error rate of Prefetch+Prefetch and Prefetch+Load are always
very close under different transmission rates. Again, this is because same
amount of operations are involved in each iteration of these two attacks.

TABLE III: Transmission rate of the prefetch based channels. Model |  Core i7-6700K |  Core i7-7700K |  Xeon Platinum 8124 |  Xeon Platinum 8124
---|---|---|---|---
Frequency | 3.4GHz | 4.2GHz | 3.0GHz | 3.4GHz
Prefetch+Reload | 666KB/s | 790KB/s | 328KB/s | 495KB/s
Prefetch+Prefetch | 752KB/s | 864KB/s | 587KB/s | 637KB/s
Prefetch+Load | 743KB/s | 847KB/s | 562KB/s | 686KB/s

Table III shows the maximum transmission rates of the three attacks when the
bit error rate is less than 1%. On desktop processors, when the processor
frequency is 3.4GHz, the transmission rate can be 666KB/s for Prefetch+Reload,
752KB/s for Prefetch+Prefetch, and 743KB/s for Prefetch+Load; when the
processor frequency is 4.2GHz, the transmission rate can even be higher which
is 790KB/s for Prefetch+Reload, 864KB/s for Prefetch+Prefetch, and 847KB/s for
Prefetch+Load. To the best of our knowledge, our covert channel attacks are
faster than all existing covert channel attacks. As a reference, the ring
interconnect contention based attack [28] reported a very high transmission
rate which is 518KB/s on a 4GHz desktop processor. Flush+Reload and
Flush+Flush can achieve a transmission rate of 298KB/s and 496KB/s,
respectively on a 3.6GHz desktop processor [19]; the LRU attack can only
achieve 62.5KB/s on a 3.8GHz processor, although it is an L1 cache attack; the
Micro-op cache attack can only have a 31.3KB/s transmission rate across
processes.

###  VI-B Evaluation of Prefetch Based Side Channel Attacks

Side Channel Attack on Cryptographic Code. We focus on the cryptographic
libraries where the instruction access patterns are related to the
cryptographic key. More specifically we target the square-and-multiply
algorithm [16], shown as Algorithm 3. This algorithm is found in GnuPG
(version 1.4.13) for both RSA [31] and ElGamal [14] ciphers; leaking the
exponent e of this algorithm leaks the decryption key. As shown in Algorithm
3, in each iteration of the for loop, the algorithm first executes a sqr and
mod instruction. Then, if the bit is “1”, a mul and another mod instruction
will be executed which are otherwise skipped. Thus, by monitoring the access
pattern on the cache line that contains sqr and mul respectively, the attacker
is able to leak each bit of the exponent e and therefore the decryption key:
an access on sqr instruction indicates one round of the algorithm (i.e. one
bit of exponent e); if this access if followed by an access to mul, the
current bit is “1”, otherwise the bit is “0”.

Input: base $b$, modulo $m$, exponent $e=(e_{n1}...e_{0})_{2}$

Output: $b^{e}$ mod $m$

$r\leftarrow 1$

for  _$i=n-1;$ $i>=0;$ $i--$_ do

$r\leftarrow r^{2}\mod n$

if  _$e_{i}==1$_ then

$r\leftarrow r*b\mod n$

Algorithm 3 Square-and-multiply exponentiation

To deploy the attack, we use mmap to map the pages that contain sqr and mul
into the attacker’s address space. Note that during the execution of the
victim cryptographic library, the cache lines containing those instructions
will be brought into the victim core’s L1 instruction cache. However, since we
map the instruction pages as a data block in the attacker’s address space, the
same cache lines containing those instructions will be mapped to the
attacker’s L1 data cache. Thus, although PREFETCHW can only be used to
prefetch cache lines into L1 data cache. It can still be used to leak the
victim’s access pattern on instructions.

For simplicity, we only show the results of Prefetch+Reload on Intel Xeon
Platinum 8124M processor. However, we have obtained similar results running
both Prefetch+Prefetch and Prefetch+Reload on all the processors listed in
Table II. We use a waiting time of 1000 cycles between the prefetch and reload
steps. Figure 8 shows the time measurement of the reload step for 100 samples:
a higher reload latency (over 150 cycles) indicates that the victim did not
access the target cache line during the last waiting interval; a lower reload
latency (less than 100 cycles) means the victim did access. As mentioned
above, according to the algorithm, an access on sqr followed by an access on
mul indicates a bit “1”, and two consecutive accesses on sqr (one from the
current iteration, one from the next iteration) indicate a bit “0” (in the
current iteration). Thus, part of the exponent e shown in Figure 8 is
“00101011110”.

Figure 8: A segment of the access latencies measured in step 3 of
Prefetch+Reload while running GnuPG; a sequence of “00101011110” can be
deduced as part of the exponent “e”.

###  VI-C Prefetch Based Channels in Transient Execution Attacks

Transient execution attacks such as Spectre [24] utilize covert channels to
transfer the secret to the attacker (in a speculative window). Currently, most
transient execution attacks use the Flush+Reload channel since it is a clear,
simple, and high-bandwidth channel. Here we demonstrate that prefetch based
channels can also work with Spectre attacks to leak secrets.

Victim Code In Flush+Reload, the victim (sender) sends secrets to the attacker
by accessing certain cache line(s) and the secret is related to the
address(es) of the cache line(s). As in Prefetch+Reload and Prefetch+Prefetch
the victim (sender) is also sending secrets by cache accesses, the code
vulnerable to Spectre with Flush+Reload is also vulnerable to Spectre with
Prefetch+Reload and Prefetch+Prefetch, i.e. the victim remains the same. In
Linux v5.11-rc7, 37 gadgets are identified that can be used as the victim code
for Spectre v1 with Flush+Reload [24] to leak data [30].

With Flush+Reload, the data accesses perform by the victim to encode (i.e.
send) secrets in the speculative window are slow off-chip memory accesses. In
contrast, when using prefetch based channels, the victim’s speculative data
accesses are LLC accesses which are much faster. Thus, Spectre attacks with
prefetch channels require a smaller speculative window and thus may become
harder to defend. More importantly, within the same speculative window, when
using prefetch based channels the victim may be able to perform more data
accesses and thus leak more secrets to the attacker. Note that although this
is also true for L1 LRU attack [38] and L1 prime+Probe attack [43], those
attacks are not as practical because they are limited by the number of L1
cache sets: for a secret which contains more than one bit, multiple sets are
required to encode the secret.

⬇

if (x+n < arrary1_size)

{

y1 = array2[array1[x] * 4096];

y2 = array2[array1[x+1] * 4096];

…

yn = array2[array1[x+n] * 4096];

}

lstlistingSpectre v1 Code Example.

To show the benefit of using prefetch based channels, we take the Spectre v1
PoC code [5] and modify it accordingly such that Prefetch+Reload or
Prefetch+Prefetch is used in the attacker code. We then modify the victim code
to simulate the gadget where a branch instruction is followed by $n$ secrets
related data accesses. As shown in Listing VI-C, the secrets are array[x] to
array[x+n], when x is out of bound. We run this code on multiple processors
and collect that on each processor the amount of these $n$ accesses the victim
can speculatively perform in original Spectre v1, Spectre v1 with
Prefetch+Reload, and Spectre v1 with Prefetch+Prefetch, respectively, and draw
the histograms in Figure 9: on the desktop processors, when using prefetch
based channels the victim can perform up to 17 data accesses speculatively,
while the victim can only perform up to 8 accesses when using the Flush+Reload
channel. However, on server processors, the amount of speculative accesses
when using prefetch based channels are only slightly larger than the one using
the Flush+Reload channel. This is because on this processor, the latency of an
LLC hit in M state is very long and close to the latency of a memory access.

(a) Intel Core i7-6700K

(b) Intel Core i7-7700K

(c) Intel Xeon Platinum 8124M

(d) Intel Xeon Platinum 8151

Figure 9: The distributions of the amount of data accesses can be performed in
a speculative window when running the original Spectre v1, Spectre v1 with
Prefetch+Reload, and Spectre v1 with Prefetch+Prefetch, respectively.

##  VII Discussion

###  VII-A Related Works

In [18], the authors observed the prefetch instructions such as PREFETCHT0 in
a user-space process can execute on privileged data, and built an attack based
on this to bypass Address Space Layout Randomization (ASLR). However, very
recently this observation has been proved to be fundamentally incorrect by a
following work [34], and it has been shown that the fact that prefetch
instructions can change the microarchitectural state of privileged data is a
result of Spectre-BTB-SA-IP (branch target buffer, training in same address
space, and in-place), instead of prefetch instructions. The previous false
observation was made because in their implementation of the attack, there is
always a system call before the prefetch instruction. To ensure that our
observations are valid in Section III, we run those experiments without
locking pthreads (which involves system calls) and the results shown that our
observations still exist. In addition, [18] also observed that the execution
time of prefetch instructions is related to the cache states of the
translation levels, which is orthogonal with our observations.

In [40], the authors first observed that the execution time of an LLC hit is
longer when the target cache line is in E state than when it is in S state.
They further built a a variant of Flush+Reload in which the attacker pre-sets
the coherence state of the target cache line to E in each attack iteration by
flushing and reloading the data. This work also suffers from low bandwidth as
it works on LLC and requires off-chip memory accesses. Note that the bandwidth
of this attack is even lower than the original Flush+Reload attack.

Ring interconnect attack [28] is the first cross-core attack that does not
rely on off-chip memory accesses. However, this attack is a contention-based
attack instead of eviction-based attack, which is very limited as mentioned in
Section II. For example, in this attack, the attacker can only learn the LLC
slice the victim is accessing which typically contains at least 32K cache
lines. In contrast, our attacks can leak in cache-line granularity. More
importantly, this ring interconnect attack rely on the technique of cleansing
the victim’s private cache on interrupts which is not yet deployed on modern
processors.

###  VII-B Defending Prefetch Based Attacks

Intel classified our attacks as “classic side channel attacks” and suggested
defending it from software level following the instructions of developing
constant time algorithms in [4]. This could help defending known side channel
attacks such as the attack on RSA discussed in this work. However, without
fully understanding the details of hardware structures, it is very difficult
to have truly constant-time library. For example, the scalar point
multiplication algorithm in OpenSSL 1.1.0g was implemented in the form of
branchless Montgomery ladder. This implementation was known to have no secret-
dependent cache traces and thus should be resistant against cache attacks.
However, later it was proved that this implementation can be attacked by
monitoring the cache behavior of hardware prefetchers.

A simple way to defend all the proposed prefetch based attacks is to ensure
the permission check when executing PREFETCHW. Since this instruction is not
used by most applications, it should not significantly affect user
performance. However, it may affect applications whose performance relies on
this instruction: adding permission check may delay the execution of PREFETCHW
and make it executed too late that future writes on the data happen before the
data is ready.

Microarchitectural modifications can also be used to defend our attacks.
Prefetch+Prefetch can be simply defended by eliminating the timing difference
on the execution. Prefetch+Reload can be defended by hiding the timing
difference on LLC hit with different coherence states, e.g. by using lower-
granularity time stamp counters. Though Prefetch+Load is hard to defend, it is
less effective than the other two attacks since it cannot be used to leak
access patterns.

##  VIII Conclusion

In this paper, we proposed the first cross-core covert channel and side
channel attacks that work on private caches. We gave the key insight that
cache coherence protocol has the potential to be utilized to build such
attacks but it is challenging. Then we made two important observations on
PREFETCHW instruction which can help solving the challenges in our insight.
Then, based on the observations, we first built two covert channel attacks
which can achieve a transmission rate of 864KB/s and 847KB/s, respectively
with less than 1% error rate, the highest to date for cache covet channel
attacks. We then built two side channel attacks and showed that our attacks
can be used to leak information from real-world applications as well as
strengthen transient execution attacks.

## References

  * [1] “mmap(2) — linux manual page.” [Online]. Available: https://man7.org/linux/man-pages/man2/mmap.2.html
  * [2] “pthread_attr_setaffinity_np(3) — linux manual page.” [Online]. Available: https://man7.org/linux/man-pages/man3/pthread_attr_setaffinity_np.3.html
  * [3] “pthread_mutex_lock(3p) — linux manual page.” [Online]. Available: https://man7.org/linux/man-pages/man3/pthread_mutex_lock.3p.html
  * [4] “Security best practices for side channel resistance.” [Online]. Available: https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/best-practices/security-best-practices-side-channel-resistance.html
  * [5] “Spectrepoc.” [Online]. Available: https://github.com/crozone/SpectrePoC
  * [6] “taskset(1) — linux manual page.” [Online]. Available: https://man7.org/linux/man-pages/man1/taskset.1.html
  * [7] “3dnow! technology manual,” 2000. [Online]. Available: https://www.amd.com/system/files/TechDocs/21928.pdf
  * [8] “Intel quickpath architecture,” 2012. [Online]. Available: http://www.intel.com/pressroom/archive/reference/whitepaperQuickPath.pdf
  * [9] “Intel® xeon® scalable processor: The foundation of data centre innovation,” 2017. [Online]. Available: https://simplecore-ger.intel.com/swdevcon-uk/wp-content/uploads/sites/5/2017/10/UK-Dev-Con_Toby-Smith-Track-A_1000.pdf
  * [10] S. Briongos, G. Irazoqui, P. Malagón, and T. Eisenbarth, “Cacheshield: Detecting cache attacks through self-observation,” in _Proceedings of the Eighth ACM Conference on Data and Application Security and Privacy_ , 2018, pp. 224–235.
  * [11] S. Briongos, P. Malagón, J. M. Moya, and T. Eisenbarth, “Reload+ refresh: Abusing cache replacement policies to perform stealthy cache attacks,” in _29th $\\{$USENIX$\\}$ Security Symposium ($\\{$USENIX$\\}$ Security 20)_, 2020, pp. 1967–1984.
  * [12] J. Cho, T. Kim, S. Kim, M. Im, T. Kim, and Y. Shin, “Real-time detection for cache side channel attack using performance counter monitor,” _Applied Sciences_ , vol. 10, no. 3, p. 984, 2020.
  * [13] P. Conway and B. Hughes, “The amd opteron northbridge architecture,” _IEEE Micro_ , vol. 27, no. 2, p. 10–21, Mar. 2007.
  * [14] T. Elgamal, “A public key cryptosystem and a signature scheme based on discrete logarithms,” _IEEE Trans. Inf. Theor._ , vol. 31, no. 4, pp. 469–472, Sep. 2006.
  * [15] Q. Ge, Y. Yarom, D. Cock, and G. Heiser, “A survey of microarchitectural timing attacks and countermeasures on contemporary hardware,” _Journal of Cryptographic Engineering_ , vol. 8, no. 1, pp. 1–27, 2018.
  * [16] D. M. Gordon, “A survey of fast exponentiation methods,” _J. Algorithms_ , vol. 27, no. 1, pp. 129–146, Apr. 1998.
  * [17] B. Gras, K. Razavi, E. Bosman, H. Bos, and C. Giuffrida, “Aslr on the line: Practical cache attacks on the mmu,” in _NDSS_ , 2017.
  * [18] D. Gruss, C. Maurice, A. Fogh, M. Lipp, and S. Mangard, “Prefetch side-channel attacks: Bypassing smap and kernel aslr,” in _Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security_ , ser. CCS ’16. Association for Computing Machinery, 2016, p. 368–379.
  * [19] D. Gruss, C. Maurice, K. Wagner, and S. Mangard, “Flush+ flush: a fast and stealthy cache attack,” in _International Conference on Detection of Intrusions and Malware, and Vulnerability Assessment_. Springer, 2016, pp. 279–299.
  * [20] D. Gruss, R. Spreitzer, and S. Mangard, “Cache template attacks: Automating attacks on inclusive last-level caches,” in _24th $\\{$USENIX$\\}$ Security Symposium ($\\{$USENIX$\\}$ Security 15)_, 2015, pp. 897–912.
  * [21] D. Gullasch, E. Bangerter, and S. Krenn, “Cache games–bringing access-based cache attacks on aes to practice,” in _2011 IEEE Symposium on Security and Privacy_. IEEE, 2011, pp. 490–505.
  * [22] T. Hornby, “Side-channel attacks on everyday applications: Distinguishing inputs with flush+ reload,” _BlackHat USA_ , 2016.
  * [23] Y. Jang, S. Lee, and T. Kim, “Breaking kernel address space layout randomization with intel tsx,” in _Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security_ , ser. CCS ’16. ACM, 2016, pp. 380–392. [Online]. Available: http://doi.acm.org/10.1145/2976749.2978321
  * [24] P. Kocher, J. Horn, A. Fogh, , D. Genkin, D. Gruss, W. Haas, M. Hamburg, M. Lipp, S. Mangard, T. Prescher, M. Schwarz, and Y. Yarom, “Spectre attacks: Exploiting speculative execution,” in _40th IEEE Symposium on Security and Privacy (S &P’19)_, 2019.
  * [25] C. Li and J.-L. Gaudiot, “Detecting malicious attacks exploiting hardware vulnerabilities using performance counters,” in _2019 IEEE 43rd Annual Computer Software and Applications Conference (COMPSAC)_ , vol. 1. IEEE, 2019, pp. 588–597.
  * [26] M. Lipp, M. Schwarz, D. Gruss, T. Prescher, W. Haas, A. Fogh, J. Horn, S. Mangard, P. Kocher, D. Genkin, Y. Yarom, and M. Hamburg, “Meltdown: Reading kernel memory from user space,” in _27th USENIX Security Symposium (USENIX Security 18)_ , 2018.
  * [27] F. Liu, Y. Yarom, Q. Ge, G. Heiser, and R. B. Lee, “Last-level cache side-channel attacks are practical,” in _2015 IEEE symposium on security and privacy_. IEEE, 2015, pp. 605–622.
  * [28] R. Paccagnella, L. Luo, and C. W. Fletcher, “Lord of the ring (s): Side channel attacks on the $\\{$CPU$\\}$ on-chip ring interconnect are practical,” in _30th $\\{$USENIX$\\}$ Security Symposium ($\\{$USENIX$\\}$ Security 21)_, 2021.
  * [29] C. Percival, “Cache missing for fun and profit,” 2005.
  * [30] X. Ren, L. Moody, M. Taram, M. Jordan, D. M. Tullsen, and A. Venkat, “I see dead µops: Leaking secrets via intel/amd micro-op caches,” in _2021 ACM/IEEE 48th Annual International Symposium on Computer Architecture (ISCA)_ , 2021, pp. 361–374.
  * [31] R. L. Rivest, A. Shamir, and L. Adleman, “A method for obtaining digital signatures and public-key cryptosystems,” _Commun. ACM_ , vol. 21, no. 2, pp. 120–126, Feb. 1978.
  * [32] M. Schwarz, M. Lipp, D. Moghimi, J. Van Bulck, J. Stecklina, T. Prescher, and D. Gruss, “ZombieLoad: Cross-privilege-boundary data sampling,” in _CCS_ , 2019.
  * [33] M. Schwarz, M. Schwarzl, M. Lipp, J. Masters, and D. Gruss, _NetSpectre: Read Arbitrary Memory over Network_ , 09 2019, pp. 279–299.
  * [34] M. Schwarzl, T. Schuster, M. Schwarz, and D. Gruss, “Speculative dereferencing of registers: Reviving foreshadow,” _arXiv preprint arXiv:2008.02307_ , 2020\.
  * [35] D. Skarlatos, M. Yan, B. Gopireddy, R. Sprabery, J. Torrellas, and C. W. Fletcher, “Microscope: Enabling microarchitectural replay attacks,” in _Proceedings of the 46th International Symposium on Computer Architecture_ , ser. ISCA ’19, 2019, p. 318–331.
  * [36] J. Van Bulck, D. Moghimi, M. Schwarz, M. Lipp, M. Minkin, D. Genkin, Y. Yuval, B. Sunar, D. Gruss, and F. Piessens, “LVI: Hijacking Transient Execution through Microarchitectural Load Value Injection,” in _41th IEEE Symposium on Security and Privacy (S &P’20)_, 2020.
  * [37] S. van Schaik, A. Milburn, S. Österlund, P. Frigo, G. Maisuradze, K. Razavi, H. Bos, and C. Giuffrida, “RIDL: Rogue in-flight data load,” in _S &P_, May 2019.
  * [38] W. Xiong and J. Szefer, “Leaking information through cache lru states,” in _2020 IEEE International Symposium on High Performance Computer Architecture (HPCA)_. IEEE, 2020, pp. 139–152.
  * [39] M. Yan, R. Sprabery, B. Gopireddy, C. Fletcher, R. Campbell, and J. Torrellas, “Attack directories, not caches: Side channel attacks in a non-inclusive world,” in _2019 IEEE Symposium on Security and Privacy (SP)_. IEEE, 2019, pp. 888–904.
  * [40] F. Yao, M. Doroslovacki, and G. Venkataramani, “Are coherence protocol states vulnerable to information leakage?” in _2018 IEEE International Symposium on High Performance Computer Architecture (HPCA)_ , 2018, pp. 168–179.
  * [41] Y. Yarom and K. Falkner, “Flush+ reload: A high resolution, low noise, l3 cache side-channel attack,” in _23rd $\\{$USENIX$\\}$ Security Symposium ($\\{$USENIX$\\}$ Security 14)_, 2014, pp. 719–732.
  * [42] Y. Yarom, D. Genkin, and N. Heninger, “Cachebleed: a timing attack on openssl constant-time rsa,” _Journal of Cryptographic Engineering_ , vol. 7, no. 2, pp. 99–112, 2017.
  * [43] Y. A. Younis, K. Kifayat, Q. Shi, and B. Askwith, “A new prime and probe cache side-channel attack for cloud computing,” in _2015 IEEE International Conference on Computer and Information Technology; Ubiquitous Computing and Communications; Dependable, Autonomic and Secure Computing; Pervasive Intelligence and Computing_. IEEE, 2015, pp. 1718–1724.