Exemplo n.º 1
0
/*===========================================================================*
 *				do_exec					     *
 *===========================================================================*/
PUBLIC int do_exec()
{
    /* Perform the execve(name, argv, envp) call.  The user library builds a
     * complete stack image, including pointers, args, environ, etc.  The stack
     * is copied to a buffer inside MM, and then to the new core image.
     */

    register struct mproc *rmp;
    struct mproc *sh_mp;
    int m, r, fd, ft, sn;
    static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
    static char name_buf[PATH_MAX]; /* the name of the file to exec */
    char *new_sp, *basename;
    vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
    phys_bytes tot_bytes;		/* total space for program, including gap */
    long sym_bytes;
    vir_clicks sc;
    struct stat s_buf;
    vir_bytes pc;

    /* Do some validity checks. */
    rmp = mp;
    stk_bytes = (vir_bytes) stack_bytes;
    if (stk_bytes > ARG_MAX) return(ENOMEM);	/* stack too big */
    if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL);

    /* Get the exec file name and see if the file is executable. */
    src = (vir_bytes) exec_name;
    dst = (vir_bytes) name_buf;
    r = sys_copy(who, D, (phys_bytes) src,
                 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len);
    if (r != OK) return(r);	/* file name not in user data segment */
    tell_fs(CHDIR, who, FALSE, 0);	/* switch to the user's FS environ. */
    fd = allowed(name_buf, &s_buf, X_BIT);	/* is file executable? */
    if (fd < 0) return(fd);	/* file was not executable */

    /* Read the file header and extract the segment sizes. */
    sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
    m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes,
                    &tot_bytes, &sym_bytes, sc, &pc);
    if (m < 0) {
        close(fd);		/* something wrong with header */
        return(ENOEXEC);
    }

    /* Fetch the stack from the user before destroying the old core image. */
    src = (vir_bytes) stack_ptr;
    dst = (vir_bytes) mbuf;
    r = sys_copy(who, D, (phys_bytes) src,
                 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes);
    if (r != OK) {
        close(fd);		/* can't fetch stack (e.g. bad virtual addr) */
        return(EACCES);
    }

    /* Can the process' text be shared with that of one already running? */
    sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime);

    /* Allocate new memory and release old memory.  Fix map and tell kernel. */
    r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
    if (r != OK) {
        close(fd);		/* insufficient core or program too big */
        return(r);
    }

    /* Save file identification to allow it to be shared. */
    rmp->mp_ino = s_buf.st_ino;
    rmp->mp_dev = s_buf.st_dev;
    rmp->mp_ctime = s_buf.st_ctime;

    /* Patch up stack and copy it from MM to new core image. */
    vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
    vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
    vsp -= stk_bytes;
    patch_ptr(mbuf, vsp);
    src = (vir_bytes) mbuf;
    r = sys_copy(MM_PROC_NR, D, (phys_bytes) src,
                 who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes);
    if (r != OK) panic("do_exec stack copy err", NO_NUM);

    /* Read in text and data segments. */
    if (sh_mp != NULL) {
        lseek(fd, (off_t) text_bytes, SEEK_CUR);  /* shared: skip text */
    } else {
        load_seg(fd, T, text_bytes);
    }
    load_seg(fd, D, data_bytes);

#if (SHADOWING == 1)
    if (lseek(fd, (off_t)sym_bytes, SEEK_CUR) == (off_t) -1) ;	/* error */
    if (relocate(fd, (unsigned char *)mbuf) < 0) 	;		/* error */
    pc += (vir_bytes) rp->mp_seg[T].mem_vir << CLICK_SHIFT;
