Пример #1
0
static int
__zero_segment (int envid, u_int start, u_int sz)
{
  u_int temp_pages;

  assert (!(start & PGMASK)); 

  temp_pages = (u_int)__malloc(PGROUNDUP(sz));
  if (temp_pages == 0) return -1;

  /* alloc pages for this segment and map into our address space writeable */
  if (__vm_alloc_region (temp_pages, sz, 0, PG_P|PG_U|PG_W) < 0) {
    __free((void*)temp_pages);
    return -1;
  }
  /* and map them into the other address space */
  if (__vm_share_region (temp_pages, sz, 0, 0, envid, start) < 0) {
    __free((void*)temp_pages);
    return -1;
  }
  /* zero the pages */
  bzero ((void *)temp_pages, sz);
  /* and remove our mapping of the pages */
  if (__vm_free_region (temp_pages, sz, 0) < 0) {
    __free((void*)temp_pages);
    return -1;
  }

  __free((void*)temp_pages);
  return 0;
}  
Пример #2
0
int 
ShareAshRegion(u_int k, int envid) {
  /* printf("ShareAshRegion sz: %d\n",sizeof(struct ash_sh_network)); */
  if (__vm_share_region(ADD_UVA(ASH_PKT_DATA_ADDR),
			sizeof(struct ash_sh_network), k, k, envid,
			ASH_PKT_DATA_ADDR + env_id2env(envid)->env_ashuva)
      < 0) {
    sys_env_free (k, envid);
    kprintf("ShareAshRegion: __vm_share_region failed\n");
    return (-1);
  }
  
  return 0;
}
Пример #3
0
static int
exec_exos_aout(int fd, const char *path, char *const argv[],
	       char *const envp[], struct Env *e, u_int flags)
{
  u_int envid = e->env_id;
  struct exec hdr;
  u_int dynamic;
  int r;
  struct _exos_exec_args eea;

  if (lseek(fd, 0, SEEK_SET) == -1 ||
      read(fd, &hdr, sizeof(hdr)) != sizeof(hdr) ||
      lseek(fd, sizeof(hdr) + hdr.a_text, SEEK_SET) == -1 ||
      read(fd, &dynamic, sizeof(dynamic)) != sizeof(dynamic))
    return 0;

  if (N_GETMAGIC(hdr) != OMAGIC ||
      N_GETMID(hdr) != MID_I386 ||
      N_GETFLAG(hdr) != 0)
    return 0;

  if (!(flags & _EXEC_USE_FD)) {
    close(fd);
    fd = -1;
  } else if (lseek(fd, 0, SEEK_SET) == -1)
    return 0;

  if (dynamic < SHARED_LIBRARY_START) dynamic = 0;
  if (dynamic == 0 && (flags & _EXEC_SHLIB_ONLY)) {
    r = -EINVAL;
    goto err;
  }

  /* if static, then read in entire program... */
  if (!dynamic) {
    u_int start_text_addr;

    if (flags & _EXEC_USE_FD)
      start_text_addr = __load_prog_fd(fd, 1, envid);
    else
      start_text_addr = __load_prog(path, argv[0], 1, envid);
    if (!start_text_addr) {
      r = -ENOEXEC;
      goto err;
    }
    /* set start address */
    e->env_tf.tf_eip = start_text_addr;
  }
  /* if dynamic, then make sure shared library is available */
  else if (dynamic) {
    struct stat sb;

    /* If flag so indicates, then require RO copy and use in mem version */
    if (!(flags & _EXEC_SHLIB_ONLY)) {
      /* if the shared library is not already in memory, or if it's old */
      /* then we need to (re)read it in */
      if (stat(PATH_LIBEXOS, &sb)) {
	r = -errno;
	kprintf("error stat'ing sl: %d\n", errno);
	goto err;
      }
      /* if we don't have a RO copy or it's out of date... */
      if (!isvamapped(SHARED_LIBRARY_START_RODATA) ||
	  memcmp(&sl_data->mod_time, &sb.st_mtimespec,
		 sizeof(sb.st_mtimespec))) {
	int slfd;

	/* if it's out of date, then unmap it */
	if (isvamapped(SHARED_LIBRARY_START_RODATA))
	  munmap((void*)SHARED_LIBRARY_START_RODATA,
		 (sl_data->text_pages + sl_data->data_pages) * NBPG);
	slfd = open (PATH_LIBEXOS, O_RDONLY);
	if (slfd < 0) {
	  r = -errno;
	  kprintf("could not open shared library " PATH_LIBEXOS "\n");
	  goto err;
	}
	if ((r = __load_sl_image (slfd)) < 0) {
	  kprintf("could not load library\n");
	  close(slfd);
	  goto err;
	}
	*((struct timespec*)&sl_data->mod_time) = sb.st_mtimespec;
	assert(sys_self_mod_pte_range(0, PG_RO, PG_W,
				      SHARED_LIBRARY_START_RODATA, 1) == 0);
	close (slfd);
      }
    } else {
      if (!isvamapped(SHARED_LIBRARY_START_RODATA)) {
	r = -EINVAL;
	goto err;
      }
    }

    /* share the text region read only/exec into child */
    if (__vm_share_region(SHARED_LIBRARY_START_RODATA,
			  sl_data->text_pages * NBPG, 0, 0,
			  envid, SHARED_LIBRARY_START)) {
      kprintf ("__vm_share_region failed for text region\n");
      r = -ENOEXEC;
      goto err;
    }

    /* share the read only data region into child cow */
    if (__vm_share_region(SHARED_LIBRARY_START_RODATA +
			  sl_data->text_pages * NBPG,
			  sl_data->data_pages * NBPG, 0, 0, envid,
			  SHARED_LIBRARY_START + sl_data->text_pages * NBPG)) {
      kprintf ("__vm_share_region failed for cow data region\n");
      r = -ENOEXEC;
      goto err;
    }
    if (sys_mod_pte_range(0, PG_COW, PG_RO | PG_SHARED, SHARED_LIBRARY_START +
			  sl_data->text_pages * NBPG, sl_data->data_pages, 0,
			  envid) < 0) {
      kprintf ("sys_mod_pte_range failed for cow data region\n");
      r = -ENOEXEC;
      goto err;
    }

    /* share the RO copy of the shared library */
    if (__vm_share_region(SHARED_LIBRARY_START_RODATA,
			  (sl_data->text_pages + sl_data->data_pages) * NBPG,
			  0, 0, envid, SHARED_LIBRARY_START_RODATA)) {
      kprintf ("__vm_share_region failed for read only text/data region\n");
      r = -ENOEXEC;
      goto err;
    }

    /* demand alloc bss for sl or no? */    
    if (getenv("NO_BSS_DEMAND_ALLOC")) {
      /* zero the bss */
      if (__zero_segment (envid, SHARED_LIBRARY_START +
			  (sl_data->text_pages + sl_data->data_pages) *
			  NBPG, sl_data->bss_pages * NBPG) < 0) {
	kprintf("could not create bss segment\n");
	r = -ENOEXEC;
	goto err;
      }
     } /* otherwise the fault handler will deal with it */
    
    /* set start address */
    e->env_tf.tf_eip = SHARED_LIBRARY_START + sizeof(struct exec);
  }

  /* take care of args, etc */
  if (flags & _EXEC_USE_FD)
    eea.eea_prog_fd = fd;
  else
    eea.eea_prog_fd = -1;
  if ((r = setup_new_stack(argv, envp, envid, &e->env_tf.tf_esp, &eea)) < 0)
    goto err;

  return 1;

 err:
  return r;
}
Пример #4
0
static int
setup_new_stack_simple(char *const argv[], char *const env[], 
                       u_int envid, u_int *newesp)
{
  int len=0, argc=0, envc=0, pages_needed, i;
  void *pages;
  u_int p;
  char **argvstr;
  char **envstr;

  if (!argv || !env) return -EFAULT;

  /* figure out how much we'll be putting on the new stack */

  /* size of new args */
  while (argv[argc]) len += strlen(argv[argc++])+1;
  
  /* size of env vars  */
  while (env[envc]) len += strlen(env[envc++])+1;

  /* for the pointers to the args' null termination */
  len += (argc + 1) * sizeof(void*);
  
  /* for the pointers to the env vars' null termination */
  len += (envc + 1) * sizeof(void*);

  /* leave a space argc */
  len += sizeof(int); 
  
  /* leave a space for argv */
  len += sizeof(char*);
  
  /* leave a space for env */
  len += sizeof(char*);
  
  len = ALIGN(len);

  /* calculate how many pages we need, and always allocate at least 1 page */
  pages_needed = PGNO(PGROUNDUP(len))+1;
  pages = __malloc(pages_needed*NBPG);
  if (!pages) return -ENOMEM;

  /* now we put things on the page */
  p = (u_int)pages + pages_needed*NBPG - len;

  /* first, the argc */
  *(int*)p = argc;
  p += sizeof(int);

  /* then, the argv pointer */
  *(int*)p = (USTACKTOP - ((u_int)pages + pages_needed*NBPG - 
                           (p+sizeof(char*)+sizeof(char*))));
  p += sizeof(char*);

  /* then, the env pointer */
  *(int*)p = (USTACKTOP - ((u_int)pages + pages_needed*NBPG -
      			   (p+sizeof(char*)+(argc+1)*sizeof(char*))));
  p += sizeof(char*);

  /* now, all the pointers to arguments */
  argvstr = (char**)p;
  p += (argc+1)*sizeof(char*);

  /* then, all the pointers to env vars */
  envstr = (char**)p;
  p += (envc+1)*sizeof(char*);

  /* copy in arguments, set up pointers to arguments */
  for (i=0; i < argc; i++) {
    argvstr[i] = (char*)(USTACKTOP - ((u_int)pages + pages_needed*NBPG - p));
    strcpy((char*)p, argv[i]);
    p += strlen(argv[i])+1;
  }
  argvstr[argc] = NULL;

  /* copy in env variables, set up pointers to env vars */
  for (i=0; i < envc; i++) {
    envstr[i] = (char*)(USTACKTOP - ((u_int)pages + pages_needed*NBPG - p));
    strcpy((char*)p, env[i]);
    p += strlen(env[i])+1;
  }
  envstr[envc] = NULL;


  /* now map the pages into the new process */
  *(char*)pages = 0;
  if (__vm_share_region((u_int)pages, pages_needed*NBPG, 0, 0, envid,
			USTACKTOP-pages_needed*NBPG) == -1 ||
      __vm_free_region((u_int)pages, pages_needed*NBPG, 0) == -1) {
    __free(pages);
    return -ENOMEM;
  }
  __free(pages);

  /* dude, this is totally a GCC thing: gcc convention says when starting
   * a program first argument is esp+4. That's the -4 here */
  *newesp = USTACKTOP - len - 4;
  
  return 0;
}
Пример #5
0
static int
setup_new_stack(char *const argv[], char *const env[], u_int envid,
		u_int *newesp, struct _exos_exec_args *eea)
{
  int len=0, envsize=0, argsize=0, argc=0, envc=0, pages_needed, i;
  void *pages;
  u_int p, padding, reserved_start;
  struct ps_strings *ps;
  char **argvstr, **envstr;

  /* XXX - sanity check ponters */
  if (!argv || !env) return -EFAULT;

  /* figure out how much we'll be putting on the new stack */
  len += sizeof(struct ps_strings);
  len = ALIGN(len);
  len += sizeof(struct _exos_exec_args);
  len = ALIGN(len);
  /* the reserved (mapped, but unused) pages */
  padding = PGROUNDUP(len) - len;
  len += padding;
  len += NBPG * __RESERVED_PAGES;
  reserved_start = len;
  /* size of new args */
  while (argv[argc]) argsize += strlen(argv[argc++])+1;
  /* size of new environment */
  while (env[envc]) envsize += strlen(env[envc++])+1;
  len += envsize + argsize;
  len = ALIGN(len);
  /* for the pointers to the args & envs and their null termination */
  len += (envc + 1 + argc + 1) * sizeof(void*);
  len += sizeof(int); /* the argc */
  /* extra page so child has at least one totally free stack page */
  pages_needed = PGNO(PGROUNDUP(len)) + 1;
  pages = __malloc(pages_needed*NBPG);
  if (!pages) return -ENOMEM;
  p = (u_int)pages + pages_needed*NBPG - len;
  *(int*)p = argc;
  p += sizeof(int);
  argvstr = (char**)p;
  p += (argc+1)*sizeof(char*);
  envstr = (char**)p;
  p += (envc+1)*sizeof(char*);
  for (i=0; i < argc; i++) {
    strcpy((char*)p, argv[i]);
    argvstr[i] = (char*)(USTACKTOP - ((u_int)pages + pages_needed*NBPG - p));
    p += strlen(argv[i])+1;
  }
  argvstr[argc] = NULL;
  for (i=0; i < envc; i++) {
    strcpy((char*)p, env[i]);
    envstr[i] = (char*)(USTACKTOP - ((u_int)pages + pages_needed*NBPG - p));
    p += strlen(env[i])+1;
  }
  envstr[envc] = NULL;
  /* map (via touching) the reserved pages */
  for (i=0; i < __RESERVED_PAGES; i++) {
    *(u_int*)p = 0;
    p += NBPG;
  }
  p += padding;
  /* continue... */
  eea->eea_reserved_pages = __RESERVED_PAGES;
  eea->eea_reserved_first = (char*)(USTACKTOP - reserved_start);
  p = ALIGN(p);
  *(struct _exos_exec_args*)p = *eea;
  p += sizeof(struct _exos_exec_args);
  p = ALIGN(p);
  ps = (struct ps_strings*)p;
  ps->ps_argvstr = (char**)(USTACKTOP - ((u_int)pages + pages_needed*NBPG -
					 (u_int)argvstr));
  ps->ps_nargvstr = argc;
  ps->ps_envstr = (char**)(USTACKTOP - ((u_int)pages + pages_needed*NBPG -
					(u_int)envstr));
  ps->ps_nenvstr = envc;
  /* now map the pages into the new process */
  /* XXX - touch clean page so it'll be mapped */
  *(char*)pages = 0;
  if (__vm_share_region((u_int)pages, pages_needed*NBPG, 0, 0, envid,
			USTACKTOP-pages_needed*NBPG) == -1 ||
      __vm_free_region((u_int)pages, pages_needed*NBPG, 0) == -1) {
    __free(pages);
    return -ENOMEM;
  }
  __free(pages);
  *newesp = USTACKTOP - len;

  return 0;
}