Exemple #1
0
/*===========================================================================*
 *				do_newexec				     *
 *===========================================================================*/
int do_newexec(void)
{
	int proc_e, proc_n, allow_setuid;
	vir_bytes ptr;
	struct mproc *rmp;
	struct exec_info args;
	int r;

	if (who_e != VFS_PROC_NR && who_e != RS_PROC_NR)
		return EPERM;

	proc_e= m_in.m_lexec_pm_exec_new.endpt;
	if (pm_isokendpt(proc_e, &proc_n) != OK) {
		panic("do_newexec: got bad endpoint: %d", proc_e);
	}
	rmp= &mproc[proc_n];
	ptr= m_in.m_lexec_pm_exec_new.ptr;
	r= sys_datacopy(who_e, ptr, SELF, (vir_bytes)&args, sizeof(args));
	if (r != OK)
		panic("do_newexec: sys_datacopy failed: %d", r);

	allow_setuid = 0;	/* Do not allow setuid execution */
	rmp->mp_flags &= ~TAINTED;	/* By default not tainted */

	if (rmp->mp_tracer == NO_TRACER) {
		/* Okay, setuid execution is allowed */
		allow_setuid = 1;
	}

	if (allow_setuid && args.allow_setuid) {
		rmp->mp_effuid = args.new_uid;
		rmp->mp_effgid = args.new_gid;
	}

	/* A process is considered 'tainted' when it's executing with
	 * setuid or setgid bit set, or when the real{u,g}id doesn't
	 * match the eff{u,g}id, respectively. */
	if (allow_setuid && args.allow_setuid) {
		/* Program has setuid and/or setgid bits set */
		rmp->mp_flags |= TAINTED;
	} else if (rmp->mp_effuid != rmp->mp_realuid ||
		   rmp->mp_effgid != rmp->mp_realgid) {
		rmp->mp_flags |= TAINTED;
	}

	/* System will save command line for debugging, ps(1) output, etc. */
	strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1);
	rmp->mp_name[PROC_NAME_LEN-1] = '\0';

	/* Save offset to initial argc (for procfs) */
	rmp->mp_frame_addr = (vir_bytes) args.stack_high - args.frame_len;
	rmp->mp_frame_len = args.frame_len;

	/* Kill process if something goes wrong after this point. */
	rmp->mp_flags |= PARTIAL_EXEC;

	mp->mp_reply.m_pm_lexec_exec_new.suid = (allow_setuid && args.allow_setuid);

	return r;
}
Exemple #2
0
/*===========================================================================*
 *				do_adddma				     *
 *===========================================================================*/
PUBLIC int do_adddma()
{
	endpoint_t req_proc_e, target_proc_e;
	int proc_n, r;
	phys_bytes base, size;

	if (mp->mp_effuid != SUPER_USER)
		return EPERM;

	req_proc_e= m_in.m_source;
	target_proc_e= m_in.m2_i1;
	base= m_in.m2_l1;
	size= m_in.m2_l2;

	if((r = vm_adddma(req_proc_e, target_proc_e, base, size)) != OK) {
		printf("pm:do_adddma: vm_adddma failed (%d)\n", r);
		return r;
	}

	/* Find target process */
	if (pm_isokendpt(target_proc_e, &proc_n) != OK)
	{
		printf("pm:do_adddma: endpoint %d not found\n", target_proc_e);
		return EINVAL;
	}

	return OK;
}
Exemple #3
0
/*===========================================================================*
 *				do_exec_newmem				     *
 *===========================================================================*/
