int do_mq_send(void)
{
  /*
  first try to find the right slot.then try puting message into the correponding queue.if this is a sendblocking queue and,using while if cannot insert into
  return -1 if mdq is invalid or cannot insert now
  */
  //check mqd validation
  int mqd = m_in.m7_i5;
  int sender = m_in.m7_i1;
  int to_receive_count = m_in.m7_i2;
  int priority = m_in.m7_i4;

  if(mqs[mqd].registcount <= 0)  //wrong mqd
  {
    //printf("faild to send,wrong mqd\n");
    return -1;
  }
  message_t* pq = 0;
  switch (priority) {
    case 1:
      pq = mqs[mqd].queue_p1;
      break;
    case 2:
      pq = mqs[mqd].queue_p2;
      break;
    case 3:
      pq = mqs[mqd].queue_p3;
      break;
    default:
      pq = mqs[mqd].queue_p4;
  }
  if(mqs[mqd].attribute.sb == 0)//send blocking queue
  {
    while(1)
    {
      int i;
      for(i = 0;i < MAX_MESSAGE_PER_MQ && mqs[mqd].message_count < mqs[mqd].attribute.mm;i++)
      {
        if(pq[i].to_receive_count == 0 && mqs[mqd].message_count < mqs[mqd].attribute.mm) { //this slot is useable
          pq[i].sender = sender;      //set msg sender
          bzero(pq[i].receivers,RECEIVER_LENGTH); //reset receiverlist
          sys_datacopy(who_e, (vir_bytes)m_in.m7_p1, SELF, (vir_bytes)pq[i].receivers, RECEIVER_LENGTH);
          pq[i].to_receive_count = to_receive_count;    //set to_receive_count
          pq[i].priority = priority;
          bzero(pq[i].content,MAX_MSG_LENGTH);
          sys_datacopy(who_e, (vir_bytes)m_in.m7_p2, SELF, (vir_bytes)pq[i].content, MAX_MSG_LENGTH);   //copy message content
          mqs[mqd].message_count ++;
          notify_helper(mqd,&pq[i]);    //notify receivers
          //debug_send();
          return 0;
        }
      }
    }
  }
  else{ //send non-blocking queue
    int i;
    for(i = 0;i < MAX_MESSAGE_PER_MQ && mqs[mqd].message_count < mqs[mqd].attribute.mm;i++)
    {
      if(pq[i].to_receive_count == 0 && mqs[mqd].message_count < mqs[mqd].attribute.mm) { //this slot is useable
        pq[i].sender = sender;      //set msg sender
        bzero(pq[i].receivers,RECEIVER_LENGTH); //reset receiverlist
        sys_datacopy(who_e, (vir_bytes)m_in.m7_p1, SELF, (vir_bytes)pq[i].receivers, RECEIVER_LENGTH);
        pq[i].to_receive_count = to_receive_count;    //set to_receive_count
        pq[i].priority = priority;
        bzero(pq[i].content,MAX_MSG_LENGTH);          //reset content
        sys_datacopy(who_e, (vir_bytes)m_in.m7_p2, SELF, (vir_bytes)pq[i].content, MAX_MSG_LENGTH);   //copy message content
        mqs[mqd].message_count ++;
        notify_helper(mqd,&pq[i]);    //notify receivers
        return 0;
      }
    }
  }
  //printf("now useable slot\n");
  return -1;    //fail to do non-blocking send
}
示例#2
0
文件: sem.c 项目: Hooman3/minix
/*===========================================================================*
 *				do_semop		     		     *
 *===========================================================================*/
