Пример #1
0
/*===========================================================================*
 *				service_pm				     *
 *===========================================================================*/
static void service_pm()
{
  int r, slot;

  switch (job_call_nr) {
    case PM_SETUID:
	{
		endpoint_t proc_e;
		uid_t euid, ruid;

		proc_e = job_m_in.PM_PROC;
		euid = job_m_in.PM_EID;
		ruid = job_m_in.PM_RID;

		pm_setuid(proc_e, euid, ruid);

		m_out.m_type = PM_SETUID_REPLY;
		m_out.PM_PROC = proc_e;
	}
	break;

    case PM_SETGID:
	{
		endpoint_t proc_e;
		gid_t egid, rgid;

		proc_e = job_m_in.PM_PROC;
		egid = job_m_in.PM_EID;
		rgid = job_m_in.PM_RID;

		pm_setgid(proc_e, egid, rgid);

		m_out.m_type = PM_SETGID_REPLY;
		m_out.PM_PROC = proc_e;
	}
	break;

    case PM_SETSID:
	{
		endpoint_t proc_e;

		proc_e = job_m_in.PM_PROC;
		pm_setsid(proc_e);

		m_out.m_type = PM_SETSID_REPLY;
		m_out.PM_PROC = proc_e;
	}
	break;

    case PM_EXEC:
    case PM_EXIT:
    case PM_DUMPCORE:
	{
		endpoint_t proc_e = job_m_in.PM_PROC;
		okendpt(proc_e, &slot);
		fp = &fproc[slot];

		if (fp->fp_flags & FP_PENDING) {
			/* This process has a request pending, but PM wants it
			 * gone. Forget about the pending request and satisfy
			 * PM's request instead. Note that a pending request
			 * AND an EXEC request are mutually exclusive. Also, PM
			 * should send only one request/process at a time.
			 */
			 assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR);
		}

		/* PM requests on behalf of a proc are handled after the
		 * system call that might be in progress for that proc has
		 * finished. If the proc is not busy, we start a dummy call.
		 */
		if (!(fp->fp_flags & FP_PENDING) &&
					mutex_trylock(&fp->fp_lock) == 0) {
			mutex_unlock(&fp->fp_lock);
			worker_start(do_dummy);
			fp->fp_flags |= FP_DROP_WORK;
		}

		fp->fp_job.j_m_in = job_m_in;
		fp->fp_flags |= FP_PM_PENDING;

		return;
	}
    case PM_FORK:
    case PM_SRV_FORK:
	{
		endpoint_t pproc_e, proc_e;
		pid_t child_pid;
		uid_t reuid;
		gid_t regid;

		pproc_e = job_m_in.PM_PPROC;
		proc_e = job_m_in.PM_PROC;
		child_pid = job_m_in.PM_CPID;
		reuid = job_m_in.PM_REUID;
		regid = job_m_in.PM_REGID;

		pm_fork(pproc_e, proc_e, child_pid);
		m_out.m_type = PM_FORK_REPLY;

		if (job_call_nr == PM_SRV_FORK) {
			m_out.m_type = PM_SRV_FORK_REPLY;
			pm_setuid(proc_e, reuid, reuid);
			pm_setgid(proc_e, regid, regid);
		}

		m_out.PM_PROC = proc_e;
	}
	break;
    case PM_SETGROUPS:
	{
		endpoint_t proc_e;
		int group_no;
		gid_t *group_addr;

		proc_e = job_m_in.PM_PROC;
		group_no = job_m_in.PM_GROUP_NO;
		group_addr = (gid_t *) job_m_in.PM_GROUP_ADDR;

		pm_setgroups(proc_e, group_no, group_addr);

		m_out.m_type = PM_SETGROUPS_REPLY;
		m_out.PM_PROC = proc_e;
	}
	break;

    case PM_UNPAUSE:
	{
		endpoint_t proc_e;

		proc_e = job_m_in.PM_PROC;

		unpause(proc_e);

		m_out.m_type = PM_UNPAUSE_REPLY;
		m_out.PM_PROC = proc_e;
	}
	break;

    case PM_REBOOT:
	pm_reboot();

	/* Reply dummy status to PM for synchronization */
	m_out.m_type = PM_REBOOT_REPLY;

	break;

    default:
	printf("VFS: don't know how to handle PM request %d\n", job_call_nr);

	return;
  }

  r = send(PM_PROC_NR, &m_out);
  if (r != OK)
	panic("service_pm: send failed: %d", r);

}
Пример #2
0
/*===========================================================================*
 *				service_pm				     *
 *===========================================================================*/