PUBLIC int do_exec_newmem()
{
	int proc_e, proc_n, allow_setuid;
	char *ptr;
	struct mproc *rmp;
	struct exec_newmem args;
	int r, flags;
	char *stack_top;

	if (who_e != VFS_PROC_NR && who_e != RS_PROC_NR)
		return EPERM;

	proc_e= m_in.EXC_NM_PROC;
	if (pm_isokendpt(proc_e, &proc_n) != OK) {
		panic("do_exec_newmem: got bad endpoint: %d", proc_e);
	}
	rmp= &mproc[proc_n];
	ptr= m_in.EXC_NM_PTR;
	r= sys_datacopy(who_e, (vir_bytes)ptr,
		SELF, (vir_bytes)&args, sizeof(args));
	if (r != OK)
		panic("do_exec_newmem: sys_datacopy failed: %d", r);

	if((r=vm_exec_newmem(proc_e, &args, sizeof(args), &stack_top, &flags)) == OK) {
		allow_setuid= 0;                /* Do not allow setuid execution */  

		if (rmp->mp_tracer == NO_TRACER) {
			/* Okay, setuid execution is allowed */
			allow_setuid= 1;
			rmp->mp_effuid = args.new_uid;
			rmp->mp_effgid = args.new_gid;
		}

		/* System will save command line for debugging, ps(1) output, etc. */
		strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1);
		rmp->mp_name[PROC_NAME_LEN-1] = '\0';

		/* Save offset to initial argc (for procfs) */
		rmp->mp_frame_addr = (vir_bytes) stack_top - args.args_bytes;
		rmp->mp_frame_len = args.args_bytes;

		/* Kill process if something goes wrong after this point. */
		rmp->mp_flags |= PARTIAL_EXEC;

		mp->mp_reply.reply_res2= (vir_bytes) stack_top;
		mp->mp_reply.reply_res3= flags;
		if (allow_setuid)
			mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
	} else {
		printf("PM: newmem failed for %s\n", args.progname);
	}
	return r;
}
Exemple #4
0
/*===========================================================================*
 *				do_getepinfo			             *
 *===========================================================================*/
int do_getepinfo(void)
{
    struct mproc *rmp;
    endpoint_t ep;
    int slot;

    ep = m_in.m_lsys_pm_getepinfo.endpt;
    if (pm_isokendpt(ep, &slot) != OK)
        return(ESRCH);

    rmp = &mproc[slot];
    mp->mp_reply.m_pm_lsys_getepinfo.uid = rmp->mp_effuid;
    mp->mp_reply.m_pm_lsys_getepinfo.gid = rmp->mp_effgid;
    return(rmp->mp_pid);
}
Exemple #5
0
/*===========================================================================*
 *				get_work				     *
 *===========================================================================*/
PRIVATE void get_work()
{
/* Wait for the next message and extract useful information from it. */
  if (receive(ANY, &m_in) != OK)
	panic(__FILE__,"PM receive error", NO_NUM);
  who_e = m_in.m_source;	/* who sent the message */
  if(pm_isokendpt(who_e, &who_p) != OK)
	panic(__FILE__, "PM got message from invalid endpoint", who_e);
  call_nr = m_in.m_type;	/* system call number */

  /* Process slot of caller. Misuse PM's own process slot if the kernel is
   * calling. This can happen in case of synchronous alarms (CLOCK) or or 
   * event like pending kernel signals (SYSTEM).
   */
  mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p];
  if(who_p >= 0 && mp->mp_endpoint != who_e) {
	panic(__FILE__, "PM endpoint number out of sync with source",
		mp->mp_endpoint);
  }
}
Exemple #6
0
/*===========================================================================*
 *				do_execrestart				     *
 *===========================================================================*/
PUBLIC int do_execrestart()
{
	int proc_e, proc_n, result;
	struct mproc *rmp;
	vir_bytes pc;

	if (who_e != RS_PROC_NR)
		return EPERM;

	proc_e= m_in.EXC_RS_PROC;
	if (pm_isokendpt(proc_e, &proc_n) != OK) {
		panic("do_execrestart: got bad endpoint: %d", proc_e);
	}
	rmp= &mproc[proc_n];
	result= m_in.EXC_RS_RESULT;
	pc= (vir_bytes)m_in.EXC_RS_PC;

	exec_restart(rmp, result, pc);

	return OK;
}
/*===========================================================================*
 *				do_execrestart				     *
 *===========================================================================*/
