Exemplo n.º 1
0
/*===========================================================================*
 *				do_reboot				     *
 *===========================================================================*/
int do_reboot()
{
    message m;

    /* Check permission to abort the system. */
    if (mp->mp_effuid != SUPER_USER) return(EPERM);

    /* See how the system should be aborted. */
    abort_flag = m_in.m_lc_pm_reboot.how;

    /* notify readclock (some arm systems power off via RTC alarms) */
    if (abort_flag & RB_POWERDOWN) {
        endpoint_t readclock_ep;
        if (ds_retrieve_label_endpt("readclock.drv", &readclock_ep) == OK) {
            message m; /* no params to set, nothing we can do if it fails */
            _taskcall(readclock_ep, RTCDEV_PWR_OFF, &m);
        }
    }

    /* Order matters here. When VFS is told to reboot, it exits all its
     * processes, and then would be confused if they're exited again by
     * SIGKILL. So first kill, then reboot.
     */

    check_sig(-1, SIGKILL, FALSE /* ksig*/); /* kill all users except init */
    sys_stop(INIT_PROC_NR);		   /* stop init, but keep it around */

    /* Tell VFS to reboot */
    memset(&m, 0, sizeof(m));
    m.m_type = VFS_PM_REBOOT;

    tell_vfs(&mproc[VFS_PROC_NR], &m);

    return(SUSPEND);			/* don't reply to caller */
}
Exemplo n.º 2
0
static void jargrep(regex_t *exp, regex_t *nl_exp, const char *jarfile, int options){
	int fd;
	int floop = TRUE;
	pb_file pbf;
	ub1 scratch[16];

	if((fd = open(jarfile, O_RDONLY)) == -1) {
		if(!(options & JG_SUPRESS_ERROR))
			fprintf(stderr, "Error reading file '%s': %s\n", jarfile, strerror(errno));
	}
	else {
		pb_init(&pbf, fd);	
		
		do {
			if(pb_read(&pbf, scratch, 4) != 4) {
				perror("read");
				floop = FALSE;
			}
			else {
				switch (check_sig(scratch, &pbf)) {
				case 0:
					floop = cont_grep(exp, nl_exp, fd, &pbf, options);
					break;
				case 1:
					floop = FALSE;
					break;
				case 2:
          continue; /* fall through continue */
				}
			}
		} while(floop);
	}
}
Exemplo n.º 3
0
/*===========================================================================*
 *				do_ksig					     *
 *===========================================================================*/
PUBLIC int do_ksig()
{
/* Certain signals, such as segmentation violations and DEL, originate in the
 * kernel.  When the kernel detects such signals, it sets bits in a bit map.
 * As soon as MM is awaiting new work, the kernel sends MM a message containing
 * the process slot and bit map.  That message comes here.  The File System
 * also uses this mechanism to signal writing on broken pipes (SIGPIPE).
 */

  register struct mproc *rmp;
  int i, proc_nr;
  pid_t proc_id, id;
  sigset_t sig_map;

  /* Only kernel may make this call. */
  if (who != HARDWARE) return(EPERM);
  dont_reply = TRUE;		/* don't reply to the kernel */
  proc_nr = mm_in.SIG_PROC;
  rmp = &mproc[proc_nr];
  if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
  proc_id = rmp->mp_pid;
  sig_map = (sigset_t) mm_in.SIG_MAP;
  mp = &mproc[0];		/* pretend kernel signals are from MM */
  mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */

  /* Check each bit in turn to see if a signal is to be sent.  Unlike
   * kill(), the kernel may collect several unrelated signals for a
   * process and pass them to MM in one blow.  Thus loop on the bit
   * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast
   * to the recipient's process group.  For SIGKILL, use proc_id -1 to
   * indicate a systemwide broadcast.
   */
  for (i = 1; i <= _NSIG; i++) {
	if (!sigismember(&sig_map, i)) continue;
	switch (i) {
	    case SIGINT:
	    case SIGQUIT:
		id = 0; break;	/* broadcast to process group */
	    case SIGKILL:
		id = -1; break;	/* broadcast to all except INIT */
	    case SIGALRM:
		/* Disregard SIGALRM when the target process has not
		 * requested an alarm.  This only applies for a KERNEL
		 * generated signal.
		 */
		if ((rmp->mp_flags & ALARM_ON) == 0) continue;
		rmp->mp_flags &= ~ALARM_ON;
		/* fall through */
	    default:
		id = proc_id;
		break;
	}
	check_sig(id, i);
	sys_endsig(proc_nr);	/* tell kernel it's done */
  }
  return(OK);
}
Exemplo n.º 4
0
/*===========================================================================*
 *			      do_srv_kill				     *
 *===========================================================================*/
