Is hyperthreading dangerous?
[Posted May 17, 2005 by corbet]
Hyperthreading (or symmetric multi-threading) is a hardware technique used
to squeeze more performance out of modern processors. A hyperthreaded
processor appears, in many ways, to be a set of two independent
processors. These two processors share the same hardware, however,
with only the processor registers and other state-dependent information
being kept separate. Only one of the two CPUs can actually be executing at one
time. Hyperthreading helps performance because processors often stall,
waiting for memory accesses. When one processor in a hyperthreaded set
must wait, the other can be executing. Hyperthreading thus enables greater
utilization of the processor hardware; the resulting performance gains are
said to be anywhere from 5% to 30%, depending on the workload.
One of the resources shared by hyperthreaded processor sets is the memory
cache. This sharing has its advantages: if processes running on the two
processors are sharing memory, that memory need only be fetched into the
cache once. That kind of sharing happens often; shared libraries are one
obvious example. The shared cache also makes moving processes between
hyperthreaded processors an inexpensive operation, so keeping loads
balanced across the system is easier.
The sharing of caches between hyperthreaded processors is also, however,
the cause of a vulnerability identified in a heavily trailered report
by Colin Percival. The core of the problem is that, by measuring the
latency of specific memory accesses, a process can tell whether a given
memory location was represented in the processor cache or not. A hostile
process can load the cache with its own memory, wait a bit, then run tests
to see which locations have been evicted from the cache. From that
information, it can make inferences about which memory locations were
accessed by the sibling processor in the hyperthreaded set.
Two cooperating processes, running at different privilege levels, could
make use of the cache to set up a covert channel for communication. In a
highly secured system, these two processes might not be able to talk to
each other at all normally. With a covert channel in place, information
can be leaked from a privileged level to one less privileged, leading to
all kinds of dreadful consequences - for somebody. Most systems, however,
are not overly concerned about this sort of covert channel; there are
easier ways to deliberately leak information.
Mr. Percival, however, also shows how the vulnerability can be exploited to
obtain information from processes which are not cooperating. In
particular, he claims that it can be used to steal keys from cryptographic
applications. A number of crypto algorithms have data-dependent memory
access patterns; an attacker who can watch memory accesses can, for some
algorithms, derive the key which was being used. The exploit discussed in
the report attacks the OpenSSL key signing algorithm in this way.
The paper makes a number of recommendations on steps which can be taken to
mitigate this problem. The simplest is to simply disable hyperthreading;
on Linux systems, it is a simple matter of configuring out hyperthreading
support or booting with the noht option. Alternatively, the
kernel could take care not to schedule potentially unfriendly processes on
the same hyperthreaded set. Removing access to a high-resolution clock
would make the necessary timing information unavailable, thus defeating
such attacks. Cryptographic algorithms could be rewritten to avoid
data-dependent memory access patterns. Processors could be redesigned
to not share caches between hyperthreaded siblings, or to use a cache
eviction algorithm which makes it harder to determine which cache lines
have been removed.
The Linux scheduler could certainly be changed to defeat attempted cache-based
attacks on hyperthreaded processors, but the chances of that happening are
small. There are numerous obstacles to any sort of real-world exploit of
this vulnerability. The attacker must be able to run a CPU-intensive program on
the target system - without being noticed - and ensure that it remains on
the same hyperthreaded processor as the cryptographic process. The data
channel is noisy at best, and it will be made much more so by any other
processes running on the system. Timing the attack (knowing when the
target process is performing cryptographic calculations, rather than doing
something else) is tricky. Getting past all these roadblocks is
likely to keep a would-be key thief busy for some time.
In other words, there are almost certainly more effective ways of attacking
cryptographic applications. Closing this particular hole is unlikely to be
worth the trouble, extra complexity in the kernel, and performance impact
it would require. So this vulnerability, despite all the press it has
obtained, will probably not lead to any changes to the kernel in the near
future. Anybody who is truly worried about this problem will be best off
simply turning off hyperthreading for now. In the longer term, authors of
cryptographic code may find that they need to add avoidance of
data-dependent memory access patterns to their arsenal of techniques.
(
Log in to post comments)