int do_execrestart(void)
{
	int proc_e, proc_n, result;
	struct mproc *rmp;
	vir_bytes pc, ps_str;

	if (who_e != RS_PROC_NR)
		return EPERM;

	proc_e = m_in.m_rs_pm_exec_restart.endpt;
	if (pm_isokendpt(proc_e, &proc_n) != OK) {
		panic("do_execrestart: got bad endpoint: %d", proc_e);
	}
	rmp = &mproc[proc_n];
	result = m_in.m_rs_pm_exec_restart.result;
	pc = m_in.m_rs_pm_exec_restart.pc;
	ps_str = m_in.m_rs_pm_exec_restart.ps_str;

	exec_restart(rmp, result, pc, rmp->mp_frame_addr, ps_str);

	return OK;
}
Exemple #8
0
/*===========================================================================*
 *				do_execrestart				     *
 *===========================================================================*/
int do_execrestart()
{
	int proc_e, proc_n, result;
	struct mproc *rmp;

	if (who_e != RS_PROC_NR)
		return -EPERM;

	proc_e= m_in.EXC_RS_PROC;

	if (pm_isokendpt(proc_e, &proc_n) != 0) {
		panic(__FILE__, "do_execrestart: got bad endpoint",
			proc_e);
	}

	rmp= &mproc[proc_n];
	result= m_in.EXC_RS_RESULT;

	exec_restart(rmp, result);

	return 0;
}
Exemple #9
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 */
  }
}
/*===========================================================================*
 *				main					     *
 *===========================================================================*/
int main()
{
/* Main routine of the process manager. */
  int result;

  /* SEF local startup. */
  sef_local_startup();
  
  
// Initialization of the semarray (of pointers) to NULL
  
  register struct mproc *rmp;
  
// rmp is the pointer to the struct of the process table

    	 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
    	 
    	 {
    				 for(int i=0; i<12; i++) // for all 12 semaphores
    				  {
    					  rmp->semarray[i]=NULL;
    				  }
    				  
    	  }

  // end of Initialization
  

/* This is PM's main loop-  get work and do it, forever and forever. */
  
while (TRUE) {
	  int ipc_status;

	  /* Wait for the next message and extract useful information from it. */
	  if (sef_receive_status(ANY, &m_in, &ipc_status) != OK)
		  panic("PM sef_receive_status error");
	  who_e = m_in.m_source;	/* who sent the message */
	  if(pm_isokendpt(who_e, &who_p) != OK)
		  panic("PM got message from invalid endpoint: %d", who_e);
	  call_nr = m_in.m_type;	/* system call number */

	  /* Process slot of caller. Misuse PM's own process slot if the kernel is
	   * calling. This can happen in case of synchronous alarms (CLOCK) or or
	   * event like pending kernel signals (SYSTEM).
	   */
	  mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p];
	  if(who_p >= 0 && mp->mp_endpoint != who_e) {
		  panic("PM endpoint number out of sync with source: %d",
				  			mp->mp_endpoint);
	  }

	/* Drop delayed calls from exiting processes. */
	if (mp->mp_flags & EXITING)
		continue;

	/* Check for system notifications first. Special cases. */
	if (is_ipc_notify(ipc_status)) {
		if (who_p == CLOCK) {
			expire_timers(m_in.NOTIFY_TIMESTAMP);
		}

		/* done, send reply and continue */
		sendreply();
		continue;
	}

	switch(call_nr)
	{
	case PM_SETUID_REPLY:
	case PM_SETGID_REPLY:
	case PM_SETSID_REPLY:
	case PM_EXEC_REPLY:
	case PM_EXIT_REPLY:
	case PM_CORE_REPLY:
	case PM_FORK_REPLY:
	case PM_SRV_FORK_REPLY:
	case PM_UNPAUSE_REPLY:
	case PM_REBOOT_REPLY:
	case PM_SETGROUPS_REPLY:
		if (who_e == VFS_PROC_NR)
		{
			handle_vfs_reply();
			result= SUSPEND;		/* don't reply */
		}
		else
			result= ENOSYS;
		break;
	case COMMON_GETSYSINFO:
		result = do_getsysinfo();
		break;
	default:
		/* Else, if the system call number is valid, perform the
		 * call.
		 */
		if ((unsigned) call_nr >= NCALLS) {
			result = ENOSYS;
		} else {
#if ENABLE_SYSCALL_STATS
			calls_stats[call_nr]++;
#endif

			result = (*call_vec[call_nr])();

		}
		break;
	}

	/* Send reply. */
	if (result != SUSPEND) setreply(who_p, result);
	sendreply();
  }
  return(OK);
}
Exemple #11
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 */
  }
}
Exemple #12
0
/*===========================================================================*
 *				main					     *
 *===========================================================================*/