int do_semop(message *m)
{
	int id, i, j, r;
	struct sembuf *sops;
	unsigned int nsops;
	struct sem_struct *sem;
	int no_reply = 0;

	id = m->m_lc_ipc_semop.id;
	nsops = m->m_lc_ipc_semop.size;

	r = EINVAL;
	if (!(sem = sem_find_id(id)))
		goto out;

	if (nsops <= 0)
		goto out;

	r = E2BIG;
	if (nsops > SEMOPM)
		goto out;

	/* check for read permission */
	r = EACCES;
	if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
		goto out;

	/* get the array from user application */
	r = ENOMEM;
	sops = malloc(sizeof(struct sembuf) * nsops);
	if (!sops)
		goto out_free;
	r = sys_datacopy(who_e, (vir_bytes) m->m_lc_ipc_semop.ops,
			SELF, (vir_bytes) sops,
			sizeof(struct sembuf) * nsops);
	if (r != OK) {
		r = EINVAL;
		goto out_free;
	}

#ifdef DEBUG_SEM
	for (i = 0; i < nsops; i++)
		printf("SEMOP: num:%d  op:%d  flg:%d\n",
			sops[i].sem_num, sops[i].sem_op, sops[i].sem_flg);
#endif
	/* check for value range */
	r = EFBIG;
	for (i = 0; i < nsops; i++)
		if (sops[i].sem_num >= sem->semid_ds.sem_nsems)
			goto out_free;

	/* check for duplicate number */
	r = EINVAL;
	for (i = 0; i < nsops; i++)
		for (j = i + 1; j < nsops; j++)
			if (sops[i].sem_num == sops[j].sem_num)
				goto out_free;

	/* check for EAGAIN error */
	r = EAGAIN;
	for (i = 0; i < nsops; i++) {
		int op_n, val;

		op_n = sops[i].sem_op;
		val = sem->sems[sops[i].sem_num].semval;

		if ((sops[i].sem_flg & IPC_NOWAIT) &&
				((!op_n && val) ||
				 (op_n < 0 &&
				  -op_n > val)))
			goto out_free;

	}
	/* there will be no errors left, so we can go ahead */
	for (i = 0; i < nsops; i++) {
		struct semaphore *s;
		int op_n;

		s = &sem->sems[sops[i].sem_num];
		op_n = sops[i].sem_op;

		s->sempid = getnpid(who_e);

		if (op_n > 0) {
			/* check for alter permission */
			r = EACCES;
			if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
				goto out_free;
			s->semval += sops[i].sem_op;
		} else if (!op_n) {
			if (s->semval) {
				/* put the process asleep */
				s->semzcnt++;
				s->zlist = realloc(s->zlist, sizeof(struct waiting) * s->semzcnt);
				if (!s->zlist) {
					printf("IPC: zero waiting list lost...\n");
					break;
				}
				s->zlist[s->semzcnt-1].who = who_e;
				s->zlist[s->semzcnt-1].val = op_n;

#ifdef DEBUG_SEM
				printf("SEMOP: Put into sleep... %d\n", who_e);
#endif
				no_reply++;
			}
		} else {
			/* check for alter permission */
			r = EACCES;
			if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
				goto out_free;
			if (s->semval >= -op_n)
				s->semval += op_n;
			else {
				/* put the process asleep */
				s->semncnt++;
				s->nlist = realloc(s->nlist, sizeof(struct waiting) * s->semncnt);
				if (!s->nlist) {
					printf("IPC: increase waiting list lost...\n");
					break;
				}
				s->nlist[s->semncnt-1].who = who_e;
				s->nlist[s->semncnt-1].val = -op_n;

				no_reply++;
			}
		}
	}

	r = OK;
out_free:
	free(sops);
out:
	/* if we reach here by errors
	 * or with no errors but we should reply back.
	 */
	if (r != OK || !no_reply) {
		m->m_type = r;

		ipc_sendnb(who_e, m);
	}

	/* awaken process if possible */
	update_semaphores();

	return 0;
}
示例#3
0
/*===========================================================================*
 *				do_shmctl		     		     *
 *===========================================================================*/
