db_exception.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * db_signal.c
  17. *
  18. * This file contains APIs to set up handlers of exceptions issued by the
  19. * host, and the methods to pass the exceptions to the upcalls.
  20. */
  21. #include "pal_defs.h"
  22. #include "pal_linux_defs.h"
  23. #include "pal.h"
  24. #include "pal_internal.h"
  25. #include "pal_linux.h"
  26. #include "pal_error.h"
  27. #include "pal_security.h"
  28. #include "api.h"
  29. #include "linux_list.h"
  30. #include <atomic.h>
  31. #include <sigset.h>
  32. #include <linux/signal.h>
  33. #include <ucontext.h>
  34. #include <asm/errno.h>
  35. #if !defined(__i386__)
  36. /* In x86_64 kernels, sigaction is required to have a user-defined
  37. * restorer. Also, they not yet support SA_INFO. The reference:
  38. * http://lxr.linux.no/linux+v2.6.35/arch/x86/kernel/signal.c#L448
  39. *
  40. * / * x86-64 should always use SA_RESTORER. * /
  41. * if (ka->sa.sa_flags & SA_RESTORER) {
  42. * put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
  43. * } else {
  44. * / * could use a vstub here * /
  45. * err |= -EFAULT;
  46. * }
  47. */
  48. void restore_rt (void) asm ("__restore_rt");
  49. #ifndef SA_RESTORER
  50. #define SA_RESTORER 0x04000000
  51. #endif
  52. #define DEFINE_RESTORE_RT(syscall) DEFINE_RESTORE_RT2(syscall)
  53. # define DEFINE_RESTORE_RT2(syscall) \
  54. asm ( \
  55. " nop\n" \
  56. ".align 16\n" \
  57. ".LSTART_restore_rt:\n" \
  58. " .type __restore_rt,@function\n" \
  59. "__restore_rt:\n" \
  60. " movq $" #syscall ", %rax\n" \
  61. " syscall\n");
  62. DEFINE_RESTORE_RT(__NR_rt_sigreturn)
  63. #endif
  64. int set_sighandler (int * sigs, int nsig, void * handler)
  65. {
  66. struct sigaction action;
  67. if (handler) {
  68. action.sa_handler = (void (*)(int)) handler;
  69. action.sa_flags = SA_SIGINFO;
  70. #if !defined(__i386__)
  71. action.sa_flags |= SA_RESTORER;
  72. action.sa_restorer = restore_rt;
  73. #endif
  74. } else {
  75. action.sa_handler = SIG_IGN;
  76. }
  77. #ifdef DEBUG
  78. if (!linux_state.in_gdb)
  79. #endif
  80. action.sa_flags |= SA_NOCLDWAIT;
  81. __sigemptyset((__sigset_t *) &action.sa_mask);
  82. __sigaddset((__sigset_t *) &action.sa_mask, SIGCONT);
  83. for (int i = 0 ; i < nsig ; i++) {
  84. if (__sigismember(&linux_state.set_signals, sigs[i]))
  85. continue;
  86. #if defined(__i386__)
  87. int ret = INLINE_SYSCALL(sigaction, 3, sigs[i], &action, NULL)
  88. #else
  89. int ret = INLINE_SYSCALL(rt_sigaction, 4, sigs[i], &action, NULL,
  90. sizeof(sigset_t));
  91. #endif
  92. if (IS_ERR(ret))
  93. return -PAL_ERROR_DENIED;
  94. __sigaddset(&linux_state.set_signals, sigs[i]);
  95. }
  96. bool maskset = false;
  97. int ret = 0;
  98. __sigset_t mask;
  99. __sigemptyset(&mask);
  100. for (int i = 0 ; i < nsig ; i++)
  101. if (__sigismember(&linux_state.blocked_signals, sigs[i])) {
  102. __sigdelset(&linux_state.blocked_signals, sigs[i]);
  103. __sigaddset(&mask, sigs[i]);
  104. maskset = true;
  105. }
  106. if (maskset) {
  107. #if defined(__i386__)
  108. ret = INLINE_SYSCALL(sigprocmask, 3, SIG_UNBLOCK, &mask, NULL)
  109. #else
  110. ret = INLINE_SYSCALL(rt_sigprocmask, 4, SIG_UNBLOCK, &mask, NULL,
  111. sizeof(sigset_t));
  112. #endif
  113. }
  114. if (IS_ERR(ret))
  115. return -PAL_ERROR_DENIED;
  116. return 0;
  117. }
  118. int block_signals (int * sigs, int nsig)
  119. {
  120. bool maskset = false;
  121. int ret = 0;
  122. __sigset_t mask;
  123. __sigemptyset(&mask);
  124. for (int i = 0 ; i < nsig ; i++)
  125. if (!__sigismember(&linux_state.blocked_signals, sigs[i])) {
  126. __sigaddset(&linux_state.blocked_signals, sigs[i]);
  127. __sigaddset(&mask, sigs[i]);
  128. maskset = true;
  129. }
  130. if (maskset) {
  131. #if defined(__i386__)
  132. ret = INLINE_SYSCALL(sigprocmask, 3, SIG_BLOCK, &mask, NULL)
  133. #else
  134. ret = INLINE_SYSCALL(rt_sigprocmask, 4, SIG_BLOCK, &mask, NULL,
  135. sizeof(sigset_t));
  136. #endif
  137. }
  138. if (IS_ERR(ret))
  139. return -PAL_ERROR_DENIED;
  140. return 0;
  141. }
  142. int unblock_signals (int * sigs, int nsig)
  143. {
  144. bool maskset = false;
  145. int ret = 0;
  146. __sigset_t mask;
  147. __sigemptyset(&mask);
  148. for (int i = 0 ; i < nsig ; i++)
  149. if (__sigismember(&linux_state.blocked_signals, sigs[i])) {
  150. __sigdelset(&linux_state.blocked_signals, sigs[i]);
  151. __sigaddset(&mask, sigs[i]);
  152. maskset = true;
  153. }
  154. if (maskset) {
  155. #if defined(__i386__)
  156. ret = INLINE_SYSCALL(sigprocmask, 3, SIG_UNBLOCK, &mask, NULL)
  157. #else
  158. ret = INLINE_SYSCALL(rt_sigprocmask, 4, SIG_UNBLOCK, &mask, NULL,
  159. sizeof(sigset_t));
  160. #endif
  161. }
  162. if (IS_ERR(ret))
  163. return -PAL_ERROR_DENIED;
  164. return 0;
  165. }
  166. struct exception_handler {
  167. struct mutex_handle lock;
  168. int flags;
  169. PAL_UPCALL upcall;
  170. } __attribute__((aligned(sizeof(int))));
  171. struct exception_event {
  172. int event_num;
  173. int flags;
  174. PAL_CONTEXT context;
  175. ucontext_t * uc;
  176. void * eframe;
  177. };
  178. #define DECLARE_HANDLER_HEAD(event) \
  179. static struct exception_handler handler_##event = \
  180. { .lock = MUTEX_HANDLE_INIT, \
  181. .upcall = NULL, \
  182. .flags = 0, };
  183. DECLARE_HANDLER_HEAD(DivZero);
  184. DECLARE_HANDLER_HEAD(MemFault);
  185. DECLARE_HANDLER_HEAD(Illegal);
  186. DECLARE_HANDLER_HEAD(Quit);
  187. DECLARE_HANDLER_HEAD(Suspend);
  188. DECLARE_HANDLER_HEAD(Resume);
  189. DECLARE_HANDLER_HEAD(Failure);
  190. struct exception_handler * pal_handlers [PAL_EVENT_NUM_BOUND] = {
  191. NULL, /* reserved */
  192. &handler_DivZero,
  193. &handler_MemFault,
  194. &handler_Illegal,
  195. &handler_Quit,
  196. &handler_Suspend,
  197. &handler_Resume,
  198. &handler_Failure,
  199. };
  200. #define SIGNAL_MASK_TIME 1000
  201. #define save_return_point(ptr) \
  202. asm volatile ("leaq 0(%%rip), %%rax\r\n" \
  203. "movq %%rax, %0\r\n" \
  204. : "=b"(ptr) :: "memory", "rax")
  205. static int get_event_num (int signum)
  206. {
  207. switch(signum) {
  208. case SIGFPE: return PAL_EVENT_DIVZERO;
  209. case SIGSEGV: case SIGBUS: return PAL_EVENT_MEMFAULT;
  210. case SIGILL: return PAL_EVENT_ILLEGAL;
  211. case SIGTERM: return PAL_EVENT_QUIT;
  212. case SIGINT: return PAL_EVENT_SUSPEND;
  213. case SIGCONT: return PAL_EVENT_RESUME;
  214. default: return -1;
  215. }
  216. }
  217. void _DkGenericEventTrigger (int event_num, PAL_UPCALL upcall,
  218. int flags, PAL_NUM arg, struct pal_frame * frame,
  219. ucontext_t * uc, void * eframe)
  220. {
  221. struct exception_event event;
  222. event.event_num = event_num;
  223. event.flags = flags;
  224. if (uc)
  225. memcpy(&event.context, uc->uc_mcontext.gregs, sizeof(PAL_CONTEXT));
  226. if (frame) {
  227. event.context.r15 = frame->arch.r15;
  228. event.context.r14 = frame->arch.r14;
  229. event.context.r13 = frame->arch.r13;
  230. event.context.r12 = frame->arch.r12;
  231. event.context.rdi = frame->arch.rdi;
  232. event.context.rsi = frame->arch.rsi;
  233. event.context.rbx = frame->arch.rbx;
  234. /* find last frame */
  235. event.context.rsp = frame->arch.rbp + sizeof(unsigned long) * 2;
  236. event.context.rbp = ((unsigned long *) frame->arch.rbp)[0];
  237. event.context.rip = ((unsigned long *) frame->arch.rbp)[1];
  238. }
  239. event.uc = uc;
  240. event.eframe = eframe;
  241. (*upcall) (&event, arg, &event.context);
  242. }
  243. static bool _DkGenericSignalHandle (int event_num, siginfo_t * info,
  244. struct pal_frame * frame,
  245. ucontext_t * uc, void * eframe)
  246. {
  247. struct exception_handler * handler = pal_handlers[event_num];
  248. _DkMutexLock(&handler->lock);
  249. PAL_UPCALL upcall = handler->upcall;
  250. int flags = handler->flags;
  251. _DkMutexUnlock(&handler->lock);
  252. if (upcall) {
  253. PAL_NUM arg = 0;
  254. if (event_num == PAL_EVENT_DIVZERO ||
  255. event_num == PAL_EVENT_MEMFAULT ||
  256. event_num == PAL_EVENT_ILLEGAL)
  257. arg = (PAL_NUM) (info ? info->si_addr : 0);
  258. _DkGenericEventTrigger(event_num, upcall, flags, arg, frame,
  259. uc, eframe);
  260. return true;
  261. }
  262. return false;
  263. }
  264. #define ADDR_IN_PAL(addr) \
  265. ((void *) (addr) > TEXT_START && (void *) (addr) < TEXT_END)
  266. static struct pal_frame * get_frame (ucontext_t * uc)
  267. {
  268. unsigned long rip = uc->uc_mcontext.gregs[REG_RIP];
  269. unsigned long rbp = uc->uc_mcontext.gregs[REG_RBP];
  270. unsigned long last_rbp = rbp - 1024;
  271. if (!ADDR_IN_PAL(rip))
  272. return NULL;
  273. while (ADDR_IN_PAL(((unsigned long *) rbp)[1])) {
  274. last_rbp = rbp;
  275. rbp = *(unsigned long *) rbp;
  276. }
  277. /* search frame record in the top frame of PAL */
  278. for (unsigned long ptr = rbp - sizeof(unsigned long) ;
  279. ptr > last_rbp ; ptr -= 8) {
  280. struct pal_frame * frame = (struct pal_frame *) ptr;
  281. if (frame->self == frame)
  282. return frame;
  283. }
  284. return NULL;
  285. }
  286. static void return_frame (struct pal_frame * frame, int err)
  287. {
  288. if (err)
  289. _DkRaiseFailure(err);
  290. __clear_frame(frame);
  291. arch_restore_frame(&frame->arch);
  292. asm volatile ("xor %%rax, %%rax\r\n"
  293. "leaveq\r\n"
  294. "retq\r\n" ::: "memory");
  295. }
  296. static void _DkGenericSighandler (int signum, siginfo_t * info,
  297. struct ucontext * uc)
  298. {
  299. #if 0
  300. /* reseurrect this code if signal handler if giving segmentation fault */
  301. if (signum == SIGSEGV) {
  302. int pid = INLINE_SYSCALL(getpid, 0);
  303. char msg[24] = "--- SIGSEGV --- [ ]\n";
  304. msg[17] = '0' + pid / 10000;
  305. msg[18] = '0' + (pid / 1000) % 10;
  306. msg[19] = '0' + (pid / 100) % 10;
  307. msg[20] = '0' + (pid / 10) % 10;
  308. msg[21] = '0' + pid % 10;
  309. INLINE_SYSCALL(write, 3, 1, msg, 24);
  310. }
  311. #endif
  312. struct pal_frame * frame = get_frame(uc);
  313. void * eframe;
  314. asm volatile ("movq %%rbp, %0" : "=r"(eframe));
  315. if (frame && frame->func != &_DkGenericSighandler &&
  316. signum != SIGCONT &&
  317. signum != SIGINT &&
  318. signum != SIGTERM) {
  319. return_frame(frame, PAL_ERROR_BADADDR);
  320. return;
  321. }
  322. int event_num = get_event_num(signum);
  323. if (event_num == -1)
  324. return;
  325. _DkGenericSignalHandle(event_num, info, frame, uc, eframe);
  326. }
  327. static void _DkTerminateSighandler (int signum, siginfo_t * info,
  328. struct ucontext * uc)
  329. {
  330. struct pal_frame * frame = get_frame(uc);
  331. void * eframe;
  332. asm volatile ("movq %%rbp, %0" : "=r"(eframe));
  333. int event_num = get_event_num(signum);
  334. if (event_num == -1)
  335. return;
  336. if (!_DkGenericSignalHandle(event_num, NULL, frame, uc, eframe))
  337. _DkThreadExit();
  338. }
  339. static void _DkPipeSighandler (int signum, siginfo_t * info,
  340. struct ucontext * uc)
  341. {
  342. return;
  343. }
  344. void _DkRaiseFailure (int error)
  345. {
  346. _DkMutexLock(&handler_Failure.lock);
  347. PAL_UPCALL upcall = handler_Failure.upcall;
  348. int flags = handler_Failure.flags;
  349. _DkMutexUnlock(&handler_Failure.lock);
  350. if (upcall)
  351. _DkGenericEventTrigger(PAL_EVENT_FAILURE, upcall, flags, error,
  352. NULL, NULL, NULL);
  353. }
  354. struct signal_ops {
  355. int signum[3];
  356. void (*handler) (int signum, siginfo_t * info, ucontext_t * uc);
  357. };
  358. struct signal_ops on_signals[PAL_EVENT_NUM_BOUND] = {
  359. /* reserved */ { .signum = { 0 }, .handler = NULL },
  360. /* DivZero */ { .signum = { SIGFPE, 0 },
  361. .handler = _DkGenericSighandler },
  362. /* MemFault */ { .signum = { SIGSEGV, SIGBUS, 0 },
  363. .handler = _DkGenericSighandler },
  364. /* Illegal */ { .signum = { SIGILL, 0 },
  365. .handler = _DkGenericSighandler },
  366. /* Quit */ { .signum = { SIGTERM, 0, 0 },
  367. .handler = _DkTerminateSighandler },
  368. /* Suspend */ { .signum = { SIGINT, 0 },
  369. .handler = _DkTerminateSighandler },
  370. /* Resume */ { .signum = { SIGCONT, 0 },
  371. .handler = _DkGenericSighandler },
  372. /* Failure */ { .signum = { 0 }, .handler = NULL },
  373. };
  374. static int _DkPersistentSighandlerSetup (int event_num)
  375. {
  376. int nsigs, * sigs = on_signals[event_num].signum;
  377. for (nsigs = 0 ; sigs[nsigs] ; nsigs++);
  378. int ret = set_sighandler(sigs, nsigs, on_signals[event_num].handler);
  379. if (ret < 0)
  380. return ret;
  381. return 0;
  382. }
  383. static int _DkPersistentEventUpcall (int event_num, PAL_UPCALL upcall,
  384. int flags)
  385. {
  386. struct exception_handler * handler = pal_handlers[event_num];
  387. _DkMutexLock(&handler->lock);
  388. handler->upcall = upcall;
  389. handler->flags = flags;
  390. _DkMutexUnlock(&handler->lock);
  391. return _DkPersistentSighandlerSetup(event_num);
  392. }
  393. static int _DkGenericEventUpcall (int event_num, PAL_UPCALL upcall,
  394. int flags)
  395. {
  396. int nsigs, * sigs = on_signals[event_num].signum;
  397. for (nsigs = 0 ; sigs[nsigs] ; nsigs++);
  398. struct exception_handler * handler = pal_handlers[event_num];
  399. int ret = 0;
  400. _DkMutexLock(&handler->lock);
  401. handler->upcall = upcall;
  402. handler->flags = flags;
  403. _DkMutexUnlock(&handler->lock);
  404. if (upcall)
  405. ret = set_sighandler(sigs, nsigs, on_signals[event_num].handler);
  406. else
  407. ret = block_signals(sigs, nsigs);
  408. return ret;
  409. }
  410. static int _DkDummyEventUpcall (int event_num, PAL_UPCALL upcall,
  411. int flags)
  412. {
  413. struct exception_handler * handler = pal_handlers[event_num];
  414. _DkMutexLock(&handler->lock);
  415. handler->upcall = upcall;
  416. handler->flags = flags;
  417. _DkMutexUnlock(&handler->lock);
  418. return 0;
  419. }
  420. typedef void (*PAL_UPCALL) (PAL_PTR, PAL_NUM, PAL_CONTEXT *);
  421. int (*_DkExceptionHandlers[PAL_EVENT_NUM_BOUND])
  422. (int, PAL_UPCALL, int) = {
  423. /* reserved */ NULL,
  424. /* DivZero */ &_DkPersistentEventUpcall,
  425. /* MemFault */ &_DkPersistentEventUpcall,
  426. /* Illegal */ &_DkPersistentEventUpcall,
  427. /* Quit */ &_DkGenericEventUpcall,
  428. /* Suspend */ &_DkGenericEventUpcall,
  429. /* Resume */ &_DkGenericEventUpcall,
  430. /* Failure */ &_DkDummyEventUpcall,
  431. };
  432. static void _DkCompatibilitySighandler (int signum, siginfo_t * info,
  433. ucontext_t * uc)
  434. {
  435. unsigned long args[6] = { uc->uc_mcontext.gregs[REG_RDI],
  436. uc->uc_mcontext.gregs[REG_RSI],
  437. uc->uc_mcontext.gregs[REG_RDX],
  438. uc->uc_mcontext.gregs[REG_R10],
  439. uc->uc_mcontext.gregs[REG_R8],
  440. uc->uc_mcontext.gregs[REG_R9] };
  441. uc->uc_mcontext.gregs[REG_RAX] =
  442. _DkHandleCompatibilityException(uc->uc_mcontext.gregs[REG_RAX], args);
  443. }
  444. void signal_setup (void)
  445. {
  446. int ret, sig = SIGCHLD;
  447. #ifdef DEBUG
  448. if (!linux_state.in_gdb)
  449. #endif
  450. set_sighandler(&sig, 1, NULL);
  451. if ((ret = _DkPersistentEventUpcall(PAL_EVENT_DIVZERO, NULL, 0)) < 0)
  452. goto err;
  453. if ((ret = _DkPersistentEventUpcall(PAL_EVENT_MEMFAULT, NULL, 0)) < 0)
  454. goto err;
  455. if ((ret = _DkPersistentEventUpcall(PAL_EVENT_ILLEGAL, NULL, 0)) < 0)
  456. goto err;
  457. sig = SIGPIPE;
  458. if ((ret = set_sighandler(&sig, 1, &_DkPipeSighandler)) < 0)
  459. goto err;
  460. sig = SIGSYS;
  461. if ((ret = set_sighandler(&sig, 1, &_DkCompatibilitySighandler)) < 0)
  462. goto err;
  463. return;
  464. err:
  465. init_fail(-ret, "cannot setup signal handlers");
  466. }
  467. void _DkExceptionReturn (const void * event)
  468. {
  469. const struct exception_event * e = (const struct exception_event *) event;
  470. if (e->uc) {
  471. /* copy the context back to ucontext */
  472. memcpy(e->uc->uc_mcontext.gregs, &e->context, sizeof(PAL_CONTEXT));
  473. /* return to the frame of exception handler */
  474. asm volatile ("movq %0, %%rbp\r\n"
  475. "leaveq\r\n"
  476. "retq\r\n" :: "r"(e->eframe) : "memory");
  477. }
  478. }