int main()
{
/* Main routine of the process manager. */
  unsigned int call_index;
  int ipc_status, result;

  /* SEF local startup. */
  sef_local_startup();

  /* This is PM's main loop-  get work and do it, forever and forever. */
  while (TRUE) {
	/* Wait for the next message. */
	if (sef_receive_status(ANY, &m_in, &ipc_status) != OK)
		panic("PM sef_receive_status error");

	/* Check for system notifications first. Special cases. */
	if (is_ipc_notify(ipc_status)) {
		if (_ENDPOINT_P(m_in.m_source) == CLOCK)
			expire_timers(m_in.m_notify.timestamp);

		/* done, continue */
		continue;
	}

	/* Extract useful information from the message. */
	who_e = m_in.m_source;	/* who sent the message */
	if (pm_isokendpt(who_e, &who_p) != OK)
		panic("PM got message from invalid endpoint: %d", who_e);
	mp = &mproc[who_p];	/* process slot of caller */
	call_nr = m_in.m_type;	/* system call number */

	/* Drop delayed calls from exiting processes. */
	if (mp->mp_flags & EXITING)
		continue;

	if (IS_VFS_PM_RS(call_nr) && who_e == VFS_PROC_NR) {
		handle_vfs_reply();

		result = SUSPEND;		/* don't reply */
	} else if (call_nr == PROC_EVENT_REPLY) {
		result = do_proc_event_reply();
	} else if (IS_PM_CALL(call_nr)) {
		/* If the system call number is valid, perform the call. */
		call_index = (unsigned int) (call_nr - PM_BASE);

		if (call_index < NR_PM_CALLS && call_vec[call_index] != NULL) {
#if ENABLE_SYSCALL_STATS
			calls_stats[call_index]++;
#endif

			result = (*call_vec[call_index])();
		} else
			result = ENOSYS;
	} else
		result = ENOSYS;

	/* Send reply. */
	if (result != SUSPEND) reply(who_p, result);
  }
  return(OK);
}
/*===========================================================================*
 *				do_getset				     *
 *===========================================================================*/