int do_srv_kill()
{
/* Perform the srv_kill(pid, signo) system call. */

  /* Only RS is allowed to use srv_kill. */
  if (mp->mp_endpoint != RS_PROC_NR)
	return EPERM;

  /* Pretend the signal comes from the kernel when RS wants to deliver a signal
   * to a system process. RS sends a SIGKILL when it wants to perform cleanup.
   * In that case, ksig == TRUE forces PM to exit the process immediately.
   */
  return check_sig(m_in.pid, m_in.sig_nr, TRUE /* ksig */);
}
Exemplo n.º 5
0
static int __init read_suspend_image(void)
{
	int error = 0;

	if ((error = check_sig()))
		return error;
	if ((error = check_header()))
		return error;
	if ((error = read_pagedir()))
		return error;
	if ((error = data_read()))
		free_pages((unsigned long)pagedir_nosave, pagedir_order);
	return error;
}
/*===========================================================================*
 *				exec_restart				     *
 *===========================================================================*/
void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp,
       vir_bytes ps_str)
{
	int r, sn;

	if (result != OK)
	{
		if (rmp->mp_flags & PARTIAL_EXEC)
		{
			/* Use SIGKILL to signal that something went wrong */
			sys_kill(rmp->mp_endpoint, SIGKILL);
			return;
		}
		reply(rmp-mproc, result);
		return;
	}

	rmp->mp_flags &= ~PARTIAL_EXEC;

	/* 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);
		}
	}

	/* Cause a signal if this process is traced.
	 * Do this before making the process runnable again!
	 */
	if (rmp->mp_tracer != NO_TRACER && !(rmp->mp_trace_flags & TO_NOEXEC))
	{
		sn = (rmp->mp_trace_flags & TO_ALTEXEC) ? SIGSTOP : SIGTRAP;

		check_sig(rmp->mp_pid, sn, FALSE /* ksig */);
	}

	/* Call kernel to exec with SP and PC set by VFS. */
	r = sys_exec(rmp->mp_endpoint, sp, (vir_bytes)rmp->mp_name, pc, ps_str);
	if (r != OK) panic("sys_exec failed: %d", r);
}
Exemplo n.º 7
0
static int __init read_suspend_image(void)
{
	int error = 0;

	if ((error = check_sig()))
		return error;
	if ((error = check_header()))
		return error;
	if ((error = read_pagedir()))
		return error;
	if ((error = relocate_pagedir()))
		goto FreePagedir;
	if ((error = check_pagedir()))
		goto FreePagedir;
	if ((error = read_image_data()))
		goto FreePagedir;
 Done:
	return error;
 FreePagedir:
	free_pages((unsigned long)pm_pagedir_nosave,pagedir_order);
	goto Done;
}
Exemplo n.º 8
0
/*===========================================================================*
 *				do_kill					     *
 *===========================================================================*/
PUBLIC int do_kill()
{
/* Perform the kill(pid, signo) system call. */

  return check_sig(pid, sig_nr);
}
Exemplo n.º 9
0
/*===========================================================================*
 *				do_trace  				     *
 *===========================================================================*/