#endif

    close(fd);			/* don't need exec file any more */

    /* Take care of setuid/setgid bits. */
    if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
        if (s_buf.st_mode & I_SET_UID_BIT) {
            rmp->mp_effuid = s_buf.st_uid;
            tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
        }
        if (s_buf.st_mode & I_SET_GID_BIT) {
            rmp->mp_effgid = s_buf.st_gid;
            tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
        }
    }

    /* Save offset to initial argc (for ps) */
    rmp->mp_procargs = vsp;

    /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
    for (sn = 1; sn <= _NSIG; sn++) {
        if (sigismember(&rmp->mp_catch, sn)) {
            sigdelset(&rmp->mp_catch, sn);
            rmp->mp_sigact[sn].sa_handler = SIG_DFL;
            sigemptyset(&rmp->mp_sigact[sn].sa_mask);
        }
    }

    rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
    rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
    new_sp = (char *) vsp;

    tell_fs(EXEC, who, 0, 0);	/* allow FS to handle FD_CLOEXEC files */

    /* System will save command line for debugging, ps(1) output, etc. */
    basename = strrchr(name_buf, '/');
    if (basename == NULL) basename = name_buf;
    else basename++;
    sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc);
    return(OK);
}
Exemplo n.º 2
0
static int
process_share(sa_handle_impl_t impl_handle, sa_share_impl_t impl_share,
    char *pathname, char *resource, char *proto,
    char *options, char *description, char *dataset,
    boolean_t from_sharetab)
{
	struct stat statbuf;
	int rc;
	char *resource_dup = NULL, *dataset_dup = NULL;
	boolean_t new_share;
	sa_fstype_t *fstype;

	new_share = B_FALSE;

	if (impl_share == NULL)
		impl_share = find_share(impl_handle, pathname);

	if (impl_share == NULL) {
		if (lstat(pathname, &statbuf) != 0 ||
		    !S_ISDIR(statbuf.st_mode))
			return (SA_BAD_PATH);

		impl_share = alloc_share(pathname);

		if (impl_share == NULL) {
			rc = SA_NO_MEMORY;
			goto err;
		}

		new_share = B_TRUE;
	}

	if (dataset != NULL) {
		dataset_dup = strdup(dataset);

		if (dataset_dup == NULL) {
			rc = SA_NO_MEMORY;
			goto err;
		}
	}

	free(impl_share->dataset);
	impl_share->dataset = dataset_dup;

	rc = SA_INVALID_PROTOCOL;

	fstype = fstypes;
	while (fstype != NULL) {
		if (strcmp(fstype->name, proto) == 0) {
			if (resource != NULL) {
				resource_dup = strdup(resource);

				if (resource_dup == NULL) {
					rc = SA_NO_MEMORY;
					goto err;
				}
			}

			free(FSINFO(impl_share, fstype)->resource);
			FSINFO(impl_share, fstype)->resource = resource_dup;

			rc = fstype->ops->update_shareopts(impl_share,
			    resource, options);

			if (rc == SA_OK && from_sharetab)
				FSINFO(impl_share, fstype)->active = B_TRUE;

			break;
		}

		fstype = fstype->next;
	}

	if (rc != SA_OK)
		goto err;

	if (new_share) {
		impl_share->handle = impl_handle;

		impl_share->next = impl_handle->shares;
		impl_handle->shares = impl_share;

	}

err:
	if (rc != SA_OK) {
		if (new_share)
			free_share(impl_share);
	}

	return (rc);
}
Exemplo n.º 3
0
sa_share_t
sa_find_share(sa_handle_t handle, char *sharepath)
{
	return ((sa_share_t)find_share((sa_handle_impl_t)handle, sharepath));
}
Exemplo n.º 4
0
/*===========================================================================*
 *				do_exec					     *
 *===========================================================================*/