PUBLIC int do_getset()
{
/* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID.  The four
 * GETs and SETSID return their primary results in 'r'.  GETUID, GETGID, and
 * GETPID also return secondary results (the effective IDs, or the parent
 * process ID) in 'reply_res2', which is returned to the user.
 */

  register struct mproc *rmp = mp;
  int r, proc;

  switch(call_nr) {
	case GETUID:
		r = rmp->mp_realuid;
		rmp->mp_reply.reply_res2 = rmp->mp_effuid;
		break;

	case GETGID:
		r = rmp->mp_realgid;
		rmp->mp_reply.reply_res2 = rmp->mp_effgid;
		break;

	case GETPID:
		r = mproc[who_p].mp_pid;
		rmp->mp_reply.reply_res2 = mproc[rmp->mp_parent].mp_pid;
		if(pm_isokendpt(m_in.endpt, &proc) == OK && proc >= 0)
			rmp->mp_reply.reply_res3 = mproc[proc].mp_pid;
		break;

	case SETEUID:
	case SETUID:
		if (rmp->mp_realuid != (uid_t) m_in.usr_id && 
				rmp->mp_effuid != SUPER_USER)
			return(EPERM);
		if(call_nr == SETUID) rmp->mp_realuid = (uid_t) m_in.usr_id;
		rmp->mp_effuid = (uid_t) m_in.usr_id;
		tell_fs(SETUID, who_e, rmp->mp_realuid, rmp->mp_effuid);
		r = OK;
		break;

	case SETEGID:
	case SETGID:
		if (rmp->mp_realgid != (gid_t) m_in.grp_id && 
				rmp->mp_effuid != SUPER_USER)
			return(EPERM);
		if(call_nr == SETGID) rmp->mp_realgid = (gid_t) m_in.grp_id;
		rmp->mp_effgid = (gid_t) m_in.grp_id;
		tell_fs(SETGID, who_e, rmp->mp_realgid, rmp->mp_effgid);
		r = OK;
		break;

	case SETSID:
		if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
		rmp->mp_procgrp = rmp->mp_pid;
		tell_fs(SETSID, who_e, 0, 0);
		/* fall through */

	case GETPGRP:
		r = rmp->mp_procgrp;
		break;

	default:
		r = EINVAL;
		break;	
  }
  return(r);
}
Exemple #14
0
/*
 * A subscribing service has replied to a process event message from us, or at
 * least that is what should have happened.  First make sure of this, and then
 * resume event handling for the affected process.
 */
int
do_proc_event_reply(void)
{
	struct mproc *rmp;
	endpoint_t endpt;
	unsigned int i, event;
	int slot;

	assert(nested == 0);

	/*
	 * Is this an accidental call from a misguided user process?
	 * Politely tell it to go away.
	 */
	if (!(mp->mp_flags & PRIV_PROC))
		return ENOSYS;

	/*
	 * Ensure that we got the reply that we want.  Since this code is
	 * relatively new, produce lots of warnings for cases that should never
	 * or rarely occur.  Later we can just ignore all mismatching replies.
	 */
	endpt = m_in.m_pm_lsys_proc_event.endpt;
	if (pm_isokendpt(endpt, &slot) != OK) {
		printf("PM: proc event reply from %d for invalid endpt %d\n",
		    who_e, endpt);
		return SUSPEND;
	}
	rmp = &mproc[slot];
	if (!(rmp->mp_flags & EVENT_CALL)) {
		printf("PM: proc event reply from %d for endpt %d, no event\n",
		    who_e, endpt);
		return SUSPEND;
	}
	if (rmp->mp_eventsub == NO_EVENTSUB ||
	    (unsigned int)rmp->mp_eventsub >= nsubs) {
		printf("PM: proc event reply from %d for endpt %d index %d\n",
		    who_e, endpt, rmp->mp_eventsub);
		return SUSPEND;
	}
	i = rmp->mp_eventsub;
	if (subs[i].endpt != who_e) {
		printf("PM: proc event reply for %d from %d instead of %d\n",
		    endpt, who_e, subs[i].endpt);
		return SUSPEND;
	}

	if (rmp->mp_flags & EXITING)
		event = PROC_EVENT_EXIT;
	else if (rmp->mp_flags & UNPAUSED)
		event = PROC_EVENT_SIGNAL;
	else {
		printf("PM: proc event reply from %d for %d, bad flags %x\n",
		    who_e, endpt, rmp->mp_flags);
		return SUSPEND;
	}
	if (m_in.m_pm_lsys_proc_event.event != event) {
		printf("PM: proc event reply from %d for %d for event %d "
		    "instead of %d\n", who_e, endpt,
		    m_in.m_pm_lsys_proc_event.event, event);
		return SUSPEND;
	}
	/*
	 * Do NOT check the event against the subscriber's event mask, since a
	 * service may have unsubscribed from an event while it has yet to
	 * process some leftover notifications for that event.  We could decide
	 * not to wait for the replies to those leftover notifications upon
	 * unsubscription, but that could result in problems upon quick
	 * resubscription, and such cases may in fact happen in practice.
	 */

	assert(subs[i].waiting > 0);
	subs[i].waiting--;

	/*
	 * If we are now no longer waiting for any replies from an already
	 * unsubscribed (but alive) service, remove it from the set now; this
	 * will also resume events for the current process.  In the normal case
	 * however, let the current process move on to the next subscriber if
	 * there are more, and the actual event otherwise.
	 */
	if (subs[i].mask == 0 && subs[i].waiting == 0) {
		remove_sub(i);
	} else {
		rmp->mp_eventsub++;

		resume_event(rmp);
	}

	/* In any case, do not reply to this reply message. */
	return SUSPEND;
}
Exemple #15
0
/*===========================================================================*
 *				main					     *
 *===========================================================================*/