int do_shmctl(message *m)
{
	int id = m->SHMCTL_ID;
	int cmd = m->SHMCTL_CMD;
	struct shmid_ds *ds = (struct shmid_ds *)m->SHMCTL_BUF;
	struct shmid_ds tmp_ds;
	struct shm_struct *shm = NULL;
	struct shminfo sinfo;
	struct shm_info s_info;
	uid_t uid;
	int r, i;

	if (cmd == IPC_STAT)
		update_refcount_and_destroy();

	if ((cmd == IPC_STAT ||
		cmd == IPC_SET ||
		cmd == IPC_RMID) &&
		!(shm = shm_find_id(id)))
		return EINVAL;

	switch (cmd) {
	case IPC_STAT:
		if (!ds)
			return EFAULT;
		/* check whether it has read permission */
		if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444))
			return EACCES;
		r = sys_datacopy(SELF_E, (vir_bytes)&shm->shmid_ds,
			who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
		if (r != OK)
			return EFAULT;
		break;
	case IPC_SET:
		uid = getnuid(who_e);
		if (uid != shm->shmid_ds.shm_perm.cuid &&
			uid != shm->shmid_ds.shm_perm.uid &&
			uid != 0)
			return EPERM;
		r = sys_datacopy(who_e, (vir_bytes)ds,
			SELF_E, (vir_bytes)&tmp_ds, sizeof(struct shmid_ds));
		if (r != OK)
			return EFAULT;
		shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
		shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
		shm->shmid_ds.shm_perm.mode &= ~0777;
		shm->shmid_ds.shm_perm.mode |= tmp_ds.shm_perm.mode & 0666;
		shm->shmid_ds.shm_ctime = time(NULL);
		break;
	case IPC_RMID:
		uid = getnuid(who_e);
		if (uid != shm->shmid_ds.shm_perm.cuid &&
			uid != shm->shmid_ds.shm_perm.uid &&
			uid != 0)
			return EPERM;
		shm->shmid_ds.shm_perm.mode |= SHM_DEST;
		/* destroy if possible */
		update_refcount_and_destroy();
		break;
	case IPC_INFO:
		if (!ds)
			return EFAULT;
		sinfo.shmmax = (unsigned long) -1;
		sinfo.shmmin = 1;
		sinfo.shmmni = MAX_SHM_NR;
		sinfo.shmseg = (unsigned long) -1;
		sinfo.shmall = (unsigned long) -1;
		r = sys_datacopy(SELF_E, (vir_bytes)&sinfo,
			who_e, (vir_bytes)ds, sizeof(struct shminfo));
		if (r != OK)
			return EFAULT;
		m->SHMCTL_RET = shm_list_nr - 1;
		if (m->SHMCTL_RET < 0)
			m->SHMCTL_RET = 0;
		break;
	case SHM_INFO:
		if (!ds)
			return EFAULT;
		s_info.used_ids = shm_list_nr;
		s_info.shm_tot = 0;
		for (i = 0; i < shm_list_nr; i++)
			s_info.shm_tot +=
				shm_list[i].shmid_ds.shm_segsz/I386_PAGE_SIZE;
		s_info.shm_rss = s_info.shm_tot;
		s_info.shm_swp = 0;
		s_info.swap_attempts = 0;
		s_info.swap_successes = 0;
		r = sys_datacopy(SELF_E, (vir_bytes)&s_info,
			who_e, (vir_bytes)ds, sizeof(struct shm_info));
		if (r != OK)
			return EFAULT;
		m->SHMCTL_RET = shm_list_nr - 1;
		if (m->SHMCTL_RET < 0)
			m->SHMCTL_RET = 0;
		break;
	case SHM_STAT:
		if (id < 0 || id >= shm_list_nr)
			return EINVAL;
		shm = &shm_list[id];
		r = sys_datacopy(SELF_E, (vir_bytes)&shm->shmid_ds,
			who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
		if (r != OK)
			return EFAULT;
		m->SHMCTL_RET = shm->id;
		break;
	default:
		return EINVAL;
	}
	return OK;
}
示例#4
0
static int
store_t(endpoint_t who_e, vir_bytes rtcdev_tm, struct tm *t)
{
	return sys_datacopy(SELF, (vir_bytes) t, who_e, rtcdev_tm,
	    sizeof(struct tm));
}
示例#5
0
文件: sem.c 项目: Hooman3/minix
/*===========================================================================*
 *				do_semctl		     		     *
 *===========================================================================*/