PUBLIC int do_trace()
{
  register struct mproc *child;
  struct ptrace_range pr;
  int i, r, seg, req;

  req = m_in.request;

  /* The T_OK call is made by the child fork of the debugger before it execs
   * the process to be traced. The T_ATTACH call is made by the debugger itself
   * to attach to an existing process.
   */
  switch (req) {
  case T_OK:		/* enable tracing by parent for this proc */
	if (mp->mp_tracer != NO_TRACER) return(EBUSY);

	mp->mp_tracer = mp->mp_parent;
	mp->mp_reply.reply_trace = 0;
	return(OK);

  case T_ATTACH:	/* attach to an existing process */
	if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH);
	if (child->mp_flags & EXITING) return(ESRCH);

	/* For non-root processes, user and group ID must match. */
	if (mp->mp_effuid != SUPER_USER &&
		(mp->mp_effuid != child->mp_effuid ||
		 mp->mp_effgid != child->mp_effgid ||
		 child->mp_effuid != child->mp_realuid ||
		 child->mp_effgid != child->mp_realgid)) return(EPERM);

	/* Only root may trace system servers. */
	if (mp->mp_effuid != SUPER_USER && (child->mp_flags & PRIV_PROC))
		return(EPERM);

	/* System servers may not trace anyone. They can use sys_trace(). */
	if (mp->mp_flags & PRIV_PROC) return(EPERM);

	/* Can't trace self, PM or VM. */
	if (child == mp || child->mp_endpoint == PM_PROC_NR ||
		child->mp_endpoint == VM_PROC_NR) return(EPERM);

	/* Can't trace a process that is already being traced. */
	if (child->mp_tracer != NO_TRACER) return(EBUSY);

	child->mp_tracer = who_p;
	child->mp_trace_flags = TO_NOEXEC;

	sig_proc(child, SIGSTOP, TRUE /*trace*/, FALSE /* ksig */);

	mp->mp_reply.reply_trace = 0;
	return(OK);

  case T_STOP:		/* stop the process */
	/* This call is not exposed to user programs, because its effect can be
	 * achieved better by sending the traced process a signal with kill(2).
	 */
	return(EINVAL);

  case T_READB_INS:	/* special hack for reading text segments */
	if (mp->mp_effuid != SUPER_USER) return(EPERM);
	if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH);
	if (child->mp_flags & EXITING) return(ESRCH);

	r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data);
	if (r != OK) return(r);

	mp->mp_reply.reply_trace = m_in.data;
	return(OK);

  case T_WRITEB_INS:	/* special hack for patching text segments */
	if (mp->mp_effuid != SUPER_USER) return(EPERM);
	if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH);
	if (child->mp_flags & EXITING) return(ESRCH);

#if 0
	/* Should check for shared text */

	/* Make sure the text segment is not used as a source for shared
	 * text.
	 */
	child->mp_ino = 0;
	child->mp_dev = 0;
	child->mp_ctime = 0;
#endif

	r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data);
	if (r != OK) return(r);

	mp->mp_reply.reply_trace = m_in.data;
	return(OK);
  }

  /* All the other calls are made by the tracing process to control execution
   * of the child. For all these calls, the child must be stopped.
   */
  if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH);
  if (child->mp_flags & EXITING) return(ESRCH);
  if (child->mp_tracer != who_p) return(ESRCH);
  if (!(child->mp_flags & STOPPED)) return(EBUSY);

  switch (req) {
  case T_EXIT:		/* exit */
	child->mp_flags |= TRACE_EXIT;

	/* Defer the exit if the traced process has an VFS call pending. */
	if (child->mp_flags & VFS_CALL)
		child->mp_exitstatus = (int) m_in.data;	/* save for later */
	else
		exit_proc(child, (int) m_in.data, FALSE /*dump_core*/);

	/* Do not reply to the caller until VFS has processed the exit
	 * request.
	 */
	return(SUSPEND);

  case T_SETOPT:	/* set trace options */
	child->mp_trace_flags = m_in.data;

	mp->mp_reply.reply_trace = 0;
	return(OK);

  case T_GETRANGE:
  case T_SETRANGE:	/* get/set range of values */
	r = sys_datacopy(who_e, (vir_bytes) m_in.PMTRACE_ADDR,
			SELF, (vir_bytes) &pr, (phys_bytes) sizeof(pr));
	if (r != OK) return(r);

	if (pr.pr_space != TS_INS && pr.pr_space != TS_DATA) return(EINVAL);
	if (pr.pr_size == 0 || pr.pr_size > LONG_MAX) return(EINVAL);

	seg = (pr.pr_space == TS_INS) ? T : D;
	if (req == T_GETRANGE)
		r = sys_vircopy(child->mp_endpoint, seg, (vir_bytes) pr.pr_addr,
			who_e, D, (vir_bytes) pr.pr_ptr,
			(phys_bytes) pr.pr_size);
	else
		r = sys_vircopy(who_e, D, (vir_bytes) pr.pr_ptr,
			child->mp_endpoint, seg, (vir_bytes) pr.pr_addr,
			(phys_bytes) pr.pr_size);

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

	mp->mp_reply.reply_trace = 0;
	return(OK);

  case T_DETACH:	/* detach from traced process */
	if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL);

	child->mp_tracer = NO_TRACER;

	/* Let all tracer-pending signals through the filter. */
	for (i = 1; i < _NSIG; i++) {
		if (sigismember(&child->mp_sigtrace, i)) {
			(void) sigdelset(&child->mp_sigtrace, i);
			check_sig(child->mp_pid, i, FALSE /* ksig */);
		}
	}

	if (m_in.data > 0) {		/* issue signal */
		sig_proc(child, (int) m_in.data, TRUE /*trace*/, 
			FALSE /* ksig */);
	}

	/* Resume the child as if nothing ever happened. */ 
	child->mp_flags &= ~STOPPED;
	child->mp_trace_flags = 0;

	check_pending(child);

	break;

  case T_RESUME: 
  case T_STEP:
  case T_SYSCALL:	/* resume execution */
	if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL);

	if (m_in.data > 0) {		/* issue signal */
		sig_proc(child, (int) m_in.data, FALSE /*trace*/,
			FALSE /* ksig */);
	}

	/* If there are any other signals waiting to be delivered,
	 * feign a successful resumption.
	 */
	for (i = 1; i < _NSIG; i++) {
		if (sigismember(&child->mp_sigtrace, i)) {
			mp->mp_reply.reply_trace = 0;
			return(OK);
		}
	}

	child->mp_flags &= ~STOPPED;

	check_pending(child);

	break;
  }
  r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data);
  if (r != OK) return(r);

  mp->mp_reply.reply_trace = m_in.data;
  return(OK);
}
Exemplo n.º 10
0
/*===========================================================================*
 *				process_ksig				     *
 *===========================================================================*/
