Skip to content

L1TF (a.k.a. Foreshadow) Mitigation

Intel SGX is susceptible to a side channel attack in which an attacker can read the secrets of an enclave E by starting an enclave A on the same core as E. This attack only works for secrets of E stored in a L1 cache and if A and E run on the same core. This attack is referred to as enclave-to-enclave (E2E) attack. E2E does not work if E and A run on different cores since each core has its own dedicated L1 cache.

The current Intel microcode ensures that the L1 cache of a core is flushed when a thread leaves the enclave. In this way, if A runs after E, it will not be able to read any secrets from L1. Note that flushing L1 is an expensive operation. SCONE keeps the threads running inside of an enclave and in this way avoids the cost of flushing L1 on each system call.

The microcode update by Intel protects against L1TF only if hyperthreading is disabled! If enclave A would run on one hyperthread and E on the second hyperthread of the same core, A could still read the values of E stored in L1 using the L1TF side channel. Hence, you must also disable the hyperthreading inside of your BIOS1. If hyperthreading is switched on/off, is checked during attestation. In other words, one can ensure during attestation that the enclave is protected against L1TF.

According to the Intel documentation, an update microcode combined with switched off hyperthreading will fully mitigate L1TF and E2E for Intel SGX.

Microcode Update on Ubuntu

Note that the BIOS loads the microcode during boot. The operating system can load a newer version of the microcode, for example, in case there is no new microcode update available yet for your BIOS. In this case, the OS has to load the new microcode on each new boot.

On Ubuntu, you can upgrade your CPU to the newest microcode as follows:

TMPDIR=$(mktemp -d)
cd $TMPDIR
git clone https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git
cd Intel-Linux-Processor-Microcode-Data-Files
sudo apt-get update
sudo apt-get install -y intel-microcode
if [ -f /sys/devices/system/cpu/microcode/reload ] ; then
    if [ -d /lib/firmware ] ; then
        mkdir -p OLD
        cp -rf /lib/firmware/intel-ucode OLD
            sudo cp -rf intel-ucode /lib/firmware
        echo "1" | sudo tee /sys/devices/system/cpu/microcode/reload
    else
        echo "Error: microcode directory does not exist"
    fi
else
    echo "Error: is intel-micrcode really installed?"
fi

You can check that a new microcode was updated by executing:

dmesg | grep microcode

This will result in an output like

[  108.121907] microcode: CPU0 sig=0x506e3, pf=0x2, revision=0xc2
[  108.129335] microcode: CPU0 updated to revision 0xc6, date = 2018-04-17
[  108.129406] microcode: CPU1 sig=0x506e3, pf=0x2, revision=0xc2
[  108.129484] microcode: CPU1 updated to revision 0xc6, date = 2018-04-17
[  108.129539] microcode: CPU2 sig=0x506e3, pf=0x2, revision=0xc2
[  108.129611] microcode: CPU2 updated to revision 0xc6, date = 2018-04-17
[  108.129696] microcode: CPU3 sig=0x506e3, pf=0x2, revision=0xc2
[  108.129768] microcode: CPU3 updated to revision 0xc6, date = 2018-04-17
[  108.129816] microcode: CPU4 sig=0x506e3, pf=0x2, revision=0xc2
[  108.129905] microcode: CPU4 updated to revision 0xc6, date = 2018-04-17
[  108.129953] microcode: CPU5 sig=0x506e3, pf=0x2, revision=0xc2
[  108.130025] microcode: CPU5 updated to revision 0xc6, date = 2018-04-17
[  108.130070] microcode: CPU6 sig=0x506e3, pf=0x2, revision=0xc2
[  108.130142] microcode: CPU6 updated to revision 0xc6, date = 2018-04-17
[  108.130224] microcode: CPU7 sig=0x506e3, pf=0x2, revision=0xc2
[  108.130296] microcode: CPU7 updated to revision 0xc6, date = 2018-04-17
[  108.130298] microcode: Enabling Indirect Branch Prediction Barrier
[  108.130300] microcode: Enabling Indirect Branch Restricted Speculation

When you are sure that this works out, you can load this microcode during reboot as follows:

cat > /tmp/load-intel-ucode.sh << EOF
#!/bin/bash
echo "1" | sudo tee /sys/devices/system/cpu/microcode/reload
EOF
sudo mv /tmp/load-intel-ucode.sh /lib/firmware/load-intel-ucode.sh
chmod a+x /lib/firmware/load-intel-ucode.sh
# the following cmd pops up the editor: add the @reboot... via the editor
crontab -e
@reboot /lib/firmware/load-intel-ucode.sh

Checking CPU Features

CPU microcode updates that protects against side channels like L1TF are not available for all CPUs.

You can check that your microcode has up to date protection features enabled by executing the following:

docker run --rm sconecuratedimages/apps:check_cpuid

© scontain.com, August 2018. Questions or Suggestions?


  1. We have published an alternative to switching off hyperthreading in Usenix ATC 2018: we ensure that both hyperthreads of a core run inside of the same enclave.