int do_semctl(message *m)
{
	int r, i;
	long opt = 0;
	uid_t uid;
	int id, num, cmd, val;
	unsigned short *buf;
	struct semid_ds *ds, tmp_ds;
	struct sem_struct *sem;

	id = m->m_lc_ipc_semctl.id;
	num = m->m_lc_ipc_semctl.num;
	cmd = m->m_lc_ipc_semctl.cmd;

	if (cmd == IPC_STAT || cmd == IPC_SET || cmd == IPC_INFO ||
		cmd == SEM_INFO || cmd == SEM_STAT || cmd == GETALL ||
		cmd == SETALL || cmd == SETVAL)
		opt = m->m_lc_ipc_semctl.opt;

	if (!(sem = sem_find_id(id))) {
		return EINVAL;
	}

	/* IPC_SET and IPC_RMID as its own permission check */
	if (cmd != IPC_SET && cmd != IPC_RMID) {
		/* check read permission */
		if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
			return EACCES;
	}

	switch (cmd) {
	case IPC_STAT:
		ds = (struct semid_ds *) opt;
		if (!ds)
			return EFAULT;
		r = sys_datacopy(SELF, (vir_bytes) &sem->semid_ds,
			who_e, (vir_bytes) ds, sizeof(struct semid_ds));
		if (r != OK)
			return EINVAL;
		break;
	case IPC_SET:
		uid = getnuid(who_e);
		if (uid != sem->semid_ds.sem_perm.cuid &&
			uid != sem->semid_ds.sem_perm.uid &&
			uid != 0)
			return EPERM;
		ds = (struct semid_ds *) opt;
		r = sys_datacopy(who_e, (vir_bytes) ds,
			SELF, (vir_bytes) &tmp_ds, sizeof(struct semid_ds));
		if (r != OK)
			return EINVAL;
		sem->semid_ds.sem_perm.uid = tmp_ds.sem_perm.uid;
		sem->semid_ds.sem_perm.gid = tmp_ds.sem_perm.gid;
		sem->semid_ds.sem_perm.mode &= ~0777;
		sem->semid_ds.sem_perm.mode |= tmp_ds.sem_perm.mode & 0666;
		sem->semid_ds.sem_ctime = time(NULL);
		break;
	case IPC_RMID:
		uid = getnuid(who_e);
		if (uid != sem->semid_ds.sem_perm.cuid &&
			uid != sem->semid_ds.sem_perm.uid &&
			uid != 0)
			return EPERM;
		/* awaken all processes block in semop
		 * and remove the semaphore set.
		 */
		update_one_semaphore(sem, 1);
		break;
	case IPC_INFO:
		break;
	case SEM_INFO:
		break;
	case SEM_STAT:
		break;
	case GETALL:
		buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (!buf)
			return ENOMEM;
		for (i = 0; i < sem->semid_ds.sem_nsems; i++)
			buf[i] = sem->sems[i].semval;
		r = sys_datacopy(SELF, (vir_bytes) buf,
			who_e, (vir_bytes) opt,
			sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (r != OK)
			return EINVAL;
		free(buf);
		break;
	case GETNCNT:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->m_lc_ipc_semctl.ret = sem->sems[num].semncnt;
		break;
	case GETPID:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->m_lc_ipc_semctl.ret = sem->sems[num].sempid;
		break;
	case GETVAL:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->m_lc_ipc_semctl.ret = sem->sems[num].semval;
		break;
	case GETZCNT:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->m_lc_ipc_semctl.ret = sem->sems[num].semzcnt;
		break;
	case SETALL:
		buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (!buf)
			return ENOMEM;
		r = sys_datacopy(who_e, (vir_bytes) opt,
			SELF, (vir_bytes) buf,
			sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (r != OK)
			return EINVAL;
#ifdef DEBUG_SEM
		printf("SEMCTL: SETALL: opt: %lu\n", (vir_bytes) opt);
		for (i = 0; i < sem->semid_ds.sem_nsems; i++)
			printf("SEMCTL: SETALL val: [%d] %d\n", i, buf[i]);
#endif
		for (i = 0; i < sem->semid_ds.sem_nsems; i++) {
			if (buf[i] > SEMVMX) {
				free(buf);
				update_semaphores();
				return ERANGE;
			}
			sem->sems[i].semval = buf[i];
		}
		free(buf);
		/* awaken if possible */
		update_semaphores();
		break;
	case SETVAL:
		val = (int) opt;
		/* check write permission */
		if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
			return EACCES;
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		if (val < 0 || val > SEMVMX)
			return ERANGE;
		sem->sems[num].semval = val;
#ifdef DEBUG_SEM
		printf("SEMCTL: SETVAL: %d %d\n", num, val);
#endif
		sem->semid_ds.sem_ctime = time(NULL);
		/* awaken if possible */
		update_semaphores();
		break;
	default:
		return EINVAL;
	}

	return OK;
}
示例#6
0
文件: misc.c 项目: tizzybec/minix
/*===========================================================================*
 *				do_fcntl				     *
 *===========================================================================*/
int do_fcntl()
{
/* Perform the fcntl(fd, request, ...) system call. */

  register struct filp *f;
  int new_fd, fl, r = OK, fcntl_req, fcntl_argx;
  tll_access_t locktype;

  scratch(fp).file.fd_nr = job_m_in.fd;
  scratch(fp).io.io_buffer = job_m_in.buffer;
  scratch(fp).io.io_nbytes = job_m_in.nbytes;	/* a.k.a. m_in.request */
  fcntl_req = job_m_in.request;
  fcntl_argx = job_m_in.addr;

  /* Is the file descriptor valid? */
  locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ;
  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
	return(err_code);

  switch (fcntl_req) {
    case F_DUPFD:
	/* This replaces the old dup() system call. */
	if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
	else if ((r = get_fd(fcntl_argx, 0, &new_fd, NULL)) == OK) {
		f->filp_count++;
		fp->fp_filp[new_fd] = f;
		FD_SET(new_fd, &fp->fp_filp_inuse);
		r = new_fd;
	}
	break;

    case F_GETFD:
	/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	r = 0;
	if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
		r = FD_CLOEXEC;
	break;

    case F_SETFD:
	/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	if (fcntl_argx & FD_CLOEXEC)
		FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	else
		FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	break;

    case F_GETFL:
	/* Get file status flags (O_NONBLOCK and O_APPEND). */
	fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
	r = fl;
	break;

    case F_SETFL:
	/* Set file status flags (O_NONBLOCK and O_APPEND). */
	fl = O_NONBLOCK | O_APPEND | O_REOPEN;
	f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
	break;

    case F_GETLK:
    case F_SETLK:
    case F_SETLKW:
	/* Set or clear a file lock. */
	r = lock_op(f, fcntl_req);
	break;

    case F_FREESP:
     {
	/* Free a section of a file */
	off_t start, end;
	struct flock flock_arg;
	signed long offset;

	/* Check if it's a regular file. */
	if ((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) r = EINVAL;
	else if (!(f->filp_mode & W_BIT)) r = EBADF;
	else
		/* Copy flock data from userspace. */
		r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer,
				 SELF, (vir_bytes) &flock_arg,
				 sizeof(flock_arg));

	if (r != OK) break;

	/* Convert starting offset to signed. */
	offset = (signed long) flock_arg.l_start;

	/* Figure out starting position base. */
	switch(flock_arg.l_whence) {
	  case SEEK_SET: start = 0; break;
	  case SEEK_CUR:
		if (ex64hi(f->filp_pos) != 0)
			panic("do_fcntl: position in file too high");
		start = ex64lo(f->filp_pos);
		break;
	  case SEEK_END: start = f->filp_vno->v_size; break;
	  default: r = EINVAL;
	}
	if (r != OK) break;

	/* Check for overflow or underflow. */
	if (offset > 0 && start + offset < start) r = EINVAL;
	else if (offset < 0 && start + offset > start) r = EINVAL;
	else {
		start += offset;
		if (start < 0) r = EINVAL;
	}
	if (r != OK) break;

	if (flock_arg.l_len != 0) {
		if (start >= f->filp_vno->v_size) r = EINVAL;
		else if ((end = start + flock_arg.l_len) <= start) r = EINVAL;
		else if (end > f->filp_vno->v_size) end = f->filp_vno->v_size;
	} else {
                end = 0;
	}
	if (r != OK) break;

	r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,start,end);

	if (r == OK && flock_arg.l_len == 0)
		f->filp_vno->v_size = start;

	break;
     }

    default:
	r = EINVAL;
  }

  unlock_filp(f);
  return(r);
}
示例#7
0
文件: exec.c 项目: wuzhouhui/misc
/*===========================================================================*
 *				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 */
}
示例#8
0
文件: exec.c 项目: vivekp/minix-1
/*===========================================================================*
 *				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);
}
示例#9
0
文件: exec.c 项目: grd/minix
/*===========================================================================*
 *				pm_exec					     *
 *===========================================================================*/
