mpx-mini-test.c 39 KB

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