int process_ksig(endpoint_t proc_nr_e, int signo)
{
  register struct mproc *rmp;
  int proc_nr;
  pid_t proc_id, id;

  if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0) {
	printf("PM: process_ksig: %d?? not ok\n", proc_nr_e);
	return EDEADEPT; /* process is gone. */
  }
  rmp = &mproc[proc_nr];
  if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) {
#if 0
	printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e);
#endif
	return EDEADEPT; /* process is gone. */
  }
  proc_id = rmp->mp_pid;
  mp = &mproc[0];			/* pretend signals are from PM */
  mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */

  /* For SIGVTALRM and SIGPROF, see if we need to restart a
   * virtual timer. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0
   * to indicate a broadcast to the recipient's process group.  For
   * SIGKILL, use proc_id -1 to indicate a systemwide broadcast.
   */
  switch (signo) {
      case SIGINT:
      case SIGQUIT:
      case SIGWINCH:
  	id = 0; break;	/* broadcast to process group */
      case SIGVTALRM:
      case SIGPROF:
      	check_vtimer(proc_nr, signo);
      	/* fall-through */
      default:
  	id = proc_id;
  	break;
  }
  check_sig(id, signo, TRUE /* ksig */);

  /* If SIGSNDELAY is set, an earlier sys_stop() failed because the process was
   * still sending, and the kernel hereby tells us that the process is now done
   * with that. We can now try to resume what we planned to do in the first
   * place: set up a signal handler. However, the process's message may have
   * been a call to PM, in which case the process may have changed any of its
   * signal settings. The process may also have forked, exited etcetera.
   */
  if (signo == SIGSNDELAY && (rmp->mp_flags & DELAY_CALL)) {
	rmp->mp_flags &= ~DELAY_CALL;

	/*
	 * If the VFS_CALL flag is still set we have a process which is stopped
	 * and we only need to wait for a reply from VFS. We are going to check
	 * the pending signal then
	 */
	if (rmp->mp_flags & VFS_CALL)
		return OK;
	if (rmp->mp_flags & PM_SIG_PENDING)
		panic("process_ksig: bad process state");

	/* Process as many normal signals as possible. */
	check_pending(rmp);

	if (rmp->mp_flags & DELAY_CALL)
		panic("process_ksig: multiple delay calls?");
  }
  
  /* See if the process is still alive */
  if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE)  {
      return OK; /* signal has been delivered */
  }
  else {
      return EDEADEPT; /* process is gone */
  }
}
Exemplo n.º 11
0
/*===========================================================================*
 *				do_kill					     *
 *===========================================================================*/
int do_kill()
{
/* Perform the kill(pid, signo) system call. */

  return check_sig(m_in.pid, m_in.sig_nr, FALSE /* ksig */);
}
Exemplo n.º 12
0
/*===========================================================================*
 *				process_ksig				     *
 *===========================================================================*/
int process_ksig(endpoint_t proc_nr_e, int signo)
{
  register struct mproc *rmp;
  int proc_nr;
  pid_t proc_id, id;

  if(pm_isokendpt(proc_nr_e, &proc_nr) != OK) {
	printf("PM: process_ksig: %d?? not ok\n", proc_nr_e);
	return EDEADEPT; /* process is gone. */
  }
  rmp = &mproc[proc_nr];
  if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) {
#if 0
	printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e);
