Пример #1
0
/*===========================================================================*
 *                             do_lstat					     *
 *===========================================================================*/
int do_lstat()
{
/* Perform the lstat(name, buf) system call. */
  struct vnode *vp;
  struct vmnt *vmp;
  int r;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  int old_stat = 0;
  vir_bytes vname1, statbuf;
  size_t vname1_length;

  vname1 = (vir_bytes) job_m_in.name1;
  vname1_length = (size_t) job_m_in.name1_length;
  statbuf = (vir_bytes) job_m_in.name2;

  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  if (job_call_nr == PREV_LSTAT)
	old_stat = 1;
  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
  r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat);

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return(r);
}
Пример #2
0
/*===========================================================================*
 *				do_fstat				     *
 *===========================================================================*/
int do_fstat()
{
/* Perform the fstat(fd, buf) system call. */
  register struct filp *rfilp;
  int r, pipe_pos = 0, old_stat = 0, rfd;
  vir_bytes statbuf;

  statbuf = (vir_bytes) job_m_in.buffer;
  rfd = job_m_in.fd;

  if (job_call_nr == PREV_FSTAT)
	old_stat = 1;

  /* Is the file descriptor valid? */
  if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);

  /* If we read from a pipe, send position too */
  if (rfilp->filp_vno->v_pipe == I_PIPE) {
	if (rfilp->filp_mode & R_BIT)
		if (ex64hi(rfilp->filp_pos) != 0) {
			panic("do_fstat: bad position in pipe");
		}
	pipe_pos = ex64lo(rfilp->filp_pos);
  }

  r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
	       who_e, statbuf, pipe_pos, old_stat);

  unlock_filp(rfilp);

  return(r);
}
Пример #3
0
/*===========================================================================*
 *                             do_lstat					     *
 *===========================================================================*/
int do_lstat(void)
{
/* Perform the lstat(name, buf) system call. */
  struct vnode *vp;
  struct vmnt *vmp;
  int r;
  char fullpath[PATH_MAX];
  struct lookup resolve;
  vir_bytes vname1, statbuf;
  size_t vname1_length;

  vname1 = job_m_in.m_lc_vfs_stat.name;
  vname1_length = job_m_in.m_lc_vfs_stat.len;
  statbuf = job_m_in.m_lc_vfs_stat.buf;

  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
  r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf);

  unlock_vnode(vp);
  unlock_vmnt(vmp);

  put_vnode(vp);
  return(r);
}
Пример #4
0
/*===========================================================================*
 *				do_fstat				     *
 *===========================================================================*/
int do_fstat(void)
{
/* Perform the fstat(fd, buf) system call. */
  register struct filp *rfilp;
  int r, rfd;
  vir_bytes statbuf;

  statbuf = job_m_in.m_lc_vfs_fstat.buf;
  rfd = job_m_in.m_lc_vfs_fstat.fd;

  /* Is the file descriptor valid? */
  if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);

  r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
	       who_e, statbuf);

  unlock_filp(rfilp);

  return(r);
}
Пример #5
0
/*===========================================================================*
 *				get_read_vp				     *
 *===========================================================================*/
static int get_read_vp(struct vfs_exec_info *execi,
  char *fullpath, int copyprogname, int sugid, struct lookup *resolve, struct fproc *fp)
{
/* Make the executable that we want to exec() into the binary pointed
 * to by 'fullpath.' This function fills in necessary details in the execi
 * structure, such as opened vnode. It unlocks and releases the vnode if
 * it was already there. This makes it easy to change the executable
 * during the exec(), which is often necessary, by calling this function
 * more than once. This is specifically necessary when we discover the
 * executable is actually a script or a dynamically linked executable.
 */
	int r;

	/* Caller wants to switch vp to the file in 'fullpath.'
	 * unlock and put it first if there is any there.
	 */
	if(execi->vp) {
		unlock_vnode(execi->vp);
		put_vnode(execi->vp);
		execi->vp = NULL;
	}

	/* Remember/overwrite the executable name if requested. */
	if(copyprogname) {
		char *cp = strrchr(fullpath, '/');
		if(cp) cp++;
		else cp = fullpath;
		strlcpy(execi->args.progname, cp, sizeof(execi->args.progname));
		execi->args.progname[sizeof(execi->args.progname)-1] = '\0';
	}

	/* Open executable */
	if ((execi->vp = eat_path(resolve, fp)) == NULL)
		return err_code;

	unlock_vmnt(execi->vmp);

	if (!S_ISREG(execi->vp->v_mode))
		return ENOEXEC;
	else if ((r = forbidden(fp, execi->vp, X_BIT)) != OK)
		return r;
	else
		r = req_stat(execi->vp->v_fs_e, execi->vp->v_inode_nr,
			VFS_PROC_NR, (vir_bytes) &(execi->sb));

	if (r != OK) return r;

	/* If caller wants us to, honour suid/guid mode bits. */
        if (sugid) {
		/* Deal with setuid/setgid executables */
		if (execi->vp->v_mode & I_SET_UID_BIT) {
			execi->args.new_uid = execi->vp->v_uid;
			execi->args.allow_setuid = 1;
		}
		if (execi->vp->v_mode & I_SET_GID_BIT) {
			execi->args.new_gid = execi->vp->v_gid;
			execi->args.allow_setuid = 1;
		}
        }

	/* Read in first chunk of file. */
	if((r=map_header(execi)) != OK)
		return r;

	return OK;
}
Пример #6
0
/*===========================================================================*
 *				pm_exec					     *
 *===========================================================================*/
PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
		   vir_bytes frame_len, vir_bytes *pc)
{
/* 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 VFS, and then to the new core image.
 */
  int r, r1, round, proc_s;
  vir_bytes vsp;
  struct fproc *rfp;
  struct vnode *vp;
  char *cp;
  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
  struct exec_info execi;
  int i;

  okendpt(proc_e, &proc_s);
  rfp = fp = &fproc[proc_s];
  who_e = proc_e;
  who_p = proc_s;
  super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */

  /* Get the exec file name. */
  if ((r = fetch_name(path, path_len, 0)) != OK) return(r);

  /* Fetch the stack from the user before destroying the old core image. */
  if (frame_len > ARG_MAX) {
		printf("VFS: pm_exec: stack too big\n");
		return(ENOMEM);	/* stack too big */
	}
  r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
  		   (phys_bytes) frame_len);
  if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
        printf("pm_exec: sys_datacopy failed\n");
        return(r);	
  }

  /* The default is to keep the original user and group IDs */
  execi.new_uid = rfp->fp_effuid;
  execi.new_gid = rfp->fp_effgid;

  for (round= 0; round < 2; round++) {
	/* round = 0 (first attempt), or 1 (interpreted script) */

	/* Save the name of the program */
	(cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);

	strncpy(execi.progname, cp, PROC_NAME_LEN-1);
	execi.progname[PROC_NAME_LEN-1] = '\0';
	execi.setugid = 0;

	/* Open executable */
	if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
	execi.vp = vp;

	if ((vp->v_mode & I_TYPE) != I_REGULAR) 
		r = ENOEXEC;
	else if ((r1 = forbidden(vp, X_BIT)) != OK)
		r = r1;
	else
		r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR,
			     (char *) &(execi.sb), 0, 0);
	if (r != OK) {
	    put_vnode(vp);
	    return(r);
	}

        if (round == 0) {
		/* Deal with setuid/setgid executables */
		if (vp->v_mode & I_SET_UID_BIT) {
			execi.new_uid = vp->v_uid;
			execi.setugid = 1;
		}
		if (vp->v_mode & I_SET_GID_BIT) {
			execi.new_gid = vp->v_gid;
			execi.setugid = 1;
		}
        }

	r = map_header(&execi.hdr, execi.vp);
	if (r != OK) {
	    put_vnode(vp);
	    return(r);
	}

	if (!is_script(execi.hdr, execi.vp->v_size) || round != 0)
		break;

	/* Get fresh copy of the file name. */
	if ((r = fetch_name(path, path_len, 0)) != OK) 
		printf("VFS pm_exec: 2nd fetch_name failed\n");
	else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK) 
		printf("VFS pm_exec: patch_stack failed\n");
	put_vnode(vp);
	if (r != OK) return(r);
  }

  execi.proc_e = proc_e;
  execi.frame_len = frame_len;

  for(i = 0; exec_loaders[i].load_object != NULL; i++) {
      r = (*exec_loaders[i].load_object)(&execi);
      /* Loaded successfully, so no need to try other loaders */
      if (r == OK) break;
  }
  put_vnode(vp);

  /* No exec loader could load the object */
  if (r != OK) {
	return(ENOEXEC);
  }

  /* Save off PC */
  *pc = execi.pc;

  /* Patch up stack and copy it from VFS to new core image. */
  vsp = execi.stack_top;
  vsp -= frame_len;
  patch_ptr(mbuf, vsp);
  if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
		   (phys_bytes)frame_len)) != OK) {
	printf("VFS: datacopy failed (%d) trying to copy to %lu\n", r, vsp);
	return(r);
  }

  if (r != OK) return(r);
  clo_exec(rfp);

  if (execi.setugid) {
	/* If after loading the image we're still allowed to run with
	 * setuid or setgid, change the credentials now */
	rfp->fp_effuid = execi.new_uid;
	rfp->fp_effgid = execi.new_gid;
  }

  /* This child has now exec()ced. */
  rfp->fp_execced = 1;

  return(OK);
}