aboutsummaryrefslogtreecommitdiff
path: root/proc/info.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc/info.c')
-rw-r--r--proc/info.c285
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;
+}