#endif
	return EDEADEPT; /* process is gone. */
  }
  proc_id = rmp->mp_pid;
  mp = &mproc[0];			/* pretend signals are from PM */
  mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */

  /* For SIGVTALRM and SIGPROF, see if we need to restart a
   * virtual timer. For SIGINT, SIGINFO, SIGWINCH and SIGQUIT, use proc_id 0
   * to indicate a broadcast to the recipient's process group.  For
   * SIGKILL, use proc_id -1 to indicate a systemwide broadcast.
   */
  switch (signo) {
      case SIGINT:
      case SIGQUIT:
      case SIGWINCH:
      case SIGINFO:
  	id = 0; break;	/* broadcast to process group */
      case SIGVTALRM:
      case SIGPROF:
      	check_vtimer(proc_nr, signo);
      	/* fall-through */
      default:
  	id = proc_id;
  	break;
  }
  check_sig(id, signo, TRUE /* ksig */);

  /* If SIGSNDELAY is set, an earlier sys_stop() failed because the process was
   * still sending, and the kernel hereby tells us that the process is now done
   * with that. We can now try to resume what we planned to do in the first
   * place: set up a signal handler. However, the process's message may have
   * been a call to PM, in which case the process may have changed any of its
   * signal settings. The process may also have forked, exited etcetera.
   */
  if (signo == SIGSNDELAY && (rmp->mp_flags & DELAY_CALL)) {
	/* When getting SIGSNDELAY, the process is stopped at least until the
	 * receipt of the SIGSNDELAY signal is acknowledged to the kernel. The
	 * process is not stopped on PROC_STOP in the kernel. However, now that
	 * there is no longer a delay call, stop_proc() is guaranteed to
	 * succeed immediately.
	 */
	rmp->mp_flags &= ~DELAY_CALL;

	assert(!(rmp->mp_flags & PROC_STOPPED));

	/* If the delay call was to PM, it may have resulted in a VFS call. In
	 * that case, we must wait with further signal processing until VFS has
	 * replied. Stop the process.
	 */
	if (rmp->mp_flags & VFS_CALL) {
		stop_proc(rmp, FALSE /*may_delay*/);

		return OK;
	}

	/* Process as many normal signals as possible. */
	check_pending(rmp);

	assert(!(rmp->mp_flags & DELAY_CALL));
  }
  
  /* See if the process is still alive */
  if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE)  {
      return OK; /* signal has been delivered */
  }
  else {
      return EDEADEPT; /* process is gone */
  }
}
Exemplo n.º 13
0
/*===========================================================================*
 *				do_kill					     *
 *===========================================================================*/
int do_kill(void)
{
/* Perform the kill(pid, signo) system call. */

  return check_sig(m_in.m_lc_pm_sig.pid, m_in.m_lc_pm_sig.nr, FALSE /* ksig */);
}
Exemplo n.º 14
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 */
}
Exemplo n.º 15
0
inline bool check_sig(RDPDrawable & data, char * message, const char * shasig)
{
    return check_sig(data.data(), data.height(), data.rowsize(), message, shasig);
}
Exemplo n.º 16
0
int main(int argc, char *argv[])
{
    char *filename = argc < 2 ? "fat.ima" : argv[1];

    FILE *f = fopen(filename, "r");

    if(f == NULL) {
        errorf("couldn't open file '%s'\n", filename);
        return 1;
    }

    if(!check_sig(f))
        return 1;

    struct BPB_t bpb;
    read_bytes(f, 0x0, &bpb, sizeof(bpb));

    if(bpb.BytsPerSec != 512 || bpb.NumFATs != 2)
        return 1;

    greenf( "FAT addr: 0x%x\n"
            "Root addr: 0x%x\n"
            "Data addr: 0x%x\n",
            BPB_FAT_addr(&bpb),
            BPB_Root_addr(&bpb),
            BPB_Data_addr(&bpb)
          );

    for(int i = 0; i < bpb.RootEntCnt; i++) {
        struct dir_t dir;
        uint32_t offset = BPB_Root_addr(&bpb) + i*32;
        read_bytes(f, offset, &dir, sizeof(dir));

        if(dir.Name[0] == 0) {
            break;
        } else if(dir.Name[0] == 0xE5) {
            printf("<unused space>\n");
            continue;
        }


        purplef("\n%.*s", (int)(sizeof(dir.Name)/sizeof(char)), dir.Name);
        const char *type;

        if(dir.Attr & DIR_ATTR_LFN) {
            purplef("<LONG FILENAME>\n");
        } else if(dir.Attr & DIR_ATTR_DIRECTORY) {
            purplef("<DIRECTORY>\n");
        } else {
            purplef("<FILE>\n");

            //if(i == 0xF)
            //    print_cluster(f, &bpb, &dir);
            //else
                printf("<omitting print>\n");
        }
    }

    fclose(f);

    return 0;
}