int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
		   vir_bytes frame, size_t frame_len, vir_bytes *pc,
		   vir_bytes *newsp, int user_exec_flags)
{
/* 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, slot;
  vir_bytes vsp;
  struct fproc *rfp;
  int extrabase = 0;
  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
  struct vfs_exec_info execi;
  int i;
  static char fullpath[PATH_MAX],
  	elf_interpreter[PATH_MAX],
	firstexec[PATH_MAX],
	finalexec[PATH_MAX];
  struct lookup resolve;
  struct fproc *vmfp = &fproc[VM_PROC_NR];
  stackhook_t makestack = NULL;
  static int n;
  n++;
  struct filp *newfilp = NULL;

  lock_exec();
  lock_proc(vmfp, 0);

  /* unset execi values are 0. */
  memset(&execi, 0, sizeof(execi));
  execi.vmfd = -1;

  /* passed from exec() libc code */
  execi.userflags = user_exec_flags;
  execi.args.stack_high = kinfo.user_sp;
  execi.args.stack_size = DEFAULT_STACK_LIMIT;

  okendpt(proc_e, &slot);
  rfp = fp = &fproc[slot];
  rfp->text_size = 0;
  rfp->data_size = 0;

  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp);

  resolve.l_vmnt_lock = VMNT_READ;
  resolve.l_vnode_lock = VNODE_READ;

  /* Fetch the stack from the user before destroying the old core image. */
  if (frame_len > ARG_MAX)
	FAILCHECK(ENOMEM); /* stack too big */

  r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
		   (size_t) frame_len);
  if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
        printf("VFS: pm_exec: sys_datacopy failed\n");
	FAILCHECK(r);
  }

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

  /* Get the exec file name. */
  FAILCHECK(fetch_name(path, path_len, fullpath));
  strlcpy(finalexec, fullpath, PATH_MAX);
  strlcpy(firstexec, fullpath, PATH_MAX);

  /* Get_read_vp will return an opened vn in execi.
   * if necessary it releases the existing vp so we can
   * switch after we find out what's inside the file.
   * It reads the start of the file.
   */
  Get_read_vp(execi, fullpath, 1, 1, &resolve, fp);

  /* If this is a script (i.e. has a #!/interpreter line),
   * retrieve the name of the interpreter and open that
   * executable instead.
   */
  if(is_script(&execi)) {
  	/* patch_stack will add interpreter name and
	 * args to stack and retrieve the new binary
	 * name into fullpath.
	 */
	FAILCHECK(fetch_name(path, path_len, fullpath));
	FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath));
	strlcpy(finalexec, fullpath, PATH_MAX);
  	strlcpy(firstexec, fullpath, PATH_MAX);
	Get_read_vp(execi, fullpath, 1, 0, &resolve, fp);
  }

  /* If this is a dynamically linked executable, retrieve
   * the name of that interpreter in elf_interpreter and open that
   * executable instead. But open the current executable in an
   * fd for the current process.
   */
  if(elf_has_interpreter(execi.args.hdr, execi.args.hdr_len,
	elf_interpreter, sizeof(elf_interpreter))) {
	/* Switch the executable vnode to the interpreter */
	execi.is_dyn = 1;

	/* The interpreter (loader) needs an fd to the main program,
	 * which is currently in finalexec
	 */
	if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) {
		printf("VFS: exec: dynamic: open main exec failed %s (%d)\n",
			fullpath, r);
		FAILCHECK(r);
	}

	/* ld.so is linked at 0, but it can relocate itself; we
	 * want it higher to trap NULL pointer dereferences. 
	 */
	execi.args.load_offset = 0x10000;

	/* Remember it */
	strlcpy(execi.execname, finalexec, PATH_MAX);

	/* The executable we need to execute first (loader)
	 * is in elf_interpreter, and has to be in fullpath to
	 * be looked up
	 */
	strlcpy(fullpath, elf_interpreter, PATH_MAX);
	strlcpy(firstexec, elf_interpreter, PATH_MAX);
	Get_read_vp(execi, fullpath, 0, 0, &resolve, fp);
  }

  /* We also want an FD for VM to mmap() the process in if possible. */
  {
	struct vnode *vp = execi.vp;
	assert(vp);
	if(vp->v_vmnt->m_haspeek && major(vp->v_dev) != MEMORY_MAJOR) {
		int newfd = -1;
		if(get_fd(vmfp, 0, R_BIT, &newfd, &newfilp) == OK) {
			assert(newfd >= 0 && newfd < OPEN_MAX);
			assert(!vmfp->fp_filp[newfd]);
			newfilp->filp_count = 1;
			newfilp->filp_vno = vp;
			newfilp->filp_flags = O_RDONLY;
			FD_SET(newfd, &vmfp->fp_filp_inuse);
			vmfp->fp_filp[newfd] = newfilp;
			/* dup_vnode(vp); */
			execi.vmfd = newfd;
			execi.args.memmap = vfs_memmap;
		}
	}
  }

  /* callback functions and data */
  execi.args.copymem = read_seg;
  execi.args.clearproc = libexec_clearproc_vm_procctl;
  execi.args.clearmem = libexec_clear_sys_memset;
  execi.args.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared;
  execi.args.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk;
  execi.args.allocmem_ondemand = libexec_alloc_mmap_ondemand;
  execi.args.opaque = &execi;

  execi.args.proc_e = proc_e;
  execi.args.frame_len = frame_len;
  execi.args.filesize = execi.vp->v_size;

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

  FAILCHECK(r);

  /* Inform PM */
  FAILCHECK(libexec_pm_newexec(proc_e, &execi.args));

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

  /* call a stack-setup function if this executable type wants it */
  vsp = execi.args.stack_high - frame_len;
  if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase));

  /* Patch up stack and copy it from VFS to new core image. */
  libexec_patch_ptr(mbuf, vsp + extrabase);
  FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
		   (phys_bytes)frame_len));

  /* Return new stack pointer to caller */
  *newsp = vsp;

  clo_exec(rfp);

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

  /* Remember the new name of the process */
  strlcpy(rfp->fp_name, execi.args.progname, PROC_NAME_LEN);
  rfp->text_size = execi.args.text_size;
  rfp->data_size = execi.args.data_size;