PUBLIC int main()
{
/* Main routine of the process manager. */
  int result;

  /* SEF local startup. */
  sef_local_startup();
  sched_init();	/* initialize user-space scheduling */

  /* This is PM's main loop-  get work and do it, forever and forever. */
  while (TRUE) {
	  int ipc_status;

	  /* Wait for the next message and extract useful information from it. */
	  if (sef_receive_status(ANY, &m_in, &ipc_status) != OK)
		  panic("PM sef_receive_status error");
	  who_e = m_in.m_source;	/* who sent the message */
	  if(pm_isokendpt(who_e, &who_p) != OK)
		  panic("PM got message from invalid endpoint: %d", who_e);
	  call_nr = m_in.m_type;	/* system call number */

	  /* Process slot of caller. Misuse PM's own process slot if the kernel is
	   * calling. This can happen in case of synchronous alarms (CLOCK) or or
	   * event like pending kernel signals (SYSTEM).
	   */
	  mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p];
	  if(who_p >= 0 && mp->mp_endpoint != who_e) {
		  panic("PM endpoint number out of sync with source: %d",
				  			mp->mp_endpoint);
	  }

	/* Drop delayed calls from exiting processes. */
	if (mp->mp_flags & EXITING)
		continue;

	/* Check for system notifications first. Special cases. */
	if (is_ipc_notify(ipc_status)) {
		switch(who_p) {
			case CLOCK:
				pm_expire_timers(m_in.NOTIFY_TIMESTAMP);
				result = SUSPEND;	/* don't reply */
				break;
			default :
				result = ENOSYS;
		}

		/* done, send reply and continue */
		if (result != SUSPEND) setreply(who_p, result);
		sendreply();
		continue;
	}

	switch(call_nr)
	{
	case PM_SETUID_REPLY:
	case PM_SETGID_REPLY:
	case PM_SETSID_REPLY:
	case PM_EXEC_REPLY:
	case PM_EXIT_REPLY:
	case PM_CORE_REPLY:
	case PM_FORK_REPLY:
	case PM_SRV_FORK_REPLY:
	case PM_UNPAUSE_REPLY:
	case PM_REBOOT_REPLY:
	case PM_SETGROUPS_REPLY:
		/*?????????????????????????????????????????????????????????????????????*/
		/*?????????????????????????????????????????????????????????????????????*/
		/* Chamando a funcao terminator() para todos os processos finalizados. */
		if ( call_nr==PM_EXIT_REPLY ) terminator( _ENDPOINT_P(m_in.m1_i1));
		/*?????????????????????????????????????????????????????????????????????*/
		/*?????????????????????????????????????????????????????????????????????*/

		if (who_e == FS_PROC_NR)
		{
			handle_fs_reply();
			result= SUSPEND;		/* don't reply */
		}
		else
			result= ENOSYS;
		break;
	default:
		/* Else, if the system call number is valid, perform the
		 * call.
		 */
		if ((unsigned) call_nr >= NCALLS) {
			result = ENOSYS;
		} else {
#if ENABLE_SYSCALL_STATS
			calls_stats[call_nr]++;
#endif

			result = (*call_vec[call_nr])();

		}
		break;
	}

	/* Send reply. */
	if (result != SUSPEND) setreply(who_p, result);
	sendreply();
  }
  return(OK);
}
Exemple #16
0
/*===========================================================================*
 *				do_getset				     *
 *===========================================================================*/
