1540 * system calls to get us back here after the Linux signal handler returns.
1541 * This function is modelled on the in-kernel "sendsig()" signal delivery
1542 * mechanism.
1543 */
1544 void
1545 lx_sigdeliver(int lx_sig, siginfo_t *sip, ucontext_t *ucp, size_t stacksz,
1546 void (*stack_builder)(), void (*user_handler)(),
1547 struct lx_sigaction *lxsap)
1548 {
1549 lx_sigbackup_t sigbackup;
1550 ucontext_t uc;
1551 lx_tsd_t *lxtsd = lx_get_tsd();
1552 int totsz = 0;
1553 uintptr_t flags;
1554 uintptr_t hargs[3];
1555 /*
1556 * These variables must be "volatile", as they are modified after the
1557 * getcontext() stores the register state:
1558 */
1559 volatile boolean_t signal_delivered = B_FALSE;
1560 volatile uintptr_t lxfp;
1561 volatile uintptr_t old_tsd_sp;
1562 volatile int newstack;
1563
1564 /*
1565 * This function involves modifying the Linux process stack for this
1566 * thread. To do so without corruption requires us to exclude other
1567 * signal handlers (or emulated system calls called from within those
1568 * handlers) from running while we reserve space on that stack. We
1569 * defer the execution of further instances of lx_call_user_handler()
1570 * until we have completed this operation.
1571 */
1572 _sigoff();
1573
1574 /*
1575 * Clear register arguments vector.
1576 */
1577 bzero(hargs, sizeof (hargs));
1578
1579 /*
1580 * We save a context here so that we can be returned later to complete
1581 * handling the signal.
1582 */
1788 * uc_link value from this synthetic context, as that would
1789 * break the signal handling context chain.
1790 */
1791 jump_uc.uc_flags = UC_CPU;
1792 jump_uc.uc_brand_data[0] = (void *)(LX_UC_STACK_BRAND |
1793 LX_UC_IGNORE_LINK);
1794
1795 LX_REG(&jump_uc, REG_FP) = 0;
1796 LX_REG(&jump_uc, REG_SP) = lxfp;
1797 LX_REG(&jump_uc, REG_PC) = (uintptr_t)user_handler;
1798
1799 #if defined(_LP64)
1800 /*
1801 * Pass signal handler arguments by registers on AMD64.
1802 */
1803 LX_REG(&jump_uc, REG_RDI) = hargs[0];
1804 LX_REG(&jump_uc, REG_RSI) = hargs[1];
1805 LX_REG(&jump_uc, REG_RDX) = hargs[2];
1806 #endif
1807
1808 if (syscall(SYS_brand, B_JUMP_TO_LINUX, &jump_uc) == -1) {
1809 lx_err_fatal("B_JUMP_TO_LINUX failed: %s",
1810 strerror(errno));
1811 }
1812 }
1813
1814 assert(0);
1815
1816 after_signal_handler:
1817 /*
1818 * Ensure all nested signal handlers have completed correctly
1819 * and then remove our stack reservation.
1820 */
1821 _sigoff();
1822 LX_SIGNAL_POST_HANDLER(lxfp, old_tsd_sp);
1823 assert(lxtsd->lxtsd_lx_sp == lxfp);
1824 lx_debug("lx_sigdeliver: after; Linux tsd sp %p -> %p\n", lxfp,
1825 old_tsd_sp);
1826 lxtsd->lxtsd_lx_sp = old_tsd_sp;
1827 if (newstack) {
1828 LX_SIGNAL_ALTSTACK_DISABLE();
1829 lx_debug("lx_sigdeliver: disabling ALTSTACK sp %p\n", lxfp);
1830 lxtsd->lxtsd_sigaltstack.ss_flags &= ~LX_SS_ONSTACK;
1831 }
1832 /*
1833 * Restore backup signal tracking chain pointer to previous value:
1834 */
|
1540 * system calls to get us back here after the Linux signal handler returns.
1541 * This function is modelled on the in-kernel "sendsig()" signal delivery
1542 * mechanism.
1543 */
1544 void
1545 lx_sigdeliver(int lx_sig, siginfo_t *sip, ucontext_t *ucp, size_t stacksz,
1546 void (*stack_builder)(), void (*user_handler)(),
1547 struct lx_sigaction *lxsap)
1548 {
1549 lx_sigbackup_t sigbackup;
1550 ucontext_t uc;
1551 lx_tsd_t *lxtsd = lx_get_tsd();
1552 int totsz = 0;
1553 uintptr_t flags;
1554 uintptr_t hargs[3];
1555 /*
1556 * These variables must be "volatile", as they are modified after the
1557 * getcontext() stores the register state:
1558 */
1559 volatile boolean_t signal_delivered = B_FALSE;
1560 volatile uintptr_t lxfp = 0;
1561 volatile uintptr_t old_tsd_sp = 0;
1562 volatile int newstack = 0;
1563
1564 /*
1565 * This function involves modifying the Linux process stack for this
1566 * thread. To do so without corruption requires us to exclude other
1567 * signal handlers (or emulated system calls called from within those
1568 * handlers) from running while we reserve space on that stack. We
1569 * defer the execution of further instances of lx_call_user_handler()
1570 * until we have completed this operation.
1571 */
1572 _sigoff();
1573
1574 /*
1575 * Clear register arguments vector.
1576 */
1577 bzero(hargs, sizeof (hargs));
1578
1579 /*
1580 * We save a context here so that we can be returned later to complete
1581 * handling the signal.
1582 */
1788 * uc_link value from this synthetic context, as that would
1789 * break the signal handling context chain.
1790 */
1791 jump_uc.uc_flags = UC_CPU;
1792 jump_uc.uc_brand_data[0] = (void *)(LX_UC_STACK_BRAND |
1793 LX_UC_IGNORE_LINK);
1794
1795 LX_REG(&jump_uc, REG_FP) = 0;
1796 LX_REG(&jump_uc, REG_SP) = lxfp;
1797 LX_REG(&jump_uc, REG_PC) = (uintptr_t)user_handler;
1798
1799 #if defined(_LP64)
1800 /*
1801 * Pass signal handler arguments by registers on AMD64.
1802 */
1803 LX_REG(&jump_uc, REG_RDI) = hargs[0];
1804 LX_REG(&jump_uc, REG_RSI) = hargs[1];
1805 LX_REG(&jump_uc, REG_RDX) = hargs[2];
1806 #endif
1807
1808 lx_jump_to_linux(&jump_uc);
1809 }
1810
1811 assert(0);
1812 abort();
1813
1814 after_signal_handler:
1815 /*
1816 * Ensure all nested signal handlers have completed correctly
1817 * and then remove our stack reservation.
1818 */
1819 _sigoff();
1820 LX_SIGNAL_POST_HANDLER(lxfp, old_tsd_sp);
1821 assert(lxtsd->lxtsd_lx_sp == lxfp);
1822 lx_debug("lx_sigdeliver: after; Linux tsd sp %p -> %p\n", lxfp,
1823 old_tsd_sp);
1824 lxtsd->lxtsd_lx_sp = old_tsd_sp;
1825 if (newstack) {
1826 LX_SIGNAL_ALTSTACK_DISABLE();
1827 lx_debug("lx_sigdeliver: disabling ALTSTACK sp %p\n", lxfp);
1828 lxtsd->lxtsd_sigaltstack.ss_flags &= ~LX_SS_ONSTACK;
1829 }
1830 /*
1831 * Restore backup signal tracking chain pointer to previous value:
1832 */
|