pm_execfinal:
  if(newfilp) unlock_filp(newfilp);
  else if (execi.vp != NULL) {
	unlock_vnode(execi.vp);
	put_vnode(execi.vp);
  }

  if(execi.vmfd >= 0 && !execi.vmfd_used) {
  	if(OK != close_fd(vmfp, execi.vmfd)) {
		printf("VFS: unexpected close fail of vm fd\n");
	}
  }

  unlock_proc(vmfp);
  unlock_exec();

  return(r);
}
示例#10
0
/*==========================================================================*
 *				do_vrdwt				    *
 *==========================================================================*/
PRIVATE int do_vrdwt(message* mp)
 /* mp - pointer to read or write message */
{
/* Carry out an device read or write to/from a vector of user addresses.
 * The "user addresses" are assumed to be safe, i.e. FS transferring to/from
 * its own buffers, so they are not checked.
 */
  static iovec_t iovec[NR_IOREQS];
  iovec_t *iov;
  phys_bytes iovec_size;
  unsigned nr_req, position;
  int r;
  message m_dd; /*message for disk driver*/
  nr_req = mp->COUNT;	/* Length of I/O vector */
  position = mp->POSITION;

		/* Copy the vector from the caller to kernel space. */
		if (nr_req > NR_IOREQS) nr_req = NR_IOREQS;
			iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0]));

		if (OK != sys_datacopy(mp->m_source, (vir_bytes) mp->ADDRESS, 
				SELF, (vir_bytes) iovec, iovec_size))
			panic("Crypt Drive","bad I/O vector by", s);
		iov = iovec;
  
	while(nr_req>0){
		vir_bytes user_vir = iov->iov_addr; /*User program mem addresss*/
		unsigned count = iov->iov_size; /* number of byted to copy */
		
		printf("CryptDrive: Size:%d , DST:%d , POS:%d, REQ: %d/%d \n",count, user_vir, position, nr_req, mp->COUNT);
		
		if(mp->m_type == DEV_GATHER){
			m_dd.m_type=DEV_READ;
			m_dd.DEVICE=mp->DEVICE;
			m_dd.m_source=thispid;
			m_dd.COUNT=count;
			m_dd.POSITION=position;
			m_dd.ADDRESS=(vir_bytes)  buffer;	
			if(OK != sendrec(DRVR_PROC_NR, &m_dd))
				panic("CryptDrive","do_rdv messaging failed",s);
			
			/* decrypt here  - this line here */
			/*from here to caller*/
			sys_vircopy(SELF, D, buffer, proc_nr, D, user_vir, m_dd.COUNT);
			
		}
		if(mp->m_type == DEV_SCATTER){
			/*from caller to here*/
			sys_vircopy(proc_nr, D, user_vir, SELF, D, buffer, count);
			/*ENCYPT Here - this line no more no less*/
			
			m_dd.m_type=DEV_WRITE;
			m_dd.DEVICE=mp->DEVICE;
			m_dd.m_source=thispid;
			m_dd.COUNT=count;
			m_dd.POSITION=position;
			m_dd.ADDRESS=(vir_bytes)  buffer;	
			if(OK != sendrec(DRVR_PROC_NR, &m_dd))
				panic("CryptDrive","do_wtv messaging failed",s);
			count=m_dd.REP_STATUS;
		}
		
		/* Book the number of bytes transferred. */
        position += count;
        iov->iov_addr += count;
        if ((iov->iov_size -= count) == 0) { iov++; nr_req--; } /* vector done; next request */
	}
	
	/* Copy the I/O vector back to the caller. */
	if (mp->m_source >= 0) {
		sys_datacopy(SELF, (vir_bytes) iovec, 
			mp->m_source, (vir_bytes) mp->ADDRESS, iovec_size);
	}

	mp->m_type = TASK_REPLY;
	mp->REP_PROC_NR = proc_nr;
	mp->m_source=thispid;
	/* Status is ok */
	mp->REP_STATUS = OK;	
	send(device_caller, mp);
	
	return(OK);
}