PUBLIC int do_getset()
{
/* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID.  The four
 * GETs and SETSID return their primary results in 'r'.  GETUID, GETGID, and
 * GETPID also return secondary results (the effective IDs, or the parent
 * process ID) in 'reply_res2', which is returned to the user.
 */

  register struct mproc *rmp = mp;
  int r, proc;

  switch(call_nr) {
	case GETUID:
		r = rmp->mp_realuid;
		rmp->mp_reply.reply_res2 = rmp->mp_effuid;
		break;

	case GETGID:
		r = rmp->mp_realgid;
		rmp->mp_reply.reply_res2 = rmp->mp_effgid;
		break;

	case GETPID:
		r = mproc[who_p].mp_pid;
		rmp->mp_reply.reply_res2 = mproc[rmp->mp_parent].mp_pid;
		if(pm_isokendpt(m_in.endpt, &proc) == OK && proc >= 0)
			rmp->mp_reply.reply_res3 = mproc[proc].mp_pid;
		break;

	case SETEUID:
	case SETUID:
		if (rmp->mp_realuid != (uid_t) m_in.usr_id && 
				rmp->mp_effuid != SUPER_USER)
			return(EPERM);
		if(call_nr == SETUID) rmp->mp_realuid = (uid_t) m_in.usr_id;
		rmp->mp_effuid = (uid_t) m_in.usr_id;

		if (rmp->mp_fs_call != PM_IDLE)
		{
			panic(__FILE__, "do_getset: not idle",
				rmp->mp_fs_call);
		}
		rmp->mp_fs_call= PM_SETUID;
		r= notify(FS_PROC_NR);
		if (r != OK)
			panic(__FILE__, "do_getset: unable to notify FS", r);
		
		/* Do not reply until FS is ready to process the setuid
		 * request
		 */
		r= SUSPEND;
		break;

	case SETEGID:
	case SETGID:
		if (rmp->mp_realgid != (gid_t) m_in.grp_id && 
				rmp->mp_effuid != SUPER_USER)
			return(EPERM);
		if(call_nr == SETGID) rmp->mp_realgid = (gid_t) m_in.grp_id;
		rmp->mp_effgid = (gid_t) m_in.grp_id;

		if (rmp->mp_fs_call != PM_IDLE)
		{
			panic(__FILE__, "do_getset: not idle",
				rmp->mp_fs_call);
		}
		rmp->mp_fs_call= PM_SETGID;
		r= notify(FS_PROC_NR);
		if (r != OK)
			panic(__FILE__, "do_getset: unable to notify FS", r);

		/* Do not reply until FS is ready to process the setgid
		 * request
		 */
		r= SUSPEND;
		break;

	case SETSID:
		if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
		rmp->mp_procgrp = rmp->mp_pid;

		if (rmp->mp_fs_call != PM_IDLE)
		{
			panic(__FILE__, "do_getset: not idle",
				rmp->mp_fs_call);
		}
		rmp->mp_fs_call= PM_SETSID;
		r= notify(FS_PROC_NR);
		if (r != OK)
			panic(__FILE__, "do_getset: unable to notify FS", r);

		/* Do not reply until FS is ready to process the setsid
		 * request
		 */
		r= SUSPEND;
		break;

	case GETPGRP:
		r = rmp->mp_procgrp;
		break;

	default:
		r = EINVAL;
		break;	
  }
  return(r);
}