diff options
Diffstat (limited to 'proc/info.c')
-rw-r--r-- | proc/info.c | 285 |
1 files changed, 198 insertions, 87 deletions
diff --git a/proc/info.c b/proc/info.c index c44bde6a..f35ad166 100644 --- a/proc/info.c +++ b/proc/info.c @@ -1,5 +1,5 @@ /* Process information queries - Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation + Copyright (C) 1992,93,94,95,96,99,2000,01,02 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -21,6 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <mach.h> #include <sys/types.h> +#include <sys/mman.h> #include <hurd/hurd_types.h> #include <stdlib.h> #include <errno.h> @@ -32,17 +33,32 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "proc.h" #include "process_S.h" -/* Implement S_proc_pid2task as described in <hurd/proc.defs>. */ + +/* Returns true if PROC1 has `owner' privileges over PROC2 (and can thus get + its task port &c). If PROC2 has an owner, then PROC1 must have that uid; + otherwise, both must be in the same login collection. */ +static inline int +check_owner (struct proc *proc1, struct proc *proc2) +{ + return + proc2->p_noowner + ? check_uid (proc1, 0) || proc1->p_login == proc2->p_login + : check_uid (proc1, proc2->p_owner); +} + + +/* Implement S_proc_pid2task as described in <hurd/process.defs>. */ kern_return_t S_proc_pid2task (struct proc *callerp, - pid_t pid, - task_t *t) + pid_t pid, + task_t *t) { - struct proc *p = pid_find_allow_zombie (pid); + struct proc *p; if (!callerp) return EOPNOTSUPP; + p = pid_find_allow_zombie (pid); if (!p) return ESRCH; @@ -55,16 +71,17 @@ S_proc_pid2task (struct proc *callerp, if (! check_owner (callerp, p)) return EPERM; + assert (MACH_PORT_VALID (p->p_task)); *t = p->p_task; return 0; } -/* Implement proc_task2pid as described in <hurd/proc.defs>. */ +/* Implement proc_task2pid as described in <hurd/process.defs>. */ kern_return_t S_proc_task2pid (struct proc *callerp, - task_t t, - pid_t *pid) + task_t t, + pid_t *pid) { struct proc *p = task_find (t); @@ -78,11 +95,11 @@ S_proc_task2pid (struct proc *callerp, return 0; } -/* Implement proc_task2proc as described in <hurd/proc.defs>. */ +/* Implement proc_task2proc as described in <hurd/process.defs>. */ kern_return_t S_proc_task2proc (struct proc *callerp, - task_t t, - mach_port_t *outproc) + task_t t, + mach_port_t *outproc) { struct proc *p = task_find (t); @@ -96,10 +113,10 @@ S_proc_task2proc (struct proc *callerp, return 0; } -/* Implement proc_proc2task as described in <hurd/proc.defs>. */ +/* Implement proc_proc2task as described in <hurd/process.defs>. */ kern_return_t S_proc_proc2task (struct proc *p, - task_t *t) + task_t *t) { if (!p) return EOPNOTSUPP; @@ -107,17 +124,18 @@ S_proc_proc2task (struct proc *p, return 0; } -/* Implement proc_pid2proc as described in <hurd/proc.defs>. */ +/* Implement proc_pid2proc as described in <hurd/process.defs>. */ kern_return_t S_proc_pid2proc (struct proc *callerp, - pid_t pid, - mach_port_t *outproc) + pid_t pid, + mach_port_t *outproc) { - struct proc *p = pid_find_allow_zombie (pid); + struct proc *p; if (!callerp) return EOPNOTSUPP; + p = pid_find_allow_zombie (pid); if (!p) return ESRCH; @@ -136,18 +154,18 @@ S_proc_pid2proc (struct proc *callerp, /* Read a string starting at address ADDR in task T; set *STR to point at - newly malloced storage holding it. */ + newly malloced storage holding it, and *LEN to its length with null. */ static error_t get_string (task_t t, vm_address_t addr, - char **str) + char **str, size_t *len) { /* This version assumes that a string is never more than one page in length. */ vm_address_t readaddr; vm_address_t data; - u_int readlen; + size_t readlen; error_t err; char *c; @@ -168,15 +186,15 @@ get_string (task_t t, else { c++; /* Include the null. */ - *str = malloc (c - (char *)(data + (addr - readaddr))); + *len = c - (char *) (data + (addr - readaddr)); + *str = malloc (*len); if (*str == NULL) err = ENOMEM; else - bcopy ((char *)(data + (addr - readaddr)), *str, - c - (char *)(data + (addr - readaddr))); + memcpy (*str, (char *) data + (addr - readaddr), *len); } - vm_deallocate (mach_task_self (), data, readlen); + munmap ((caddr_t) data, readlen); return err; } @@ -210,8 +228,6 @@ get_vector (task_t task, if (err) return err; - /* XXX fault bad here */ - /* Scan for a null. */ for (t = (vm_address_t *) (data + (scanned - readaddr)); t < (vm_address_t *) (data + readlen); @@ -223,15 +239,15 @@ get_vector (task_t task, if (*vec == NULL) err = ENOMEM; else - bcopy ((char *)(data + (addr - readaddr)), *vec, + memcpy (*vec, (char *)(data + (addr - readaddr)), (char *)t - (char *)(data + (addr - readaddr))); break; } /* If we didn't find the null terminator, then we will loop to read an additional page. */ - scanned = data + readlen; - vm_deallocate (mach_task_self (), data, readlen); + scanned = readaddr + readlen; + munmap ((caddr_t) data, readlen); } while (!err && *vec == NULL); return err; @@ -243,7 +259,7 @@ static error_t get_string_array (task_t t, vm_address_t loc, vm_address_t *buf, - u_int *buflen) + size_t *buflen) { char *bp; int *vector, *vp; @@ -258,62 +274,65 @@ get_string_array (task_t t, for (vp = vector; *vp; ++vp) { char *string; - int len; + size_t len; - err = get_string (t, *vp, &string); + err = get_string (t, *vp, &string, &len); if (err) { free (vector); if (*buf != origbuf) - vm_deallocate (mach_task_self (), *buf, *buflen); + munmap ((caddr_t) *buf, *buflen); return err; } - len = strlen (string) + 1; - if (len > *(char **)buf + *buflen - bp) + if (len > (char *) *buf + *buflen - bp) { - vm_address_t newbuf; - vm_size_t prev_len = bp - *(char **)buf; + char *newbuf; + vm_size_t prev_len = bp - (char *) *buf; vm_size_t newsize = *buflen * 2; if (newsize < prev_len + len) - newsize = prev_len + len; + /* Since we will mmap whole pages anyway, + notice how much space we really have. */ + newsize = round_page (prev_len + len); - err = vm_allocate (mach_task_self (), &newbuf, newsize, 1); - if (err) + newbuf = mmap (0, newsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (newbuf == MAP_FAILED) { + err = errno; free (string); free (vector); if (*buf != origbuf) - vm_deallocate (mach_task_self (), *buf, *buflen); + munmap ((caddr_t) *buf, *buflen); return err; } - bcopy (*(char **) buf, (char *) newbuf, prev_len); - bp = (char *)newbuf + prev_len; + memcpy (newbuf, (char *) *buf, prev_len); + bp = newbuf + prev_len; if (*buf != origbuf) - vm_deallocate (mach_task_self (), *buf, *buflen); + munmap ((caddr_t) *buf, *buflen); - *buf = newbuf; + *buf = (vm_address_t) newbuf; *buflen = newsize; } - bcopy (string, bp, len); + memcpy (bp, string, len); bp += len; free (string); } + free (vector); *buflen = bp - (char *) *buf; return 0; } -/* Implement proc_getprocargs as described in <hurd/proc.defs>. */ +/* Implement proc_getprocargs as described in <hurd/process.defs>. */ kern_return_t S_proc_getprocargs (struct proc *callerp, pid_t pid, char **buf, - u_int *buflen) + size_t *buflen) { struct proc *p = pid_find (pid); @@ -325,12 +344,12 @@ S_proc_getprocargs (struct proc *callerp, return get_string_array (p->p_task, p->p_argv, (vm_address_t *) buf, buflen); } -/* Implement proc_getprocenv as described in <hurd/proc.defs>. */ +/* Implement proc_getprocenv as described in <hurd/process.defs>. */ kern_return_t S_proc_getprocenv (struct proc *callerp, pid_t pid, char **buf, - u_int *buflen) + size_t *buflen) { struct proc *p = pid_find (pid); @@ -346,18 +365,18 @@ S_proc_getprocenv (struct proc *callerp, #define PI_FETCH_THREAD_DETAILS \ (PI_FETCH_THREAD_SCHED | PI_FETCH_THREAD_BASIC | PI_FETCH_THREAD_WAITS) -/* Implement proc_getprocinfo as described in <hurd/proc.defs>. */ +/* Implement proc_getprocinfo as described in <hurd/process.defs>. */ kern_return_t S_proc_getprocinfo (struct proc *callerp, pid_t pid, int *flags, int **piarray, - u_int *piarraylen, + size_t *piarraylen, char **waits, mach_msg_type_number_t *waits_len) { struct proc *p = pid_find (pid); struct procinfo *pi; - int nthreads; + size_t nthreads; thread_t *thds; error_t err = 0; size_t structsize; @@ -365,7 +384,7 @@ S_proc_getprocinfo (struct proc *callerp, int pi_alloced = 0, waits_alloced = 0; /* The amount of WAITS we've filled in so far. */ mach_msg_type_number_t waits_used = 0; - u_int tkcount, thcount; + size_t tkcount, thcount; struct proc *tp; task_t task; /* P's task port. */ mach_port_t msgport; /* P's msgport, or MACH_PORT_NULL if none. */ @@ -376,7 +395,9 @@ S_proc_getprocinfo (struct proc *callerp, return ESRCH; task = p->p_task; - msgport = p->p_deadmsg ? MACH_PORT_NULL : p->p_msgport; + + check_msgport_death (p); + msgport = p->p_msgport; if (*flags & PI_FETCH_THREAD_DETAILS) *flags |= PI_FETCH_THREADS; @@ -398,7 +419,18 @@ S_proc_getprocinfo (struct proc *callerp, if (structsize / sizeof (int) > *piarraylen) { - vm_allocate (mach_task_self (), (vm_address_t *)piarray, structsize, 1); + *piarray = mmap (0, structsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (*piarray == MAP_FAILED) + { + err = errno; + if (*flags & PI_FETCH_THREADS) + { + for (i = 0; i < nthreads; i++) + mach_port_deallocate (mach_task_self (), thds[i]); + munmap (thds, nthreads * sizeof (thread_t)); + } + return err; + } pi_alloced = 1; } *piarraylen = structsize / sizeof (int); @@ -424,7 +456,7 @@ S_proc_getprocinfo (struct proc *callerp, assert (tp); pi->logincollection = tp->p_pid; if (p->p_dead || p->p_stopped) - { + { pi->exitstatus = p->p_status; pi->sigcode = p->p_sigcode; } @@ -440,9 +472,37 @@ S_proc_getprocinfo (struct proc *callerp, if (*flags & PI_FETCH_TASKINFO) { tkcount = TASK_BASIC_INFO_COUNT; - err = task_info (task, TASK_BASIC_INFO, (int *)&pi->taskinfo, &tkcount); + err = task_info (task, TASK_BASIC_INFO, + (task_info_t) &pi->taskinfo, &tkcount); if (err == MACH_SEND_INVALID_DEST) err = ESRCH; +#ifdef TASK_SCHED_TIMESHARE_INFO + if (!err) + { + tkcount = TASK_SCHED_TIMESHARE_INFO_COUNT; + err = task_info (task, TASK_SCHED_TIMESHARE_INFO, + (int *)&pi->timeshare_base_info, &tkcount); + if (err == KERN_INVALID_POLICY) + { + pi->timeshare_base_info.base_priority = -1; + err = 0; + } + } +#endif + } + if (*flags & PI_FETCH_TASKEVENTS) + { + tkcount = TASK_EVENTS_INFO_COUNT; + err = task_info (task, TASK_EVENTS_INFO, + (task_info_t) &pi->taskevents, &tkcount); + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + if (err) + { + /* Something screwy, give up on this bit of info. */ + *flags &= ~PI_FETCH_TASKEVENTS; + err = 0; + } } for (i = 0; i < nthreads; i++) @@ -453,7 +513,7 @@ S_proc_getprocinfo (struct proc *callerp, { thcount = THREAD_BASIC_INFO_COUNT; err = thread_info (thds[i], THREAD_BASIC_INFO, - (int *)&pi->threadinfos[i].pis_bi, + (thread_info_t) &pi->threadinfos[i].pis_bi, &thcount); if (err == MACH_SEND_INVALID_DEST) { @@ -473,7 +533,7 @@ S_proc_getprocinfo (struct proc *callerp, { thcount = THREAD_SCHED_INFO_COUNT; err = thread_info (thds[i], THREAD_SCHED_INFO, - (int *)&pi->threadinfos[i].pis_si, + (thread_info_t) &pi->threadinfos[i].pis_si, &thcount); if (err == MACH_SEND_INVALID_DEST) { @@ -482,15 +542,15 @@ S_proc_getprocinfo (struct proc *callerp, continue; } if (err) - /* Something screwy, give up o nthis bit of info. */ + /* Something screwy, give up on this bit of info. */ { *flags &= ~PI_FETCH_THREAD_SCHED; err = 0; } } - /* Note that there are thread wait entries only for threads not marked - dead. */ + /* Note that there are thread wait entries only for those threads + not marked dead. */ if (*flags & PI_FETCH_THREAD_WAITS) { @@ -517,18 +577,18 @@ S_proc_getprocinfo (struct proc *callerp, mach_msg_type_number_t new_len = round_page (waits_used + desc_len + 1); - err = vm_allocate (mach_task_self (), - (vm_address_t *)&new_waits, new_len,1); + new_waits = mmap (0, new_len, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + err = (new_waits == MAP_FAILED) ? errno : 0; if (err) /* Just don't return any more waits information. */ *flags &= ~PI_FETCH_THREAD_WAITS; else { if (waits_used > 0) - bcopy (*waits, new_waits, waits_used); + memcpy (new_waits, *waits, waits_used); if (*waits_len > 0 && waits_alloced) - vm_deallocate (mach_task_self (), - (vm_address_t)*waits, *waits_len); + munmap (*waits, *waits_len); *waits = new_waits; *waits_len = new_len; waits_alloced = 1; @@ -538,7 +598,7 @@ S_proc_getprocinfo (struct proc *callerp, if (waits_used + desc_len + 1 <= *waits_len) /* Append DESC to WAITS. */ { - bcopy (desc, *waits + waits_used, desc_len); + memcpy (*waits + waits_used, desc, desc_len); waits_used += desc_len; (*waits)[waits_used++] = '\0'; } @@ -549,14 +609,11 @@ S_proc_getprocinfo (struct proc *callerp, } if (*flags & PI_FETCH_THREADS) - { - vm_deallocate (mach_task_self (), - (vm_address_t)thds, nthreads * sizeof (thread_t)); - } + munmap (thds, nthreads * sizeof (thread_t)); if (err && pi_alloced) - vm_deallocate (mach_task_self (), (u_int) *piarray, structsize); + munmap (*piarray, structsize); if (err && waits_alloced) - vm_deallocate (mach_task_self (), (vm_address_t)*waits, *waits_len); + munmap (*waits, *waits_len); else *waits_len = waits_used; @@ -602,8 +659,9 @@ kern_return_t S_proc_getloginpids (struct proc *callerp, pid_t id, pid_t **pids, - u_int *npids) + size_t *npids) { + error_t err = 0; struct proc *l = pid_find (id); struct proc *p; struct proc **tail, **new, **parray; @@ -618,6 +676,9 @@ S_proc_getloginpids (struct proc *callerp, /* Simple breadth first search of the children of L. */ parraysize = 50; parray = malloc (sizeof (struct proc *) * parraysize); + if (! parray) + return ENOMEM; + parray[0] = l; for (tail = parray, new = &parray[1]; tail != new; tail++) { @@ -630,6 +691,12 @@ S_proc_getloginpids (struct proc *callerp, struct proc **newparray; newparray = realloc (parray, ((parraysize *= 2) * sizeof (struct proc *))); + if (! newparray) + { + free (parray); + return ENOMEM; + } + tail = newparray + (tail - parray); new = newparray + (new - parray); parray = newparray; @@ -639,19 +706,28 @@ S_proc_getloginpids (struct proc *callerp, } if (*npids < new - parray) - vm_allocate (mach_task_self (), (vm_address_t *) pids, - (new - parray) * sizeof (pid_t), 1); - *npids = new - parray; - for (i = 0; i < *npids; i++) - (*pids)[i] = parray[i]->p_pid; + { + *pids = mmap (0, (new - parray) * sizeof (pid_t), PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + if (*pids == MAP_FAILED) + err = errno; + } + + if (! err) + { + *npids = new - parray; + for (i = 0; i < *npids; i++) + (*pids)[i] = parray[i]->p_pid; + } + free (parray); - return 0; + return err; } -/* Implement proc_setlogin as described in <hurd/proc.defs>. */ +/* Implement proc_setlogin as described in <hurd/process.defs>. */ kern_return_t S_proc_setlogin (struct proc *p, - char *login) + char *login) { struct login *l; @@ -662,6 +738,9 @@ S_proc_setlogin (struct proc *p, return EPERM; l = malloc (sizeof (struct login) + strlen (login) + 1); + if (! l) + return ENOMEM; + l->l_refcnt = 1; strcpy (l->l_name, login); if (!--p->p_login->l_refcnt) @@ -670,10 +749,10 @@ S_proc_setlogin (struct proc *p, return 0; } -/* Implement proc_getlogin as described in <hurd/proc.defs>. */ +/* Implement proc_getlogin as described in <hurd/process.defs>. */ kern_return_t S_proc_getlogin (struct proc *p, - char *login) + char *login) { if (!p) return EOPNOTSUPP; @@ -681,10 +760,42 @@ S_proc_getlogin (struct proc *p, return 0; } -/* Implement proc_get_tty as described in <hurd/proc.defs>. */ +/* Implement proc_get_tty as described in <hurd/process.defs>. */ kern_return_t S_proc_get_tty (struct proc *p, pid_t pid, mach_port_t *tty, mach_msg_type_name_t *tty_type) { return EOPNOTSUPP; /* XXX */ } + +/* Implement proc_getnports as described in <hurd/process.defs>. */ +kern_return_t +S_proc_getnports (struct proc *callerp, + pid_t pid, + mach_msg_type_number_t *nports) +{ + struct proc *p = pid_find (pid); + mach_port_array_t names; + mach_msg_type_number_t ncount; + mach_port_type_array_t types; + mach_msg_type_number_t tcount; + error_t err = 0; + + /* No need to check CALLERP here; we don't use it. */ + + if (!p) + return ESRCH; + + err = mach_port_names (p->p_task, &names, &ncount, &types, &tcount); + if (err == KERN_INVALID_TASK) + err = ESRCH; + + if (!err) { + *nports = ncount; + + munmap (names, ncount * sizeof (mach_port_t)); + munmap (types, tcount * sizeof (mach_port_type_t)); + } + + return err; +} |