SHARE
TWEET

Untitled

a guest Jul 12th, 2018 3 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/mman.h>
  6. #include <ucontext.h>
  7. #include <asm/cachectl.h>
  8.  
  9. #include "xed/xed-interface.h"
  10.  
  11. #include "dsm_sync.h"
  12. #include "dsm_msg.h"
  13. #include "dsm_util.h"
  14. #include "dsm_inet.h"
  15. #include "dsm_signal.h"
  16.  
  17.  
  18. /*
  19.  *******************************************************************************
  20.  *                             Symbolic Constants                              *
  21.  *******************************************************************************
  22. */
  23.  
  24.  
  25. // Length of the UD2 instruction for isa: x86-64.
  26. #define UD2_SIZE    2
  27.  
  28.  
  29. /*
  30.  *******************************************************************************
  31.  *                              Global Variables                               *
  32.  *******************************************************************************
  33. */
  34.  
  35.  
  36. // Intel XED machine state.
  37. xed_state_t g_xed_machine_state;
  38.  
  39. // Instruction buffer.
  40. unsigned char g_inst_buf[UD2_SIZE];
  41.  
  42. // UD2 instruction opcodes for isa: x86-64.
  43. unsigned char g_ud2_opcodes[UD2_SIZE] = {0x0f, 0x0b};
  44.  
  45. // Pointer to memory address at which fault occurred.
  46. void *g_fault_addr;
  47.  
  48.  
  49. /*
  50.  *******************************************************************************
  51.  *                          Message Wrapper Functions                          *
  52.  *******************************************************************************
  53. */
  54.  
  55.  
  56. // Sends a message to target file-descriptor. Performs packing task.
  57. static void send_msg (int fd, dsm_msg *mp) {
  58.     unsigned char buf[DSM_MSG_SIZE];
  59.  
  60.     // Pack message.
  61.     dsm_pack_msg(mp, buf);
  62.  
  63.     // Send message.
  64.     dsm_sendall(fd, buf, DSM_MSG_SIZE);
  65. }
  66.  
  67. // Receives a message and configures the target message pointer.
  68. static void recv_msg (int fd, dsm_msg *mp) {
  69.     unsigned char buf[DSM_MSG_SIZE];
  70.  
  71.     // Receive message.
  72.     if (dsm_recvall(fd, buf, DSM_MSG_SIZE) != 0) {
  73.         dsm_cpanic("recv_msg", "Lost connection to host!");
  74.     }
  75.  
  76.     // Unpack message.
  77.     dsm_unpack_msg(mp, buf);
  78. }
  79.  
  80.  
  81. /*
  82.  *******************************************************************************
  83.  *                        Private Function Definitions                         *
  84.  *******************************************************************************
  85. */
  86.  
  87.  
  88. // Performs ILD on given address for decoder state. Returns length in bytes.
  89. static xed_uint_t getInstLength (void *addr, xed_state_t *decoderState) {
  90.     static xed_decoded_inst_t xedd;
  91.     xed_error_enum_t err;
  92.  
  93.     // Configure decoder for specified machine state.
  94.     xed_decoded_inst_zero_set_mode(&xedd, decoderState);
  95.  
  96.     // Perform instruction-length-decoding.
  97.     if ((err = xed_ild_decode(&xedd, addr, XED_MAX_INSTRUCTION_BYTES))
  98.         != XED_ERROR_NONE) {
  99.         dsm_panic(xed_error_enum_t2str(err));
  100.     }
  101.  
  102.     // Return length.
  103.     return xed_decoded_inst_get_length(&xedd);
  104. }
  105.  
  106. // Prepares to write: Messages the arbiter, waits for an acknowledgement.
  107. static void takeAccess (void) {
  108.  
  109.     // Temporarily ignore SIGTSTP.
  110.     dsm_sigignore(SIGTSTP);
  111.  
  112.     // Configure message.
  113.     dsm_msg msg = {.type = DSM_MSG_REQ_WRT};
  114.     msg.proc.pid = getpid();
  115.  
  116.     // Send message to arbiter.
  117.     send_msg(g_sock_io, &msg);
  118.  
  119.     // Wait for response from arbiter.
  120.     recv_msg(g_sock_io, &msg);
  121.  
  122.     // Verify message.
  123.     ASSERT_COND(msg.type == DSM_MSG_WRT_NOW && msg.proc.pid == getpid());
  124. }
  125.  
  126. // Releases access: Messages the arbiter, then suspends itself until continued.
  127. static void dropAccess (void) {
  128.     dsm_msg msg = {.type = DSM_MSG_WRT_DATA};
  129.  
  130.     // Reset default behavior for SIGTSTP.
  131.     dsm_sigdefault(SIGTSTP);
  132.  
  133.     // Configure message: Size assumed to be 64 bits.
  134.     msg.data.offset = (uintptr_t)g_fault_addr - (uintptr_t)g_shared_map;
  135.     msg.data.size = sizeof(int64_t);
  136.     memcpy(msg.data.bytes, g_fault_addr, msg.data.size);
  137.  
  138.     // Send mesage.
  139.     send_msg(g_sock_io, &msg);
  140.    
  141.     // Suspend self until continued.
  142.     if (kill(getpid(), SIGTSTP) == -1) {
  143.         dsm_panic("Couldn't suspend process!\n");
  144.     }
  145. }
  146.  
  147.  
  148. /*
  149.  *******************************************************************************
  150.  *                         Public Function Definitions                         *
  151.  *******************************************************************************
  152. */
  153.  
  154.  
  155. // Initializes the decoder tables necessary for use in the sync handlers.
  156. void dsm_sync_init (void) {
  157.  
  158.     // Initialize decoder table.
  159.     xed_tables_init();
  160.  
  161.     // Setup machine state.
  162.     xed_state_init2(&g_xed_machine_state, XED_MACHINE_MODE_LONG_64,
  163.         XED_ADDRESS_WIDTH_64b);
  164. }
  165.  
  166. // Handler: Synchronization action for SIGSEGV.
  167. void dsm_sync_sigsegv (int signal, siginfo_t *info, void *ucontext) {
  168.     ucontext_t *context = (ucontext_t *)ucontext;
  169.     void *prgm_counter = (void *)context->uc_mcontext.gregs[REG_RIP];
  170.     xed_uint_t len;
  171.     UNUSED(signal);
  172.  
  173.     printf("[%d] SIGSEGV (%p)!\n", getpid(), info->si_addr);
  174.  
  175.     // Set fault address.
  176.     g_fault_addr = info->si_addr;
  177.  
  178.     // Verify address is within shared page. Otherwise panic.
  179.     if ((uintptr_t)g_fault_addr < (uintptr_t)g_shared_map ||
  180.         (uintptr_t)g_fault_addr >= (uintptr_t)g_shared_map + g_map_size) {
  181.         dsm_panicf("Segmentation Fault: %p", g_fault_addr);
  182.     }
  183.  
  184.     // Request write access.
  185.     takeAccess();
  186.  
  187.     printf("[%d] Got access! (%p = %d)\n", getpid(), g_fault_addr, *((int *)g_fault_addr)); fflush(stdout);
  188.  
  189.     // Get instruction length.
  190.     len = getInstLength(prgm_counter, &g_xed_machine_state);
  191.  
  192.     // Compute start of next instruction.
  193.     void *nextInst = (void *)((uintptr_t)prgm_counter + len);
  194.  
  195.     // Copy out UD2_SIZE bytes for fault substitution.
  196.     memcpy(g_inst_buf, nextInst, UD2_SIZE);
  197.  
  198.     // Assign full access permissions to program text page.
  199.     off_t offset = (uintptr_t)nextInst % (uintptr_t)DSM_PAGESIZE;
  200.     void *pageStart = (void *)((uintptr_t)nextInst - offset);
  201.     dsm_mprotect(pageStart, DSM_PAGESIZE, PROT_READ|PROT_WRITE|PROT_EXEC);
  202.  
  203.     // Copy in the UD2 instruction.
  204.     memcpy(nextInst, g_ud2_opcodes, UD2_SIZE);
  205.  
  206.     // Give protected portion of shared page read-write access.
  207.     dsm_mprotect(g_shared_map, g_map_size, PROT_WRITE);
  208. }
  209.  
  210. // Handler: Synchronization action for SIGILL.
  211. void dsm_sync_sigill (int signal, siginfo_t *info, void *ucontext) {
  212.     ucontext_t *context = (ucontext_t *)ucontext;
  213.     void *prgm_counter = (void *)context->uc_mcontext.gregs[REG_RIP];
  214.     UNUSED(signal);
  215.     UNUSED(info);
  216.  
  217.     // Verify fault address is set. If not, abort.
  218.     if (g_fault_addr == NULL) {
  219.         dsm_panicf("Illegal Instruction (SIGILL). Aborting!");
  220.     }
  221.  
  222.     //printf("SIGILL!\n"); fflush(stdout);
  223.  
  224.     // Restore origin instruction.
  225.     memcpy(prgm_counter, g_inst_buf, UD2_SIZE);
  226.  
  227.     // Protect shared page again.
  228.     dsm_mprotect(g_shared_map, g_map_size, PROT_READ);
  229.  
  230.     // Flush both the instruction and data caches.
  231.     if (cacheflush(g_shared_map, g_map_size, ICACHE|DCACHE) == -1) {
  232.         dsm_panic("Error flushing caches w.r.t shared memory map!");
  233.     }
  234.    
  235.  
  236.     printf("[%d] Done (%p = %d)\n", getpid(), g_fault_addr, *((int *)g_fault_addr)); fflush(stdout);
  237.  
  238.     // Release lock and send sychronization information.
  239.     dropAccess();
  240.  
  241.     // Unset fault address.
  242.     g_fault_addr = NULL;
  243. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top