static void service_pm(void)
{
/* Process a request from PM. This function is called from the main thread, and
 * may therefore not block. Any requests that may require blocking the calling
 * thread must be executed in a separate thread. Aside from VFS_PM_REBOOT, all
 * requests from PM involve another, target process: for example, PM tells VFS
 * that a process is performing a setuid() call. For some requests however,
 * that other process may not be idle, and in that case VFS must serialize the
 * PM request handling with any operation is it handling for that target
 * process. As it happens, the requests that may require blocking are also the
 * ones where the target process may not be idle. For both these reasons, such
 * requests are run in worker threads associated to the target process.
 */
  struct fproc *rfp;
  int r, slot;
  message m_out;

  memset(&m_out, 0, sizeof(m_out));

  switch (call_nr) {
  case VFS_PM_SETUID:
	{
		endpoint_t proc_e;
		uid_t euid, ruid;

		proc_e = m_in.VFS_PM_ENDPT;
		euid = m_in.VFS_PM_EID;
		ruid = m_in.VFS_PM_RID;

		pm_setuid(proc_e, euid, ruid);

		m_out.m_type = VFS_PM_SETUID_REPLY;
		m_out.VFS_PM_ENDPT = proc_e;
	}
	break;

  case VFS_PM_SETGID:
	{
		endpoint_t proc_e;
		gid_t egid, rgid;

		proc_e = m_in.VFS_PM_ENDPT;
		egid = m_in.VFS_PM_EID;
		rgid = m_in.VFS_PM_RID;

		pm_setgid(proc_e, egid, rgid);

		m_out.m_type = VFS_PM_SETGID_REPLY;
		m_out.VFS_PM_ENDPT = proc_e;
	}
	break;

  case VFS_PM_SETSID:
	{
		endpoint_t proc_e;

		proc_e = m_in.VFS_PM_ENDPT;
		pm_setsid(proc_e);

		m_out.m_type = VFS_PM_SETSID_REPLY;
		m_out.VFS_PM_ENDPT = proc_e;
	}
	break;

  case VFS_PM_EXEC:
  case VFS_PM_EXIT:
  case VFS_PM_DUMPCORE:
  case VFS_PM_UNPAUSE:
	{
		endpoint_t proc_e = m_in.VFS_PM_ENDPT;

		if(isokendpt(proc_e, &slot) != OK) {
			printf("VFS: proc ep %d not ok\n", proc_e);
			return;
		}

		rfp = &fproc[slot];

		/* PM requests on behalf of a proc are handled after the
		 * system call that might be in progress for that proc has
		 * finished. If the proc is not busy, we start a new thread.
		 */
		worker_start(rfp, NULL, &m_in, FALSE /*use_spare*/);

		return;
	}
  case VFS_PM_FORK:
  case VFS_PM_SRV_FORK:
	{
		endpoint_t pproc_e, proc_e;
		pid_t child_pid;
		uid_t reuid;
		gid_t regid;

		pproc_e = m_in.VFS_PM_PENDPT;
		proc_e = m_in.VFS_PM_ENDPT;
		child_pid = m_in.VFS_PM_CPID;
		reuid = m_in.VFS_PM_REUID;
		regid = m_in.VFS_PM_REGID;

		pm_fork(pproc_e, proc_e, child_pid);
		m_out.m_type = VFS_PM_FORK_REPLY;

		if (call_nr == VFS_PM_SRV_FORK) {
			m_out.m_type = VFS_PM_SRV_FORK_REPLY;
			pm_setuid(proc_e, reuid, reuid);
			pm_setgid(proc_e, regid, regid);
		}

		m_out.VFS_PM_ENDPT = proc_e;
	}
	break;
  case VFS_PM_SETGROUPS:
	{
		endpoint_t proc_e;
		int group_no;
		gid_t *group_addr;

		proc_e = m_in.VFS_PM_ENDPT;
		group_no = m_in.VFS_PM_GROUP_NO;
		group_addr = (gid_t *) m_in.VFS_PM_GROUP_ADDR;

		pm_setgroups(proc_e, group_no, group_addr);

		m_out.m_type = VFS_PM_SETGROUPS_REPLY;
		m_out.VFS_PM_ENDPT = proc_e;
	}
	break;

  case VFS_PM_REBOOT:
	/* Reboot requests are not considered postponed PM work and are instead
	 * handled from a separate worker thread that is associated with PM's
	 * process. PM makes no regular VFS calls, and thus, from VFS's
	 * perspective, PM is always idle. Therefore, we can safely do this.
	 * We do assume that PM sends us only one VFS_PM_REBOOT message at
	 * once, or ever for that matter. :)
	 */
	worker_start(fproc_addr(PM_PROC_NR), pm_reboot, &m_in,
		FALSE /*use_spare*/);

	return;

    default:
	printf("VFS: don't know how to handle PM request %d\n", call_nr);

	return;
  }

  r = ipc_send(PM_PROC_NR, &m_out);
  if (r != OK)
	panic("service_pm: ipc_send failed: %d", r);
}