/**
 * This function behaves exactly like mtcp_sys_open(), except that you are
 * guaranteed to receive a file descriptor that is not one of the standard 3.
 * This is useful if, for instance, you have no fd 0, receive one through
 * open(), dup2 it to stdin, and close the original (therefore closing stdin).
 *
 * @param filename the file to open
 * @param flags the flags that indicate how to open it
 * @param mode if O_CREAT is in flags and the file gets created, mode indicates
 * the permissions
 *
 * @return a file descriptor to filename, opened according to flags and mode,
 * that is guaranteed to not be one of the standard 3
 */
int mtcp_safe_open(char const *filename, int flags, mode_t mode)
{
    int fds[3];
    int i, j, fd;

    for(i = 0; i < 4; i++)
    {
        fd = mtcp_sys_open(filename, flags, mode);

        if((fd != STDIN_FILENO) &&
           (fd != STDOUT_FILENO) &&
           (fd != STDERR_FILENO))
            break;

        fds[i] = fd;
    }

    for(j = 0; j < i; j++)
        mtcp_sys_close(fds[j]);

    return fd;
}
Ejemplo n.º 2
0
/**
 * This function will return the first character of the given file.  If the
 * file is not readable, we will abort.
 *
 * @param filename the name of the file to read
 * @return the first character of the given file
 */
static char first_char(char *filename)
{
    int fd, rc;
    char c;

    fd = mtcp_sys_open(filename, O_RDONLY, 0);
    if(fd < 0)
    {
        MTCP_PRINTF("ERROR: Cannot open file %s\n", filename);
        mtcp_abort();
    }

    rc = mtcp_sys_read(fd, &c, 1);
    if(rc != 1)
    {
        MTCP_PRINTF("ERROR: Error reading from file %s\n", filename);
        mtcp_abort();
    }

    mtcp_sys_close(fd);
    return c;
}
Ejemplo n.º 3
0
int mtcp_selfmap_open() {
  return mtcp_sys_open ("/proc/self/maps", O_RDONLY, 0);
}
Ejemplo n.º 4
0
void mtcp_get_memory_region_of_this_library(VA *startaddr, VA *endaddr)
{
  struct {
    VA start_addr;
    VA end_addr;
  } text, guard, rodata, rwdata, bssdata;

  Area area;
  VA thislib_fnc = (void*) &mtcp_get_memory_region_of_this_library;
  VA thislib_static_var = (VA) &dummy_uninitialized_static_var;
  char filename[PATH_MAX] = {0};
  text.start_addr = guard.start_addr = rodata.start_addr = NULL;
  rwdata.start_addr = bssdata.start_addr = bssdata.end_addr = NULL;
  int mapsfd = mtcp_sys_open("/proc/self/maps", O_RDONLY, 0);
  MTCP_ASSERT(mapsfd != -1);

  while (mtcp_readmapsline (mapsfd, &area, NULL)) {
    VA start_addr = area.addr;
    VA end_addr = area.addr + area.size;

    if (thislib_fnc >= start_addr && thislib_fnc < end_addr) {
      MTCP_ASSERT(text.start_addr == NULL);
      text.start_addr = start_addr; text.end_addr = end_addr;
      mtcp_strcpy(filename, area.name);
      continue;
    }

    if (text.start_addr != NULL && guard.start_addr == NULL &&
        mtcp_strcmp(filename, area.name) == 0) {
      MTCP_ASSERT(area.addr == text.end_addr);
      if (area.prot == 0) {
        /* The guard pages are unreadable due to the "---p" protection. Even if
         * the protection is changed to "r--p", a read will result in a SIGSEGV
         * as the pages are not backed by the kernel. A better way to handle
         * this is to remap these pages with anonymous memory.
         */
        MTCP_ASSERT(mtcp_sys_mmap(start_addr, area.size, PROT_READ,
                                  MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED,
                                  -1, 0) == start_addr);
        guard.start_addr = start_addr; guard.end_addr = end_addr;
        continue;
      } else {
        // No guard pages found. This is probably the ROData section.
        guard.start_addr = start_addr; guard.end_addr = start_addr;
      }
    }

    if (guard.start_addr != NULL && rodata.start_addr == NULL &&
        mtcp_strcmp(filename, area.name) == 0) {
      MTCP_ASSERT(area.addr == guard.end_addr);
      if (area.prot == PROT_READ ||
          // On some systems, all sections of the library have exec
          // permissions.
          area.prot == (PROT_READ|PROT_EXEC)) {
        rodata.start_addr = start_addr; rodata.end_addr = end_addr;
        continue;
      } else {
        // No ROData section. This is probably the RWData section.
        rodata.start_addr = start_addr; rodata.end_addr = start_addr;
      }
    }

    if (rodata.start_addr != NULL && rwdata.start_addr == NULL &&
        mtcp_strcmp(filename, area.name) == 0) {
      MTCP_ASSERT(area.addr == rodata.end_addr);
      MTCP_ASSERT(area.prot == (PROT_READ|PROT_WRITE) ||
                  // On some systems, all sections of the library have exec
                  // permissions.
                  area.prot == (PROT_READ|PROT_WRITE|PROT_EXEC));
      rwdata.start_addr = start_addr; rwdata.end_addr = end_addr;
      continue;
    }

    if (rwdata.start_addr != NULL && bssdata.start_addr == NULL &&
        area.name[0] == '\0') {
      /* /proc/PID/maps does not label the filename for memory region holding
       * static variables in a library.  But that is also part of this
       * library (libmtcp.so).
       * So, find the meory region for static memory variables and add it.
       */
      MTCP_ASSERT(area.addr == rwdata.end_addr);
      MTCP_ASSERT(area.prot == (PROT_READ|PROT_WRITE) ||
                  // On some systems, all sections of the library have exec
                  // permissions.
                  area.prot == (PROT_READ|PROT_WRITE|PROT_EXEC));
      MTCP_ASSERT(thislib_static_var >= start_addr &&
                  thislib_static_var < end_addr);
      bssdata.start_addr = start_addr; bssdata.end_addr = end_addr;
      break;
    }
  }
  mtcp_sys_close(mapsfd);
  MTCP_ASSERT(text.start_addr != NULL);
  MTCP_ASSERT(bssdata.end_addr != NULL);
  *startaddr = text.start_addr;
  *endaddr   = bssdata.end_addr;
}
Ejemplo n.º 5
0
/**
 * This function will open the checkpoint file stored at the given filename.
 * It will check the magic number and take the appropriate action.  If the
 * magic number is unknown, we will abort.  The fd returned points to the
 * beginning of the uncompressed data.
 * NOTE: related code in ../dmtcp/src/connectionmanager.cpp:open_ckpt_to_read()
 *
 * @param filename the name of the checkpoint file
 * @return the fd to use
 */