PUBLIC int do_exec()
{
/* Perform the execve(name, argv, envp) call.  The user library builds a
 * complete stack image, including pointers, args, environ, etc.  The stack
 * is copied to a buffer inside PM, and then to the new core image.
 */
/*
 * 执行 execve(name, argv, envp) 调用. 用户库函数构造了一个完整的栈映像,
 * 包括指针, 命令行参数, 环境变量等等. 栈先复制到 PM 内的一个缓冲区中,
 * 再复制给新的堆栈映像.
 */
  register struct mproc *rmp;
  struct mproc *sh_mp;
  int m, r, fd, ft, sn;
  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
  static char name_buf[PATH_MAX]; /* the name of the file to exec */
  char *new_sp, *name, *basename;
  vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
  phys_bytes tot_bytes;		/* total space for program, including gap */
  long sym_bytes;
  vir_clicks sc;
  struct stat s_buf[2], *s_p;
  vir_bytes pc;

  /* Do some validity checks. */
  rmp = mp; // rmp = mp = 当前进程的 struct mproc 结构
  stk_bytes = (vir_bytes) m_in.stack_bytes;
  if (stk_bytes > ARG_MAX) return(ENOMEM);	/* stack too big */
  if (m_in.exec_len <= 0 || m_in.exec_len > PATH_MAX) return(EINVAL);

  /* Get the exec file name and see if the file is executable. */
  src = (vir_bytes) m_in.exec_name;
  dst = (vir_bytes) name_buf;
  // 将可执行文件的路径名从主调进程复制到 PM 的 name_buf[] 中.
  r = sys_datacopy(who, (vir_bytes) src,
		PM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len);
  if (r != OK) return(r);	/* file name not in user data segment */

  /* Fetch the stack from the user before destroying the old core image. */
  // 将主调进程的栈复制到 mbuf[], 在毁掉旧的核心映像之前
  src = (vir_bytes) m_in.stack_ptr;
  dst = (vir_bytes) mbuf;
  r = sys_datacopy(who, (vir_bytes) src,
  			PM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes);
  /* can't fetch stack (e.g. bad virtual addr) */
  if (r != OK) return(EACCES);	

  r = 0;	/* r = 0 (first attempt), or 1 (interpreted script) */
  name = name_buf;	/* name of file to exec. */
  do {
	s_p = &s_buf[r];
	// 切换到主调进程的当前工作目录
	tell_fs(CHDIR, who, FALSE, 0);  /* switch to the user's FS environ */
	// 检查文件是否可执行, 如果可执行, 返回文件描述符
	fd = allowed(name, s_p, X_BIT);	/* is file executable? */
	if (fd < 0)  return(fd);		/* file was not executable */

	/* Read the file header and extract the segment sizes. */
	sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;

	// 读取文件头部数据, 并赋值给相应参数
	m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
					&tot_bytes, &sym_bytes, sc, &pc);
	if (m != ESCRIPT || ++r > 1) break;
  } while ((name = patch_stack(fd, mbuf, &stk_bytes, name_buf)) != NULL);

  if (m < 0) {
	close(fd);		/* something wrong with header */
	return(stk_bytes > ARG_MAX ? ENOMEM : ENOEXEC);
  }

  /* Can the process' text be shared with that of one already running? */
  sh_mp = find_share(rmp, s_p->st_ino, s_p->st_dev, s_p->st_ctime);

  /* Allocate new memory and release old memory.  Fix map and tell kernel. */
  r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
  if (r != OK) {
	close(fd);		/* insufficient core or program too big */
	return(r);
  }

  /* Save file identification to allow it to be shared. */
  rmp->mp_ino = s_p->st_ino;
  rmp->mp_dev = s_p->st_dev;
  rmp->mp_ctime = s_p->st_ctime;

  /* Patch up stack and copy it from PM to new core image. */
  vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
  vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
  vsp -= stk_bytes;
  patch_ptr(mbuf, vsp);
  src = (vir_bytes) mbuf;
  r = sys_datacopy(PM_PROC_NR, (vir_bytes) src,
  			who, (vir_bytes) vsp, (phys_bytes)stk_bytes);
  if (r != OK) panic(__FILE__,"do_exec stack copy err on", who);

  /* Read in text and data segments. */
  if (sh_mp != NULL) {
	lseek(fd, (off_t) text_bytes, SEEK_CUR);  /* shared: skip text */
  } else {
	rw_seg(0, fd, who, T, text_bytes);
  }
  rw_seg(0, fd, who, D, data_bytes);

  close(fd);			/* don't need exec file any more */

  /* Take care of setuid/setgid bits. */
  if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
	if (s_buf[0].st_mode & I_SET_UID_BIT) {
		rmp->mp_effuid = s_buf[0].st_uid;
		tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
	}
	if (s_buf[0].st_mode & I_SET_GID_BIT) {
		rmp->mp_effgid = s_buf[0].st_gid;
		tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
	}
  }

  /* Save offset to initial argc (for ps) */
  rmp->mp_procargs = vsp;

  /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
  for (sn = 1; sn <= _NSIG; sn++) {
	if (sigismember(&rmp->mp_catch, sn)) {
		sigdelset(&rmp->mp_catch, sn);
		rmp->mp_sigact[sn].sa_handler = SIG_DFL;
		sigemptyset(&rmp->mp_sigact[sn].sa_mask);
	}
  }

  rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
  rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
  new_sp = (char *) vsp;

  tell_fs(EXEC, who, 0, 0);	/* allow FS to handle FD_CLOEXEC files */

  /* System will save command line for debugging, ps(1) output, etc. */
  basename = strrchr(name, '/');
  if (basename == NULL) basename = name; else basename++;
  strncpy(rmp->mp_name, basename, PROC_NAME_LEN-1);
  rmp->mp_name[PROC_NAME_LEN] = '\0';
  sys_exec(who, new_sp, basename, pc);

  /* Cause a signal if this process is traced. */
  if (rmp->mp_flags & TRACED) check_sig(rmp->mp_pid, SIGTRAP);

  return(SUSPEND);		/* no reply, new program just runs */
}