mpx-mini-test.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616
  1. /*
  2. * mpx-mini-test.c: routines to test Intel MPX (Memory Protection eXtentions)
  3. *
  4. * Written by:
  5. * "Ren, Qiaowei" <qiaowei.ren@intel.com>
  6. * "Wei, Gang" <gang.wei@intel.com>
  7. * "Hansen, Dave" <dave.hansen@intel.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms and conditions of the GNU General Public License,
  11. * version 2.
  12. */
  13. /*
  14. * 2014-12-05: Dave Hansen: fixed all of the compiler warnings, and made sure
  15. * it works on 32-bit.
  16. */
  17. int inspect_every_this_many_mallocs = 100;
  18. int zap_all_every_this_many_mallocs = 1000;
  19. #define _GNU_SOURCE
  20. #define _LARGEFILE64_SOURCE
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <stdint.h>
  24. #include <stdbool.h>
  25. #include <signal.h>
  26. #include <assert.h>
  27. #include <stdlib.h>
  28. #include <ucontext.h>
  29. #include <sys/mman.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include <fcntl.h>
  33. #include <unistd.h>
  34. #include "mpx-hw.h"
  35. #include "mpx-debug.h"
  36. #include "mpx-mm.h"
  37. #ifndef __always_inline
  38. #define __always_inline inline __attribute__((always_inline)
  39. #endif
  40. #ifndef TEST_DURATION_SECS
  41. #define TEST_DURATION_SECS 3
  42. #endif
  43. void write_int_to(char *prefix, char *file, int int_to_write)
  44. {
  45. char buf[100];
  46. int fd = open(file, O_RDWR);
  47. int len;
  48. int ret;
  49. assert(fd >= 0);
  50. len = snprintf(buf, sizeof(buf), "%s%d", prefix, int_to_write);
  51. assert(len >= 0);
  52. assert(len < sizeof(buf));
  53. ret = write(fd, buf, len);
  54. assert(ret == len);
  55. ret = close(fd);
  56. assert(!ret);
  57. }
  58. void write_pid_to(char *prefix, char *file)
  59. {
  60. write_int_to(prefix, file, getpid());
  61. }
  62. void trace_me(void)
  63. {
  64. /* tracing events dir */
  65. #define TED "/sys/kernel/debug/tracing/events/"
  66. /*
  67. write_pid_to("common_pid=", TED "signal/filter");
  68. write_pid_to("common_pid=", TED "exceptions/filter");
  69. write_int_to("", TED "signal/enable", 1);
  70. write_int_to("", TED "exceptions/enable", 1);
  71. */
  72. write_pid_to("", "/sys/kernel/debug/tracing/set_ftrace_pid");
  73. write_int_to("", "/sys/kernel/debug/tracing/trace", 0);
  74. }
  75. #define test_failed() __test_failed(__FILE__, __LINE__)
  76. static void __test_failed(char *f, int l)
  77. {
  78. fprintf(stderr, "abort @ %s::%d\n", f, l);
  79. abort();
  80. }
  81. /* Error Printf */
  82. #define eprintf(args...) fprintf(stderr, args)
  83. #ifdef __i386__
  84. /* i386 directory size is 4MB */
  85. #define REG_IP_IDX REG_EIP
  86. #define REX_PREFIX
  87. #define XSAVE_OFFSET_IN_FPMEM sizeof(struct _libc_fpstate)
  88. /*
  89. * __cpuid() is from the Linux Kernel:
  90. */
  91. static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
  92. unsigned int *ecx, unsigned int *edx)
  93. {
  94. /* ecx is often an input as well as an output. */
  95. asm volatile(
  96. "push %%ebx;"
  97. "cpuid;"
  98. "mov %%ebx, %1;"
  99. "pop %%ebx"
  100. : "=a" (*eax),
  101. "=g" (*ebx),
  102. "=c" (*ecx),
  103. "=d" (*edx)
  104. : "0" (*eax), "2" (*ecx));
  105. }
  106. #else /* __i386__ */
  107. #define REG_IP_IDX REG_RIP
  108. #define REX_PREFIX "0x48, "
  109. #define XSAVE_OFFSET_IN_FPMEM 0
  110. /*
  111. * __cpuid() is from the Linux Kernel:
  112. */
  113. static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
  114. unsigned int *ecx, unsigned int *edx)
  115. {
  116. /* ecx is often an input as well as an output. */
  117. asm volatile(
  118. "cpuid;"
  119. : "=a" (*eax),
  120. "=b" (*ebx),
  121. "=c" (*ecx),
  122. "=d" (*edx)
  123. : "0" (*eax), "2" (*ecx));
  124. }
  125. #endif /* !__i386__ */
  126. struct xsave_hdr_struct {
  127. uint64_t xstate_bv;
  128. uint64_t reserved1[2];
  129. uint64_t reserved2[5];
  130. } __attribute__((packed));
  131. struct bndregs_struct {
  132. uint64_t bndregs[8];
  133. } __attribute__((packed));
  134. struct bndcsr_struct {
  135. uint64_t cfg_reg_u;
  136. uint64_t status_reg;
  137. } __attribute__((packed));
  138. struct xsave_struct {
  139. uint8_t fpu_sse[512];
  140. struct xsave_hdr_struct xsave_hdr;
  141. uint8_t ymm[256];
  142. uint8_t lwp[128];
  143. struct bndregs_struct bndregs;
  144. struct bndcsr_struct bndcsr;
  145. } __attribute__((packed));
  146. uint8_t __attribute__((__aligned__(64))) buffer[4096];
  147. struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer;
  148. uint8_t __attribute__((__aligned__(64))) test_buffer[4096];
  149. struct xsave_struct *xsave_test_buf = (struct xsave_struct *)test_buffer;
  150. uint64_t num_bnd_chk;
  151. static __always_inline void xrstor_state(struct xsave_struct *fx, uint64_t mask)
  152. {
  153. uint32_t lmask = mask;
  154. uint32_t hmask = mask >> 32;
  155. asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
  156. : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
  157. : "memory");
  158. }
  159. static __always_inline void xsave_state_1(void *_fx, uint64_t mask)
  160. {
  161. uint32_t lmask = mask;
  162. uint32_t hmask = mask >> 32;
  163. unsigned char *fx = _fx;
  164. asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
  165. : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
  166. : "memory");
  167. }
  168. static inline uint64_t xgetbv(uint32_t index)
  169. {
  170. uint32_t eax, edx;
  171. asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
  172. : "=a" (eax), "=d" (edx)
  173. : "c" (index));
  174. return eax + ((uint64_t)edx << 32);
  175. }
  176. static uint64_t read_mpx_status_sig(ucontext_t *uctxt)
  177. {
  178. memset(buffer, 0, sizeof(buffer));
  179. memcpy(buffer,
  180. (uint8_t *)uctxt->uc_mcontext.fpregs + XSAVE_OFFSET_IN_FPMEM,
  181. sizeof(struct xsave_struct));
  182. return xsave_buf->bndcsr.status_reg;
  183. }
  184. #include <pthread.h>
  185. static uint8_t *get_next_inst_ip(uint8_t *addr)
  186. {
  187. uint8_t *ip = addr;
  188. uint8_t sib;
  189. uint8_t rm;
  190. uint8_t mod;
  191. uint8_t base;
  192. uint8_t modrm;
  193. /* determine the prefix. */
  194. switch(*ip) {
  195. case 0xf2:
  196. case 0xf3:
  197. case 0x66:
  198. ip++;
  199. break;
  200. }
  201. /* look for rex prefix */
  202. if ((*ip & 0x40) == 0x40)
  203. ip++;
  204. /* Make sure we have a MPX instruction. */
  205. if (*ip++ != 0x0f)
  206. return addr;
  207. /* Skip the op code byte. */
  208. ip++;
  209. /* Get the modrm byte. */
  210. modrm = *ip++;
  211. /* Break it down into parts. */
  212. rm = modrm & 7;
  213. mod = (modrm >> 6);
  214. /* Init the parts of the address mode. */
  215. base = 8;
  216. /* Is it a mem mode? */
  217. if (mod != 3) {
  218. /* look for scaled indexed addressing */
  219. if (rm == 4) {
  220. /* SIB addressing */
  221. sib = *ip++;
  222. base = sib & 7;
  223. switch (mod) {
  224. case 0:
  225. if (base == 5)
  226. ip += 4;
  227. break;
  228. case 1:
  229. ip++;
  230. break;
  231. case 2:
  232. ip += 4;
  233. break;
  234. }
  235. } else {
  236. /* MODRM addressing */
  237. switch (mod) {
  238. case 0:
  239. /* DISP32 addressing, no base */
  240. if (rm == 5)
  241. ip += 4;
  242. break;
  243. case 1:
  244. ip++;
  245. break;
  246. case 2:
  247. ip += 4;
  248. break;
  249. }
  250. }
  251. }
  252. return ip;
  253. }
  254. #ifdef si_lower
  255. static inline void *__si_bounds_lower(siginfo_t *si)
  256. {
  257. return si->si_lower;
  258. }
  259. static inline void *__si_bounds_upper(siginfo_t *si)
  260. {
  261. return si->si_upper;
  262. }
  263. #else
  264. /*
  265. * This deals with old version of _sigfault in some distros:
  266. *
  267. old _sigfault:
  268. struct {
  269. void *si_addr;
  270. } _sigfault;
  271. new _sigfault:
  272. struct {
  273. void __user *_addr;
  274. int _trapno;
  275. short _addr_lsb;
  276. union {
  277. struct {
  278. void __user *_lower;
  279. void __user *_upper;
  280. } _addr_bnd;
  281. __u32 _pkey;
  282. };
  283. } _sigfault;
  284. *
  285. */
  286. static inline void **__si_bounds_hack(siginfo_t *si)
  287. {
  288. void *sigfault = &si->_sifields._sigfault;
  289. void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault);
  290. int *trapno = (int*)end_sigfault;
  291. /* skip _trapno and _addr_lsb */
  292. void **__si_lower = (void**)(trapno + 2);
  293. return __si_lower;
  294. }
  295. static inline void *__si_bounds_lower(siginfo_t *si)
  296. {
  297. return *__si_bounds_hack(si);
  298. }
  299. static inline void *__si_bounds_upper(siginfo_t *si)
  300. {
  301. return *(__si_bounds_hack(si) + 1);
  302. }
  303. #endif
  304. static int br_count;
  305. static int expected_bnd_index = -1;
  306. uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */
  307. unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS];
  308. /* Failed address bound checks: */
  309. #ifndef SEGV_BNDERR
  310. # define SEGV_BNDERR 3
  311. #endif
  312. /*
  313. * The kernel is supposed to provide some information about the bounds
  314. * exception in the siginfo. It should match what we have in the bounds
  315. * registers that we are checking against. Just check against the shadow copy
  316. * since it is easily available, and we also check that *it* matches the real
  317. * registers.
  318. */
  319. void check_siginfo_vs_shadow(siginfo_t* si)
  320. {
  321. int siginfo_ok = 1;
  322. void *shadow_lower = (void *)(unsigned long)shadow_plb[expected_bnd_index][0];
  323. void *shadow_upper = (void *)(unsigned long)shadow_plb[expected_bnd_index][1];
  324. if ((expected_bnd_index < 0) ||
  325. (expected_bnd_index >= NR_MPX_BOUNDS_REGISTERS)) {
  326. fprintf(stderr, "ERROR: invalid expected_bnd_index: %d\n",
  327. expected_bnd_index);
  328. exit(6);
  329. }
  330. if (__si_bounds_lower(si) != shadow_lower)
  331. siginfo_ok = 0;
  332. if (__si_bounds_upper(si) != shadow_upper)
  333. siginfo_ok = 0;
  334. if (!siginfo_ok) {
  335. fprintf(stderr, "ERROR: siginfo bounds do not match "
  336. "shadow bounds for register %d\n", expected_bnd_index);
  337. exit(7);
  338. }
  339. }
  340. void handler(int signum, siginfo_t *si, void *vucontext)
  341. {
  342. int i;
  343. ucontext_t *uctxt = vucontext;
  344. int trapno;
  345. unsigned long ip;
  346. dprintf1("entered signal handler\n");
  347. trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
  348. ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
  349. if (trapno == 5) {
  350. typeof(si->si_addr) *si_addr_ptr = &si->si_addr;
  351. uint64_t status = read_mpx_status_sig(uctxt);
  352. uint64_t br_reason = status & 0x3;
  353. br_count++;
  354. dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
  355. dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
  356. status, ip, br_reason);
  357. dprintf2("si_signo: %d\n", si->si_signo);
  358. dprintf2(" signum: %d\n", signum);
  359. dprintf2("info->si_code == SEGV_BNDERR: %d\n",
  360. (si->si_code == SEGV_BNDERR));
  361. dprintf2("info->si_code: %d\n", si->si_code);
  362. dprintf2("info->si_lower: %p\n", __si_bounds_lower(si));
  363. dprintf2("info->si_upper: %p\n", __si_bounds_upper(si));
  364. for (i = 0; i < 8; i++)
  365. dprintf3("[%d]: %p\n", i, si_addr_ptr[i]);
  366. switch (br_reason) {
  367. case 0: /* traditional BR */
  368. fprintf(stderr,
  369. "Undefined status with bound exception:%jx\n",
  370. status);
  371. exit(5);
  372. case 1: /* #BR MPX bounds exception */
  373. /* these are normal and we expect to see them */
  374. check_siginfo_vs_shadow(si);
  375. dprintf1("bounds exception (normal): status 0x%jx at %p si_addr: %p\n",
  376. status, (void *)ip, si->si_addr);
  377. num_bnd_chk++;
  378. uctxt->uc_mcontext.gregs[REG_IP_IDX] =
  379. (greg_t)get_next_inst_ip((uint8_t *)ip);
  380. break;
  381. case 2:
  382. fprintf(stderr, "#BR status == 2, missing bounds table,"
  383. "kernel should have handled!!\n");
  384. exit(4);
  385. break;
  386. default:
  387. fprintf(stderr, "bound check error: status 0x%jx at %p\n",
  388. status, (void *)ip);
  389. num_bnd_chk++;
  390. uctxt->uc_mcontext.gregs[REG_IP_IDX] =
  391. (greg_t)get_next_inst_ip((uint8_t *)ip);
  392. fprintf(stderr, "bound check error: si_addr %p\n", si->si_addr);
  393. exit(3);
  394. }
  395. } else if (trapno == 14) {
  396. eprintf("ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n",
  397. trapno, ip);
  398. eprintf("si_addr %p\n", si->si_addr);
  399. eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
  400. test_failed();
  401. } else {
  402. eprintf("unexpected trap %d! at 0x%lx\n", trapno, ip);
  403. eprintf("si_addr %p\n", si->si_addr);
  404. eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
  405. test_failed();
  406. }
  407. }
  408. static inline void cpuid_count(unsigned int op, int count,
  409. unsigned int *eax, unsigned int *ebx,
  410. unsigned int *ecx, unsigned int *edx)
  411. {
  412. *eax = op;
  413. *ecx = count;
  414. __cpuid(eax, ebx, ecx, edx);
  415. }
  416. #define XSTATE_CPUID 0x0000000d
  417. /*
  418. * List of XSAVE features Linux knows about:
  419. */
  420. enum xfeature_bit {
  421. XSTATE_BIT_FP,
  422. XSTATE_BIT_SSE,
  423. XSTATE_BIT_YMM,
  424. XSTATE_BIT_BNDREGS,
  425. XSTATE_BIT_BNDCSR,
  426. XSTATE_BIT_OPMASK,
  427. XSTATE_BIT_ZMM_Hi256,
  428. XSTATE_BIT_Hi16_ZMM,
  429. XFEATURES_NR_MAX,
  430. };
  431. #define XSTATE_FP (1 << XSTATE_BIT_FP)
  432. #define XSTATE_SSE (1 << XSTATE_BIT_SSE)
  433. #define XSTATE_YMM (1 << XSTATE_BIT_YMM)
  434. #define XSTATE_BNDREGS (1 << XSTATE_BIT_BNDREGS)
  435. #define XSTATE_BNDCSR (1 << XSTATE_BIT_BNDCSR)
  436. #define XSTATE_OPMASK (1 << XSTATE_BIT_OPMASK)
  437. #define XSTATE_ZMM_Hi256 (1 << XSTATE_BIT_ZMM_Hi256)
  438. #define XSTATE_Hi16_ZMM (1 << XSTATE_BIT_Hi16_ZMM)
  439. #define MPX_XSTATES (XSTATE_BNDREGS | XSTATE_BNDCSR) /* 0x18 */
  440. bool one_bit(unsigned int x, int bit)
  441. {
  442. return !!(x & (1<<bit));
  443. }
  444. void print_state_component(int state_bit_nr, char *name)
  445. {
  446. unsigned int eax, ebx, ecx, edx;
  447. unsigned int state_component_size;
  448. unsigned int state_component_supervisor;
  449. unsigned int state_component_user;
  450. unsigned int state_component_aligned;
  451. /* See SDM Section 13.2 */
  452. cpuid_count(XSTATE_CPUID, state_bit_nr, &eax, &ebx, &ecx, &edx);
  453. assert(eax || ebx || ecx);
  454. state_component_size = eax;
  455. state_component_supervisor = ((!ebx) && one_bit(ecx, 0));
  456. state_component_user = !one_bit(ecx, 0);
  457. state_component_aligned = one_bit(ecx, 1);
  458. printf("%8s: size: %d user: %d supervisor: %d aligned: %d\n",
  459. name,
  460. state_component_size, state_component_user,
  461. state_component_supervisor, state_component_aligned);
  462. }
  463. /* Intel-defined CPU features, CPUID level 0x00000001 (ecx) */
  464. #define XSAVE_FEATURE_BIT (26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
  465. #define OSXSAVE_FEATURE_BIT (27) /* XSAVE enabled in the OS */
  466. bool check_mpx_support(void)
  467. {
  468. unsigned int eax, ebx, ecx, edx;
  469. cpuid_count(1, 0, &eax, &ebx, &ecx, &edx);
  470. /* We can't do much without XSAVE, so just make these assert()'s */
  471. if (!one_bit(ecx, XSAVE_FEATURE_BIT)) {
  472. fprintf(stderr, "processor lacks XSAVE, can not run MPX tests\n");
  473. exit(0);
  474. }
  475. if (!one_bit(ecx, OSXSAVE_FEATURE_BIT)) {
  476. fprintf(stderr, "processor lacks OSXSAVE, can not run MPX tests\n");
  477. exit(0);
  478. }
  479. /* CPUs not supporting the XSTATE CPUID leaf do not support MPX */
  480. /* Is this redundant with the feature bit checks? */
  481. cpuid_count(0, 0, &eax, &ebx, &ecx, &edx);
  482. if (eax < XSTATE_CPUID) {
  483. fprintf(stderr, "processor lacks XSTATE CPUID leaf,"
  484. " can not run MPX tests\n");
  485. exit(0);
  486. }
  487. printf("XSAVE is supported by HW & OS\n");
  488. cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
  489. printf("XSAVE processor supported state mask: 0x%x\n", eax);
  490. printf("XSAVE OS supported state mask: 0x%jx\n", xgetbv(0));
  491. /* Make sure that the MPX states are enabled in in XCR0 */
  492. if ((eax & MPX_XSTATES) != MPX_XSTATES) {
  493. fprintf(stderr, "processor lacks MPX XSTATE(s), can not run MPX tests\n");
  494. exit(0);
  495. }
  496. /* Make sure the MPX states are supported by XSAVE* */
  497. if ((xgetbv(0) & MPX_XSTATES) != MPX_XSTATES) {
  498. fprintf(stderr, "MPX XSTATE(s) no enabled in XCR0, "
  499. "can not run MPX tests\n");
  500. exit(0);
  501. }
  502. print_state_component(XSTATE_BIT_BNDREGS, "BNDREGS");
  503. print_state_component(XSTATE_BIT_BNDCSR, "BNDCSR");
  504. return true;
  505. }
  506. void enable_mpx(void *l1base)
  507. {
  508. /* enable point lookup */
  509. memset(buffer, 0, sizeof(buffer));
  510. xrstor_state(xsave_buf, 0x18);
  511. xsave_buf->xsave_hdr.xstate_bv = 0x10;
  512. xsave_buf->bndcsr.cfg_reg_u = (unsigned long)l1base | 1;
  513. xsave_buf->bndcsr.status_reg = 0;
  514. dprintf2("bf xrstor\n");
  515. dprintf2("xsave cndcsr: status %jx, configu %jx\n",
  516. xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u);
  517. xrstor_state(xsave_buf, 0x18);
  518. dprintf2("after xrstor\n");
  519. xsave_state_1(xsave_buf, 0x18);
  520. dprintf1("xsave bndcsr: status %jx, configu %jx\n",
  521. xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u);
  522. }
  523. #include <sys/prctl.h>
  524. struct mpx_bounds_dir *bounds_dir_ptr;
  525. unsigned long __bd_incore(const char *func, int line)
  526. {
  527. unsigned long ret = nr_incore(bounds_dir_ptr, MPX_BOUNDS_DIR_SIZE_BYTES);
  528. return ret;
  529. }
  530. #define bd_incore() __bd_incore(__func__, __LINE__)
  531. void check_clear(void *ptr, unsigned long sz)
  532. {
  533. unsigned long *i;
  534. for (i = ptr; (void *)i < ptr + sz; i++) {
  535. if (*i) {
  536. dprintf1("%p is NOT clear at %p\n", ptr, i);
  537. assert(0);
  538. }
  539. }
  540. dprintf1("%p is clear for %lx\n", ptr, sz);
  541. }
  542. void check_clear_bd(void)
  543. {
  544. check_clear(bounds_dir_ptr, 2UL << 30);
  545. }
  546. #define USE_MALLOC_FOR_BOUNDS_DIR 1
  547. bool process_specific_init(void)
  548. {
  549. unsigned long size;
  550. unsigned long *dir;
  551. /* Guarantee we have the space to align it, add padding: */
  552. unsigned long pad = getpagesize();
  553. size = 2UL << 30; /* 2GB */
  554. if (sizeof(unsigned long) == 4)
  555. size = 4UL << 20; /* 4MB */
  556. dprintf1("trying to allocate %ld MB bounds directory\n", (size >> 20));
  557. if (USE_MALLOC_FOR_BOUNDS_DIR) {
  558. unsigned long _dir;
  559. dir = malloc(size + pad);
  560. assert(dir);
  561. _dir = (unsigned long)dir;
  562. _dir += 0xfffUL;
  563. _dir &= ~0xfffUL;
  564. dir = (void *)_dir;
  565. } else {
  566. /*
  567. * This makes debugging easier because the address
  568. * calculations are simpler:
  569. */
  570. dir = mmap((void *)0x200000000000, size + pad,
  571. PROT_READ|PROT_WRITE,
  572. MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
  573. if (dir == (void *)-1) {
  574. perror("unable to allocate bounds directory");
  575. abort();
  576. }
  577. check_clear(dir, size);
  578. }
  579. bounds_dir_ptr = (void *)dir;
  580. madvise(bounds_dir_ptr, size, MADV_NOHUGEPAGE);
  581. bd_incore();
  582. dprintf1("bounds directory: 0x%p -> 0x%p\n", bounds_dir_ptr,
  583. (char *)bounds_dir_ptr + size);
  584. check_clear(dir, size);
  585. enable_mpx(dir);
  586. check_clear(dir, size);
  587. if (prctl(43, 0, 0, 0, 0)) {
  588. printf("no MPX support\n");
  589. abort();
  590. return false;
  591. }
  592. return true;
  593. }
  594. bool process_specific_finish(void)
  595. {
  596. if (prctl(44)) {
  597. printf("no MPX support\n");
  598. return false;
  599. }
  600. return true;
  601. }
  602. void setup_handler()
  603. {
  604. int r, rs;
  605. struct sigaction newact;
  606. struct sigaction oldact;
  607. /* #BR is mapped to sigsegv */
  608. int signum = SIGSEGV;
  609. newact.sa_handler = 0; /* void(*)(int)*/
  610. newact.sa_sigaction = handler; /* void (*)(int, siginfo_t*, void *) */
  611. /*sigset_t - signals to block while in the handler */
  612. /* get the old signal mask. */
  613. rs = sigprocmask(SIG_SETMASK, 0, &newact.sa_mask);
  614. assert(rs == 0);
  615. /* call sa_sigaction, not sa_handler*/
  616. newact.sa_flags = SA_SIGINFO;
  617. newact.sa_restorer = 0; /* void(*)(), obsolete */
  618. r = sigaction(signum, &newact, &oldact);
  619. assert(r == 0);
  620. }
  621. void mpx_prepare(void)
  622. {
  623. dprintf2("%s()\n", __func__);
  624. setup_handler();
  625. process_specific_init();
  626. }
  627. void mpx_cleanup(void)
  628. {
  629. printf("%s(): %jd BRs. bye...\n", __func__, num_bnd_chk);
  630. process_specific_finish();
  631. }
  632. /*-------------- the following is test case ---------------*/
  633. #include <stdint.h>
  634. #include <stdbool.h>
  635. #include <stdlib.h>
  636. #include <stdio.h>
  637. #include <time.h>
  638. uint64_t num_lower_brs;
  639. uint64_t num_upper_brs;
  640. #define MPX_CONFIG_OFFSET 1024
  641. #define MPX_BOUNDS_OFFSET 960
  642. #define MPX_HEADER_OFFSET 512
  643. #define MAX_ADDR_TESTED (1<<28)
  644. #define TEST_ROUNDS 100
  645. /*
  646. 0F 1A /r BNDLDX-Load
  647. 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation
  648. 66 0F 1A /r BNDMOV bnd1, bnd2/m128
  649. 66 0F 1B /r BNDMOV bnd1/m128, bnd2
  650. F2 0F 1A /r BNDCU bnd, r/m64
  651. F2 0F 1B /r BNDCN bnd, r/m64
  652. F3 0F 1A /r BNDCL bnd, r/m64
  653. F3 0F 1B /r BNDMK bnd, m64
  654. */
  655. static __always_inline void xsave_state(void *_fx, uint64_t mask)
  656. {
  657. uint32_t lmask = mask;
  658. uint32_t hmask = mask >> 32;
  659. unsigned char *fx = _fx;
  660. asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
  661. : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
  662. : "memory");
  663. }
  664. static __always_inline void mpx_clear_bnd0(void)
  665. {
  666. long size = 0;
  667. void *ptr = NULL;
  668. /* F3 0F 1B /r BNDMK bnd, m64 */
  669. /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */
  670. asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t"
  671. : : "c" (ptr), "d" (size-1)
  672. : "memory");
  673. }
  674. static __always_inline void mpx_make_bound_helper(unsigned long ptr,
  675. unsigned long size)
  676. {
  677. /* F3 0F 1B /r BNDMK bnd, m64 */
  678. /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */
  679. asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t"
  680. : : "c" (ptr), "d" (size-1)
  681. : "memory");
  682. }
  683. static __always_inline void mpx_check_lowerbound_helper(unsigned long ptr)
  684. {
  685. /* F3 0F 1A /r NDCL bnd, r/m64 */
  686. /* f3 0f 1a 01 bndcl (%rcx),%bnd0 */
  687. asm volatile(".byte 0xf3,0x0f,0x1a,0x01\n\t"
  688. : : "c" (ptr)
  689. : "memory");
  690. }
  691. static __always_inline void mpx_check_upperbound_helper(unsigned long ptr)
  692. {
  693. /* F2 0F 1A /r BNDCU bnd, r/m64 */
  694. /* f2 0f 1a 01 bndcu (%rcx),%bnd0 */
  695. asm volatile(".byte 0xf2,0x0f,0x1a,0x01\n\t"
  696. : : "c" (ptr)
  697. : "memory");
  698. }
  699. static __always_inline void mpx_movbndreg_helper()
  700. {
  701. /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */
  702. /* 66 0f 1b c2 bndmov %bnd0,%bnd2 */
  703. asm volatile(".byte 0x66,0x0f,0x1b,0xc2\n\t");
  704. }
  705. static __always_inline void mpx_movbnd2mem_helper(uint8_t *mem)
  706. {
  707. /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */
  708. /* 66 0f 1b 01 bndmov %bnd0,(%rcx) */
  709. asm volatile(".byte 0x66,0x0f,0x1b,0x01\n\t"
  710. : : "c" (mem)
  711. : "memory");
  712. }
  713. static __always_inline void mpx_movbnd_from_mem_helper(uint8_t *mem)
  714. {
  715. /* 66 0F 1A /r BNDMOV bnd1, bnd2/m128 */
  716. /* 66 0f 1a 01 bndmov (%rcx),%bnd0 */
  717. asm volatile(".byte 0x66,0x0f,0x1a,0x01\n\t"
  718. : : "c" (mem)
  719. : "memory");
  720. }
  721. static __always_inline void mpx_store_dsc_helper(unsigned long ptr_addr,
  722. unsigned long ptr_val)
  723. {
  724. /* 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation */
  725. /* 0f 1b 04 11 bndstx %bnd0,(%rcx,%rdx,1) */
  726. asm volatile(".byte 0x0f,0x1b,0x04,0x11\n\t"
  727. : : "c" (ptr_addr), "d" (ptr_val)
  728. : "memory");
  729. }
  730. static __always_inline void mpx_load_dsc_helper(unsigned long ptr_addr,
  731. unsigned long ptr_val)
  732. {
  733. /* 0F 1A /r BNDLDX-Load */
  734. /*/ 0f 1a 04 11 bndldx (%rcx,%rdx,1),%bnd0 */
  735. asm volatile(".byte 0x0f,0x1a,0x04,0x11\n\t"
  736. : : "c" (ptr_addr), "d" (ptr_val)
  737. : "memory");
  738. }
  739. void __print_context(void *__print_xsave_buffer, int line)
  740. {
  741. uint64_t *bounds = (uint64_t *)(__print_xsave_buffer + MPX_BOUNDS_OFFSET);
  742. uint64_t *cfg = (uint64_t *)(__print_xsave_buffer + MPX_CONFIG_OFFSET);
  743. int i;
  744. eprintf("%s()::%d\n", "print_context", line);
  745. for (i = 0; i < 4; i++) {
  746. eprintf("bound[%d]: 0x%016lx 0x%016lx(0x%016lx)\n", i,
  747. (unsigned long)bounds[i*2],
  748. ~(unsigned long)bounds[i*2+1],
  749. (unsigned long)bounds[i*2+1]);
  750. }
  751. eprintf("cpcfg: %jx cpstatus: %jx\n", cfg[0], cfg[1]);
  752. }
  753. #define print_context(x) __print_context(x, __LINE__)
  754. #ifdef DEBUG
  755. #define dprint_context(x) print_context(x)
  756. #else
  757. #define dprint_context(x) do{}while(0)
  758. #endif
  759. void init()
  760. {
  761. int i;
  762. srand((unsigned int)time(NULL));
  763. for (i = 0; i < 4; i++) {
  764. shadow_plb[i][0] = 0;
  765. shadow_plb[i][1] = ~(unsigned long)0;
  766. }
  767. }
  768. long int __mpx_random(int line)
  769. {
  770. #ifdef NOT_SO_RANDOM
  771. static long fake = 722122311;
  772. fake += 563792075;
  773. return fakse;
  774. #else
  775. return random();
  776. #endif
  777. }
  778. #define mpx_random() __mpx_random(__LINE__)
  779. uint8_t *get_random_addr()
  780. {
  781. uint8_t*addr = (uint8_t *)(unsigned long)(rand() % MAX_ADDR_TESTED);
  782. return (addr - (unsigned long)addr % sizeof(uint8_t *));
  783. }
  784. static inline bool compare_context(void *__xsave_buffer)
  785. {
  786. uint64_t *bounds = (uint64_t *)(__xsave_buffer + MPX_BOUNDS_OFFSET);
  787. int i;
  788. for (i = 0; i < 4; i++) {
  789. dprintf3("shadow[%d]{%016lx/%016lx}\nbounds[%d]{%016lx/%016lx}\n",
  790. i, (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1],
  791. i, (unsigned long)bounds[i*2], ~(unsigned long)bounds[i*2+1]);
  792. if ((shadow_plb[i][0] != bounds[i*2]) ||
  793. (shadow_plb[i][1] != ~(unsigned long)bounds[i*2+1])) {
  794. eprintf("ERROR comparing shadow to real bound register %d\n", i);
  795. eprintf("shadow{0x%016lx/0x%016lx}\nbounds{0x%016lx/0x%016lx}\n",
  796. (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1],
  797. (unsigned long)bounds[i*2], (unsigned long)bounds[i*2+1]);
  798. return false;
  799. }
  800. }
  801. return true;
  802. }
  803. void mkbnd_shadow(uint8_t *ptr, int index, long offset)
  804. {
  805. uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]);
  806. uint64_t *upper = (uint64_t *)&(shadow_plb[index][1]);
  807. *lower = (unsigned long)ptr;
  808. *upper = (unsigned long)ptr + offset - 1;
  809. }
  810. void check_lowerbound_shadow(uint8_t *ptr, int index)
  811. {
  812. uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]);
  813. if (*lower > (uint64_t)(unsigned long)ptr)
  814. num_lower_brs++;
  815. else
  816. dprintf1("LowerBoundChk passed:%p\n", ptr);
  817. }
  818. void check_upperbound_shadow(uint8_t *ptr, int index)
  819. {
  820. uint64_t upper = *(uint64_t *)&(shadow_plb[index][1]);
  821. if (upper < (uint64_t)(unsigned long)ptr)
  822. num_upper_brs++;
  823. else
  824. dprintf1("UpperBoundChk passed:%p\n", ptr);
  825. }
  826. __always_inline void movbndreg_shadow(int src, int dest)
  827. {
  828. shadow_plb[dest][0] = shadow_plb[src][0];
  829. shadow_plb[dest][1] = shadow_plb[src][1];
  830. }
  831. __always_inline void movbnd2mem_shadow(int src, unsigned long *dest)
  832. {
  833. unsigned long *lower = (unsigned long *)&(shadow_plb[src][0]);
  834. unsigned long *upper = (unsigned long *)&(shadow_plb[src][1]);
  835. *dest = *lower;
  836. *(dest+1) = *upper;
  837. }
  838. __always_inline void movbnd_from_mem_shadow(unsigned long *src, int dest)
  839. {
  840. unsigned long *lower = (unsigned long *)&(shadow_plb[dest][0]);
  841. unsigned long *upper = (unsigned long *)&(shadow_plb[dest][1]);
  842. *lower = *src;
  843. *upper = *(src+1);
  844. }
  845. __always_inline void stdsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val)
  846. {
  847. shadow_map[0] = (unsigned long)shadow_plb[index][0];
  848. shadow_map[1] = (unsigned long)shadow_plb[index][1];
  849. shadow_map[2] = (unsigned long)ptr_val;
  850. dprintf3("%s(%d, %p, %p) set shadow map[2]: %p\n", __func__,
  851. index, ptr, ptr_val, ptr_val);
  852. /*ptr ignored */
  853. }
  854. void lddsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val)
  855. {
  856. uint64_t lower = shadow_map[0];
  857. uint64_t upper = shadow_map[1];
  858. uint8_t *value = (uint8_t *)shadow_map[2];
  859. if (value != ptr_val) {
  860. dprintf2("%s(%d, %p, %p) init shadow bounds[%d] "
  861. "because %p != %p\n", __func__, index, ptr,
  862. ptr_val, index, value, ptr_val);
  863. shadow_plb[index][0] = 0;
  864. shadow_plb[index][1] = ~(unsigned long)0;
  865. } else {
  866. shadow_plb[index][0] = lower;
  867. shadow_plb[index][1] = upper;
  868. }
  869. /* ptr ignored */
  870. }
  871. static __always_inline void mpx_test_helper0(uint8_t *buf, uint8_t *ptr)
  872. {
  873. mpx_make_bound_helper((unsigned long)ptr, 0x1800);
  874. }
  875. static __always_inline void mpx_test_helper0_shadow(uint8_t *buf, uint8_t *ptr)
  876. {
  877. mkbnd_shadow(ptr, 0, 0x1800);
  878. }
  879. static __always_inline void mpx_test_helper1(uint8_t *buf, uint8_t *ptr)
  880. {
  881. /* these are hard-coded to check bnd0 */
  882. expected_bnd_index = 0;
  883. mpx_check_lowerbound_helper((unsigned long)(ptr-1));
  884. mpx_check_upperbound_helper((unsigned long)(ptr+0x1800));
  885. /* reset this since we do not expect any more bounds exceptions */
  886. expected_bnd_index = -1;
  887. }
  888. static __always_inline void mpx_test_helper1_shadow(uint8_t *buf, uint8_t *ptr)
  889. {
  890. check_lowerbound_shadow(ptr-1, 0);
  891. check_upperbound_shadow(ptr+0x1800, 0);
  892. }
  893. static __always_inline void mpx_test_helper2(uint8_t *buf, uint8_t *ptr)
  894. {
  895. mpx_make_bound_helper((unsigned long)ptr, 0x1800);
  896. mpx_movbndreg_helper();
  897. mpx_movbnd2mem_helper(buf);
  898. mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800);
  899. }
  900. static __always_inline void mpx_test_helper2_shadow(uint8_t *buf, uint8_t *ptr)
  901. {
  902. mkbnd_shadow(ptr, 0, 0x1800);
  903. movbndreg_shadow(0, 2);
  904. movbnd2mem_shadow(0, (unsigned long *)buf);
  905. mkbnd_shadow(ptr+0x12, 0, 0x1800);
  906. }
  907. static __always_inline void mpx_test_helper3(uint8_t *buf, uint8_t *ptr)
  908. {
  909. mpx_movbnd_from_mem_helper(buf);
  910. }
  911. static __always_inline void mpx_test_helper3_shadow(uint8_t *buf, uint8_t *ptr)
  912. {
  913. movbnd_from_mem_shadow((unsigned long *)buf, 0);
  914. }
  915. static __always_inline void mpx_test_helper4(uint8_t *buf, uint8_t *ptr)
  916. {
  917. mpx_store_dsc_helper((unsigned long)buf, (unsigned long)ptr);
  918. mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800);
  919. }
  920. static __always_inline void mpx_test_helper4_shadow(uint8_t *buf, uint8_t *ptr)
  921. {
  922. stdsc_shadow(0, buf, ptr);
  923. mkbnd_shadow(ptr+0x12, 0, 0x1800);
  924. }
  925. static __always_inline void mpx_test_helper5(uint8_t *buf, uint8_t *ptr)
  926. {
  927. mpx_load_dsc_helper((unsigned long)buf, (unsigned long)ptr);
  928. }
  929. static __always_inline void mpx_test_helper5_shadow(uint8_t *buf, uint8_t *ptr)
  930. {
  931. lddsc_shadow(0, buf, ptr);
  932. }
  933. #define NR_MPX_TEST_FUNCTIONS 6
  934. /*
  935. * For compatibility reasons, MPX will clear the bounds registers
  936. * when you make function calls (among other things). We have to
  937. * preserve the registers in between calls to the "helpers" since
  938. * they build on each other.
  939. *
  940. * Be very careful not to make any function calls inside the
  941. * helpers, or anywhere else beween the xrstor and xsave.
  942. */
  943. #define run_helper(helper_nr, buf, buf_shadow, ptr) do { \
  944. xrstor_state(xsave_test_buf, flags); \
  945. mpx_test_helper##helper_nr(buf, ptr); \
  946. xsave_state(xsave_test_buf, flags); \
  947. mpx_test_helper##helper_nr##_shadow(buf_shadow, ptr); \
  948. } while (0)
  949. static void run_helpers(int nr, uint8_t *buf, uint8_t *buf_shadow, uint8_t *ptr)
  950. {
  951. uint64_t flags = 0x18;
  952. dprint_context(xsave_test_buf);
  953. switch (nr) {
  954. case 0:
  955. run_helper(0, buf, buf_shadow, ptr);
  956. break;
  957. case 1:
  958. run_helper(1, buf, buf_shadow, ptr);
  959. break;
  960. case 2:
  961. run_helper(2, buf, buf_shadow, ptr);
  962. break;
  963. case 3:
  964. run_helper(3, buf, buf_shadow, ptr);
  965. break;
  966. case 4:
  967. run_helper(4, buf, buf_shadow, ptr);
  968. break;
  969. case 5:
  970. run_helper(5, buf, buf_shadow, ptr);
  971. break;
  972. default:
  973. test_failed();
  974. break;
  975. }
  976. dprint_context(xsave_test_buf);
  977. }
  978. unsigned long buf_shadow[1024]; /* used to check load / store descriptors */
  979. extern long inspect_me(struct mpx_bounds_dir *bounds_dir);
  980. long cover_buf_with_bt_entries(void *buf, long buf_len)
  981. {
  982. int i;
  983. long nr_to_fill;
  984. int ratio = 1000;
  985. unsigned long buf_len_in_ptrs;
  986. /* Fill about 1/100 of the space with bt entries */
  987. nr_to_fill = buf_len / (sizeof(unsigned long) * ratio);
  988. if (!nr_to_fill)
  989. dprintf3("%s() nr_to_fill: %ld\n", __func__, nr_to_fill);
  990. /* Align the buffer to pointer size */
  991. while (((unsigned long)buf) % sizeof(void *)) {
  992. buf++;
  993. buf_len--;
  994. }
  995. /* We are storing pointers, so make */
  996. buf_len_in_ptrs = buf_len / sizeof(void *);
  997. for (i = 0; i < nr_to_fill; i++) {
  998. long index = (mpx_random() % buf_len_in_ptrs);
  999. void *ptr = buf + index * sizeof(unsigned long);
  1000. unsigned long ptr_addr = (unsigned long)ptr;
  1001. /* ptr and size can be anything */
  1002. mpx_make_bound_helper((unsigned long)ptr, 8);
  1003. /*
  1004. * take bnd0 and put it in to bounds tables "buf + index" is an
  1005. * address inside the buffer where we are pretending that we
  1006. * are going to put a pointer We do not, though because we will
  1007. * never load entries from the table, so it doesn't matter.
  1008. */
  1009. mpx_store_dsc_helper(ptr_addr, (unsigned long)ptr);
  1010. dprintf4("storing bound table entry for %lx (buf start @ %p)\n",
  1011. ptr_addr, buf);
  1012. }
  1013. return nr_to_fill;
  1014. }
  1015. unsigned long align_down(unsigned long alignme, unsigned long align_to)
  1016. {
  1017. return alignme & ~(align_to-1);
  1018. }
  1019. unsigned long align_up(unsigned long alignme, unsigned long align_to)
  1020. {
  1021. return (alignme + align_to - 1) & ~(align_to-1);
  1022. }
  1023. /*
  1024. * Using 1MB alignment guarantees that each no allocation
  1025. * will overlap with another's bounds tables.
  1026. *
  1027. * We have to cook our own allocator here. malloc() can
  1028. * mix other allocation with ours which means that even
  1029. * if we free all of our allocations, there might still
  1030. * be bounds tables for the *areas* since there is other
  1031. * valid memory there.
  1032. *
  1033. * We also can't use malloc() because a free() of an area
  1034. * might not free it back to the kernel. We want it
  1035. * completely unmapped an malloc() does not guarantee
  1036. * that.
  1037. */
  1038. #ifdef __i386__
  1039. long alignment = 4096;
  1040. long sz_alignment = 4096;
  1041. #else
  1042. long alignment = 1 * MB;
  1043. long sz_alignment = 1 * MB;
  1044. #endif
  1045. void *mpx_mini_alloc(unsigned long sz)
  1046. {
  1047. unsigned long long tries = 0;
  1048. static void *last;
  1049. void *ptr;
  1050. void *try_at;
  1051. sz = align_up(sz, sz_alignment);
  1052. try_at = last + alignment;
  1053. while (1) {
  1054. ptr = mmap(try_at, sz, PROT_READ|PROT_WRITE,
  1055. MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
  1056. if (ptr == (void *)-1)
  1057. return NULL;
  1058. if (ptr == try_at)
  1059. break;
  1060. munmap(ptr, sz);
  1061. try_at += alignment;
  1062. #ifdef __i386__
  1063. /*
  1064. * This isn't quite correct for 32-bit binaries
  1065. * on 64-bit kernels since they can use the
  1066. * entire 32-bit address space, but it's close
  1067. * enough.
  1068. */
  1069. if (try_at > (void *)0xC0000000)
  1070. #else
  1071. if (try_at > (void *)0x0000800000000000)
  1072. #endif
  1073. try_at = (void *)0x0;
  1074. if (!(++tries % 10000))
  1075. dprintf1("stuck in %s(), tries: %lld\n", __func__, tries);
  1076. continue;
  1077. }
  1078. last = ptr;
  1079. dprintf3("mpx_mini_alloc(0x%lx) returning: %p\n", sz, ptr);
  1080. return ptr;
  1081. }
  1082. void mpx_mini_free(void *ptr, long sz)
  1083. {
  1084. dprintf2("%s() ptr: %p\n", __func__, ptr);
  1085. if ((unsigned long)ptr > 0x100000000000) {
  1086. dprintf1("uh oh !!!!!!!!!!!!!!! pointer too high: %p\n", ptr);
  1087. test_failed();
  1088. }
  1089. sz = align_up(sz, sz_alignment);
  1090. dprintf3("%s() ptr: %p before munmap\n", __func__, ptr);
  1091. munmap(ptr, sz);
  1092. dprintf3("%s() ptr: %p DONE\n", __func__, ptr);
  1093. }
  1094. #define NR_MALLOCS 100
  1095. struct one_malloc {
  1096. char *ptr;
  1097. int nr_filled_btes;
  1098. unsigned long size;
  1099. };
  1100. struct one_malloc mallocs[NR_MALLOCS];
  1101. void free_one_malloc(int index)
  1102. {
  1103. unsigned long free_ptr;
  1104. unsigned long mask;
  1105. if (!mallocs[index].ptr)
  1106. return;
  1107. mpx_mini_free(mallocs[index].ptr, mallocs[index].size);
  1108. dprintf4("freed[%d]: %p\n", index, mallocs[index].ptr);
  1109. free_ptr = (unsigned long)mallocs[index].ptr;
  1110. mask = alignment-1;
  1111. dprintf4("lowerbits: %lx / %lx mask: %lx\n", free_ptr,
  1112. (free_ptr & mask), mask);
  1113. assert((free_ptr & mask) == 0);
  1114. mallocs[index].ptr = NULL;
  1115. }
  1116. #ifdef __i386__
  1117. #define MPX_BOUNDS_TABLE_COVERS 4096
  1118. #else
  1119. #define MPX_BOUNDS_TABLE_COVERS (1 * MB)
  1120. #endif
  1121. void zap_everything(void)
  1122. {
  1123. long after_zap;
  1124. long before_zap;
  1125. int i;
  1126. before_zap = inspect_me(bounds_dir_ptr);
  1127. dprintf1("zapping everything start: %ld\n", before_zap);
  1128. for (i = 0; i < NR_MALLOCS; i++)
  1129. free_one_malloc(i);
  1130. after_zap = inspect_me(bounds_dir_ptr);
  1131. dprintf1("zapping everything done: %ld\n", after_zap);
  1132. /*
  1133. * We only guarantee to empty the thing out if our allocations are
  1134. * exactly aligned on the boundaries of a boudns table.
  1135. */
  1136. if ((alignment >= MPX_BOUNDS_TABLE_COVERS) &&
  1137. (sz_alignment >= MPX_BOUNDS_TABLE_COVERS)) {
  1138. if (after_zap != 0)
  1139. test_failed();
  1140. assert(after_zap == 0);
  1141. }
  1142. }
  1143. void do_one_malloc(void)
  1144. {
  1145. static int malloc_counter;
  1146. long sz;
  1147. int rand_index = (mpx_random() % NR_MALLOCS);
  1148. void *ptr = mallocs[rand_index].ptr;
  1149. dprintf3("%s() enter\n", __func__);
  1150. if (ptr) {
  1151. dprintf3("freeing one malloc at index: %d\n", rand_index);
  1152. free_one_malloc(rand_index);
  1153. if (mpx_random() % (NR_MALLOCS*3) == 3) {
  1154. int i;
  1155. dprintf3("zapping some more\n");
  1156. for (i = rand_index; i < NR_MALLOCS; i++)
  1157. free_one_malloc(i);
  1158. }
  1159. if ((mpx_random() % zap_all_every_this_many_mallocs) == 4)
  1160. zap_everything();
  1161. }
  1162. /* 1->~1M */
  1163. sz = (1 + mpx_random() % 1000) * 1000;
  1164. ptr = mpx_mini_alloc(sz);
  1165. if (!ptr) {
  1166. /*
  1167. * If we are failing allocations, just assume we
  1168. * are out of memory and zap everything.
  1169. */
  1170. dprintf3("zapping everything because out of memory\n");
  1171. zap_everything();
  1172. goto out;
  1173. }
  1174. dprintf3("malloc: %p size: 0x%lx\n", ptr, sz);
  1175. mallocs[rand_index].nr_filled_btes = cover_buf_with_bt_entries(ptr, sz);
  1176. mallocs[rand_index].ptr = ptr;
  1177. mallocs[rand_index].size = sz;
  1178. out:
  1179. if ((++malloc_counter) % inspect_every_this_many_mallocs == 0)
  1180. inspect_me(bounds_dir_ptr);
  1181. }
  1182. void run_timed_test(void (*test_func)(void))
  1183. {
  1184. int done = 0;
  1185. long iteration = 0;
  1186. static time_t last_print;
  1187. time_t now;
  1188. time_t start;
  1189. time(&start);
  1190. while (!done) {
  1191. time(&now);
  1192. if ((now - start) > TEST_DURATION_SECS)
  1193. done = 1;
  1194. test_func();
  1195. iteration++;
  1196. if ((now - last_print > 1) || done) {
  1197. printf("iteration %ld complete, OK so far\n", iteration);
  1198. last_print = now;
  1199. }
  1200. }
  1201. }
  1202. void check_bounds_table_frees(void)
  1203. {
  1204. printf("executing unmaptest\n");
  1205. inspect_me(bounds_dir_ptr);
  1206. run_timed_test(&do_one_malloc);
  1207. printf("done with malloc() fun\n");
  1208. }
  1209. void insn_test_failed(int test_nr, int test_round, void *buf,
  1210. void *buf_shadow, void *ptr)
  1211. {
  1212. print_context(xsave_test_buf);
  1213. eprintf("ERROR: test %d round %d failed\n", test_nr, test_round);
  1214. while (test_nr == 5) {
  1215. struct mpx_bt_entry *bte;
  1216. struct mpx_bounds_dir *bd = (void *)bounds_dir_ptr;
  1217. struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(buf, bd);
  1218. printf(" bd: %p\n", bd);
  1219. printf("&bde: %p\n", bde);
  1220. printf("*bde: %lx\n", *(unsigned long *)bde);
  1221. if (!bd_entry_valid(bde))
  1222. break;
  1223. bte = mpx_vaddr_to_bt_entry(buf, bd);
  1224. printf(" te: %p\n", bte);
  1225. printf("bte[0]: %lx\n", bte->contents[0]);
  1226. printf("bte[1]: %lx\n", bte->contents[1]);
  1227. printf("bte[2]: %lx\n", bte->contents[2]);
  1228. printf("bte[3]: %lx\n", bte->contents[3]);
  1229. break;
  1230. }
  1231. test_failed();
  1232. }
  1233. void check_mpx_insns_and_tables(void)
  1234. {
  1235. int successes = 0;
  1236. int failures = 0;
  1237. int buf_size = (1024*1024);
  1238. unsigned long *buf = malloc(buf_size);
  1239. const int total_nr_tests = NR_MPX_TEST_FUNCTIONS * TEST_ROUNDS;
  1240. int i, j;
  1241. memset(buf, 0, buf_size);
  1242. memset(buf_shadow, 0, sizeof(buf_shadow));
  1243. for (i = 0; i < TEST_ROUNDS; i++) {
  1244. uint8_t *ptr = get_random_addr() + 8;
  1245. for (j = 0; j < NR_MPX_TEST_FUNCTIONS; j++) {
  1246. if (0 && j != 5) {
  1247. successes++;
  1248. continue;
  1249. }
  1250. dprintf2("starting test %d round %d\n", j, i);
  1251. dprint_context(xsave_test_buf);
  1252. /*
  1253. * test5 loads an address from the bounds tables.
  1254. * The load will only complete if 'ptr' matches
  1255. * the load and the store, so with random addrs,
  1256. * the odds of this are very small. Make it
  1257. * higher by only moving 'ptr' 1/10 times.
  1258. */
  1259. if (random() % 10 <= 0)
  1260. ptr = get_random_addr() + 8;
  1261. dprintf3("random ptr{%p}\n", ptr);
  1262. dprint_context(xsave_test_buf);
  1263. run_helpers(j, (void *)buf, (void *)buf_shadow, ptr);
  1264. dprint_context(xsave_test_buf);
  1265. if (!compare_context(xsave_test_buf)) {
  1266. insn_test_failed(j, i, buf, buf_shadow, ptr);
  1267. failures++;
  1268. goto exit;
  1269. }
  1270. successes++;
  1271. dprint_context(xsave_test_buf);
  1272. dprintf2("finished test %d round %d\n", j, i);
  1273. dprintf3("\n");
  1274. dprint_context(xsave_test_buf);
  1275. }
  1276. }
  1277. exit:
  1278. dprintf2("\nabout to free:\n");
  1279. free(buf);
  1280. dprintf1("successes: %d\n", successes);
  1281. dprintf1(" failures: %d\n", failures);
  1282. dprintf1(" tests: %d\n", total_nr_tests);
  1283. dprintf1(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs);
  1284. dprintf1(" saw: %d #BRs\n", br_count);
  1285. if (failures) {
  1286. eprintf("ERROR: non-zero number of failures\n");
  1287. exit(20);
  1288. }
  1289. if (successes != total_nr_tests) {
  1290. eprintf("ERROR: succeded fewer than number of tries (%d != %d)\n",
  1291. successes, total_nr_tests);
  1292. exit(21);
  1293. }
  1294. if (num_upper_brs + num_lower_brs != br_count) {
  1295. eprintf("ERROR: unexpected number of #BRs: %jd %jd %d\n",
  1296. num_upper_brs, num_lower_brs, br_count);
  1297. eprintf("successes: %d\n", successes);
  1298. eprintf(" failures: %d\n", failures);
  1299. eprintf(" tests: %d\n", total_nr_tests);
  1300. eprintf(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs);
  1301. eprintf(" saw: %d #BRs\n", br_count);
  1302. exit(22);
  1303. }
  1304. }
  1305. /*
  1306. * This is supposed to SIGSEGV nicely once the kernel
  1307. * can no longer allocate vaddr space.
  1308. */
  1309. void exhaust_vaddr_space(void)
  1310. {
  1311. unsigned long ptr;
  1312. /* Try to make sure there is no room for a bounds table anywhere */
  1313. unsigned long skip = MPX_BOUNDS_TABLE_SIZE_BYTES - PAGE_SIZE;
  1314. #ifdef __i386__
  1315. unsigned long max_vaddr = 0xf7788000UL;
  1316. #else
  1317. unsigned long max_vaddr = 0x800000000000UL;
  1318. #endif
  1319. dprintf1("%s() start\n", __func__);
  1320. /* do not start at 0, we aren't allowed to map there */
  1321. for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) {
  1322. void *ptr_ret;
  1323. int ret = madvise((void *)ptr, PAGE_SIZE, MADV_NORMAL);
  1324. if (!ret) {
  1325. dprintf1("madvise() %lx ret: %d\n", ptr, ret);
  1326. continue;
  1327. }
  1328. ptr_ret = mmap((void *)ptr, PAGE_SIZE, PROT_READ|PROT_WRITE,
  1329. MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
  1330. if (ptr_ret != (void *)ptr) {
  1331. perror("mmap");
  1332. dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret);
  1333. break;
  1334. }
  1335. if (!(ptr & 0xffffff))
  1336. dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret);
  1337. }
  1338. for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) {
  1339. dprintf2("covering 0x%lx with bounds table entries\n", ptr);
  1340. cover_buf_with_bt_entries((void *)ptr, PAGE_SIZE);
  1341. }
  1342. dprintf1("%s() end\n", __func__);
  1343. printf("done with vaddr space fun\n");
  1344. }
  1345. void mpx_table_test(void)
  1346. {
  1347. printf("starting mpx bounds table test\n");
  1348. run_timed_test(check_mpx_insns_and_tables);
  1349. printf("done with mpx bounds table test\n");
  1350. }
  1351. int main(int argc, char **argv)
  1352. {
  1353. int unmaptest = 0;
  1354. int vaddrexhaust = 0;
  1355. int tabletest = 0;
  1356. int i;
  1357. check_mpx_support();
  1358. mpx_prepare();
  1359. srandom(11179);
  1360. bd_incore();
  1361. init();
  1362. bd_incore();
  1363. trace_me();
  1364. xsave_state((void *)xsave_test_buf, 0x1f);
  1365. if (!compare_context(xsave_test_buf))
  1366. printf("Init failed\n");
  1367. for (i = 1; i < argc; i++) {
  1368. if (!strcmp(argv[i], "unmaptest"))
  1369. unmaptest = 1;
  1370. if (!strcmp(argv[i], "vaddrexhaust"))
  1371. vaddrexhaust = 1;
  1372. if (!strcmp(argv[i], "tabletest"))
  1373. tabletest = 1;
  1374. }
  1375. if (!(unmaptest || vaddrexhaust || tabletest)) {
  1376. unmaptest = 1;
  1377. /* vaddrexhaust = 1; */
  1378. tabletest = 1;
  1379. }
  1380. if (unmaptest)
  1381. check_bounds_table_frees();
  1382. if (tabletest)
  1383. mpx_table_test();
  1384. if (vaddrexhaust)
  1385. exhaust_vaddr_space();
  1386. printf("%s completed successfully\n", argv[0]);
  1387. exit(0);
  1388. }
  1389. #include "mpx-dig.c"