static int open_ckpt_to_read(char *filename, char *envp[])
{
  int fd;
  int fds[2];
  char fc;
  char *gzip_cmd = "gzip";
  static char *gzip_args[] = { "gzip", "-d", "-", NULL };
#ifdef HBICT_DELTACOMP
  char *hbict_cmd = "hbict";
  static char *hbict_args[] = { "hbict", "-r", NULL };
#endif
  char decomp_path[PATH_MAX];
  static char **decomp_args;
  pid_t cpid;

  fc = first_char(filename);
  fd = mtcp_sys_open(filename, O_RDONLY, 0);
  if(fd < 0) {
    MTCP_PRINTF("ERROR: Cannot open checkpoint file %s\n", filename);
    mtcp_abort();
  }

  if (fc == MAGIC_FIRST || fc == 'D') /* no compression ('D' from DMTCP) */
    return fd;
  else if (fc == GZIP_FIRST
#ifdef HBICT_DELTACOMP
           || fc == HBICT_FIRST
#endif
          ) { /* Set prog_path */
    if( fc == GZIP_FIRST ){
      decomp_args = gzip_args;
      if( mtcp_find_executable(gzip_cmd, getenv("PATH"),
                               decomp_path) == NULL ) {
        MTCP_PRINTF("ERROR: Cannot find gunzip to decompress ckpt file!\n");
        mtcp_abort();
      }
    }
#ifdef HBICT_DELTACOMP
    if( fc == HBICT_FIRST ){
      decomp_args = hbict_args;
      if( mtcp_find_executable(hbict_cmd, getenv("PATH"),
                              decomp_path) == NULL ) {
        MTCP_PRINTF("ERROR: Cannot find hbict to decompress ckpt file!\n");
        mtcp_abort();
      }
    }
#endif
    if (mtcp_sys_pipe(fds) == -1) {
      MTCP_PRINTF("ERROR: Cannot create pipe to execute gunzip to decompress"
                  " checkpoint file!\n");
      mtcp_abort();
    }

    cpid = mtcp_sys_fork();

    if(cpid == -1) {
      MTCP_PRINTF("ERROR: Cannot fork to execute gunzip to decompress"
                  " checkpoint file!\n");
      mtcp_abort();
    }
    else if(cpid > 0) /* parent process */ {
      decomp_child_pid = cpid;
      mtcp_sys_close(fd);
      mtcp_sys_close(fds[1]);
      return fds[0];
    }
    else /* child process */ {
      fd = mtcp_sys_dup(mtcp_sys_dup(mtcp_sys_dup(fd)));
      if (fd == -1) {
        MTCP_PRINTF("ERROR: dup() failed!  No restoration will be performed!"
                    " Cancel now!\n");
        mtcp_abort();
      }
      fds[1] = mtcp_sys_dup(fds[1]);
      mtcp_sys_close(fds[0]);
      if (mtcp_sys_dup2(fd, STDIN_FILENO) != STDIN_FILENO) {
        MTCP_PRINTF("ERROR: dup2() failed!  No restoration will be performed!"
                    " Cancel now!\n");
        mtcp_abort();
      }
      mtcp_sys_close(fd);
      mtcp_sys_dup2(fds[1], STDOUT_FILENO);
      mtcp_sys_close(fds[1]);
      mtcp_sys_execve(decomp_path, decomp_args, envp);
      /* should not get here */
      MTCP_PRINTF("ERROR: Decompression failed!  No restoration will be"
                  " performed!  Cancel now!\n");
      mtcp_abort();
    }
  }
  else /* invalid magic number */ {
    MTCP_PRINTF("ERROR: Invalid magic number in this checkpoint file!\n");
    mtcp_abort();
  }
}