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