| File: | obj-scan-build/proc/../../proc/info.c |
| Location: | line 612, column 5 |
| Description: | Function call argument is an uninitialized value |
| 1 | /* Process information queries | |||
| 2 | Copyright (C) 1992,93,94,95,96,99,2000,01,02 Free Software Foundation, Inc. | |||
| 3 | ||||
| 4 | This file is part of the GNU Hurd. | |||
| 5 | ||||
| 6 | The GNU Hurd is free software; you can redistribute it and/or modify | |||
| 7 | it under the terms of the GNU General Public License as published by | |||
| 8 | the Free Software Foundation; either version 2, or (at your option) | |||
| 9 | any later version. | |||
| 10 | ||||
| 11 | The GNU Hurd is distributed in the hope that it will be useful, | |||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 14 | GNU General Public License for more details. | |||
| 15 | ||||
| 16 | You should have received a copy of the GNU General Public License | |||
| 17 | along with the GNU Hurd; see the file COPYING. If not, write to | |||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 19 | ||||
| 20 | /* Written by Michael I. Bushnell. */ | |||
| 21 | ||||
| 22 | #include <mach.h> | |||
| 23 | #include <sys/types.h> | |||
| 24 | #include <sys/mman.h> | |||
| 25 | #include <hurd/hurd_types.h> | |||
| 26 | #include <stdlib.h> | |||
| 27 | #include <errno(*__errno_location ()).h> | |||
| 28 | #include <string.h> | |||
| 29 | #include <sys/resource.h> | |||
| 30 | #include <assert.h> | |||
| 31 | #include <hurd/msg.h> | |||
| 32 | ||||
| 33 | #include "proc.h" | |||
| 34 | #include "process_S.h" | |||
| 35 | ||||
| 36 | ||||
| 37 | /* Returns true if PROC1 has `owner' privileges over PROC2 (and can thus get | |||
| 38 | its task port &c). If PROC2 has an owner, then PROC1 must have that uid; | |||
| 39 | otherwise, both must be in the same login collection. */ | |||
| 40 | int | |||
| 41 | check_owner (struct proc *proc1, struct proc *proc2) | |||
| 42 | { | |||
| 43 | return | |||
| 44 | proc2->p_noowner | |||
| 45 | ? check_uid (proc1, 0) || proc1->p_login == proc2->p_login | |||
| 46 | : check_uid (proc1, proc2->p_owner); | |||
| 47 | } | |||
| 48 | ||||
| 49 | ||||
| 50 | /* Implement S_proc_pid2task as described in <hurd/process.defs>. */ | |||
| 51 | kern_return_t | |||
| 52 | S_proc_pid2task (struct proc *callerp, | |||
| 53 | pid_t pid, | |||
| 54 | task_t *t) | |||
| 55 | { | |||
| 56 | struct proc *p; | |||
| 57 | ||||
| 58 | if (!callerp) | |||
| 59 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 60 | ||||
| 61 | p = pid_find_allow_zombie (pid); | |||
| 62 | if (!p) | |||
| 63 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 64 | ||||
| 65 | if (p->p_dead) | |||
| 66 | { | |||
| 67 | *t = MACH_PORT_NULL((mach_port_t) 0); | |||
| 68 | return 0; | |||
| 69 | } | |||
| 70 | ||||
| 71 | if (! check_owner (callerp, p)) | |||
| 72 | return EPERM((0x10 << 26) | ((1) & 0x3fff)); | |||
| 73 | ||||
| 74 | assert (MACH_PORT_VALID (p->p_task))(((((p->p_task) != ((mach_port_t) 0)) && ((p->p_task ) != ((mach_port_t) ~0)))) ? (void) (0) : __assert_fail ("(((p->p_task) != ((mach_port_t) 0)) && ((p->p_task) != ((mach_port_t) ~0)))" , "../../proc/info.c", 74, __PRETTY_FUNCTION__)); | |||
| 75 | *t = p->p_task; | |||
| 76 | ||||
| 77 | return 0; | |||
| 78 | } | |||
| 79 | ||||
| 80 | /* Implement proc_task2pid as described in <hurd/process.defs>. */ | |||
| 81 | kern_return_t | |||
| 82 | S_proc_task2pid (struct proc *callerp, | |||
| 83 | task_t t, | |||
| 84 | pid_t *pid) | |||
| 85 | { | |||
| 86 | struct proc *p = task_find (t); | |||
| 87 | ||||
| 88 | /* No need to check CALLERP here; we don't use it. */ | |||
| 89 | ||||
| 90 | if (!p) | |||
| 91 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 92 | ||||
| 93 | *pid = p->p_pid; | |||
| 94 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), t); | |||
| 95 | return 0; | |||
| 96 | } | |||
| 97 | ||||
| 98 | /* Implement proc_task2proc as described in <hurd/process.defs>. */ | |||
| 99 | kern_return_t | |||
| 100 | S_proc_task2proc (struct proc *callerp, | |||
| 101 | task_t t, | |||
| 102 | mach_port_t *outproc) | |||
| 103 | { | |||
| 104 | struct proc *p = task_find (t); | |||
| 105 | ||||
| 106 | /* No need to check CALLERP here; we don't use it. */ | |||
| 107 | ||||
| 108 | if (!p) | |||
| 109 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 110 | ||||
| 111 | *outproc = ports_get_right (p); | |||
| 112 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), t); | |||
| 113 | return 0; | |||
| 114 | } | |||
| 115 | ||||
| 116 | /* Implement proc_proc2task as described in <hurd/process.defs>. */ | |||
| 117 | kern_return_t | |||
| 118 | S_proc_proc2task (struct proc *p, | |||
| 119 | task_t *t) | |||
| 120 | { | |||
| 121 | if (!p) | |||
| 122 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 123 | *t = p->p_task; | |||
| 124 | return 0; | |||
| 125 | } | |||
| 126 | ||||
| 127 | /* Implement proc_pid2proc as described in <hurd/process.defs>. */ | |||
| 128 | kern_return_t | |||
| 129 | S_proc_pid2proc (struct proc *callerp, | |||
| 130 | pid_t pid, | |||
| 131 | mach_port_t *outproc) | |||
| 132 | { | |||
| 133 | struct proc *p; | |||
| 134 | ||||
| 135 | if (!callerp) | |||
| 136 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 137 | ||||
| 138 | p = pid_find_allow_zombie (pid); | |||
| 139 | if (!p) | |||
| 140 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 141 | ||||
| 142 | if (p->p_dead) | |||
| 143 | { | |||
| 144 | *outproc = MACH_PORT_NULL((mach_port_t) 0); | |||
| 145 | return 0; | |||
| 146 | } | |||
| 147 | ||||
| 148 | if (! check_owner (callerp, p)) | |||
| 149 | return EPERM((0x10 << 26) | ((1) & 0x3fff)); | |||
| 150 | ||||
| 151 | *outproc = ports_get_right (p); | |||
| 152 | return 0; | |||
| 153 | } | |||
| 154 | ||||
| 155 | ||||
| 156 | /* Read a string starting at address ADDR in task T; set *STR to point at | |||
| 157 | newly malloced storage holding it, and *LEN to its length with null. */ | |||
| 158 | static error_t | |||
| 159 | get_string (task_t t, | |||
| 160 | vm_address_t addr, | |||
| 161 | char **str, size_t *len) | |||
| 162 | { | |||
| 163 | /* This version assumes that a string is never more than one | |||
| 164 | page in length. */ | |||
| 165 | ||||
| 166 | vm_address_t readaddr; | |||
| 167 | vm_address_t data; | |||
| 168 | size_t readlen; | |||
| 169 | error_t err; | |||
| 170 | char *c; | |||
| 171 | ||||
| 172 | readaddr = trunc_page (addr)((((vm_offset_t) (addr)) / __vm_page_size) * __vm_page_size); | |||
| 173 | err = vm_read (t, readaddr, vm_page_size * 2, &data, &readlen); | |||
| 174 | if (err == KERN_INVALID_ADDRESS1) | |||
| 175 | err = vm_read (t, readaddr, vm_page_size, &data, &readlen); | |||
| 176 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 177 | err = ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 178 | if (err) | |||
| 179 | return err; | |||
| 180 | ||||
| 181 | /* Scan for a null. */ | |||
| 182 | c = memchr ((char *) (data + (addr - readaddr)), '\0', | |||
| 183 | readlen - (addr - readaddr)); | |||
| 184 | if (c == NULL((void*)0)) | |||
| 185 | err = KERN_INVALID_ADDRESS1; | |||
| 186 | else | |||
| 187 | { | |||
| 188 | c++; /* Include the null. */ | |||
| 189 | *len = c - (char *) (data + (addr - readaddr)); | |||
| 190 | *str = malloc (*len); | |||
| 191 | if (*str == NULL((void*)0)) | |||
| 192 | err = ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 193 | else | |||
| 194 | memcpy (*str, (char *) data + (addr - readaddr), *len); | |||
| 195 | } | |||
| 196 | ||||
| 197 | munmap ((caddr_t) data, readlen); | |||
| 198 | return err; | |||
| 199 | } | |||
| 200 | ||||
| 201 | /* Read a vector of addresses (stored as are argv and envp) from task TASK | |||
| 202 | found at address ADDR. Set *VEC to point to newly malloced storage holding | |||
| 203 | the addresses. */ | |||
| 204 | static error_t | |||
| 205 | get_vector (task_t task, | |||
| 206 | vm_address_t addr, | |||
| 207 | int **vec) | |||
| 208 | { | |||
| 209 | vm_address_t readaddr; | |||
| 210 | vm_size_t readsize; | |||
| 211 | vm_address_t scanned; | |||
| 212 | error_t err; | |||
| 213 | ||||
| 214 | *vec = NULL((void*)0); | |||
| 215 | readaddr = trunc_page (addr)((((vm_offset_t) (addr)) / __vm_page_size) * __vm_page_size); | |||
| 216 | readsize = 0; | |||
| 217 | scanned = addr; | |||
| 218 | do | |||
| 219 | { | |||
| 220 | vm_address_t data; | |||
| 221 | mach_msg_type_number_t readlen = 0; | |||
| 222 | vm_address_t *t; | |||
| 223 | ||||
| 224 | readsize += vm_page_size; | |||
| 225 | err = vm_read (task, readaddr, readsize, &data, &readlen); | |||
| 226 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 227 | err = ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 228 | if (err) | |||
| 229 | return err; | |||
| 230 | ||||
| 231 | /* Scan for a null. */ | |||
| 232 | for (t = (vm_address_t *) (data + (scanned - readaddr)); | |||
| 233 | t < (vm_address_t *) (data + readlen); | |||
| 234 | ++t) | |||
| 235 | if (*t == 0) | |||
| 236 | { | |||
| 237 | ++t; /* Include the null. */ | |||
| 238 | *vec = malloc ((char *)t - (char *)(data + (addr - readaddr))); | |||
| 239 | if (*vec == NULL((void*)0)) | |||
| 240 | err = ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 241 | else | |||
| 242 | memcpy (*vec, (char *)(data + (addr - readaddr)), | |||
| 243 | (char *)t - (char *)(data + (addr - readaddr))); | |||
| 244 | break; | |||
| 245 | } | |||
| 246 | ||||
| 247 | /* If we didn't find the null terminator, then we will loop | |||
| 248 | to read an additional page. */ | |||
| 249 | scanned = readaddr + readlen; | |||
| 250 | munmap ((caddr_t) data, readlen); | |||
| 251 | } while (!err && *vec == NULL((void*)0)); | |||
| 252 | ||||
| 253 | return err; | |||
| 254 | } | |||
| 255 | ||||
| 256 | /* Fetch an array of strings at address LOC in task T into | |||
| 257 | BUF of size BUFLEN. */ | |||
| 258 | static error_t | |||
| 259 | get_string_array (task_t t, | |||
| 260 | vm_address_t loc, | |||
| 261 | vm_address_t *buf, | |||
| 262 | size_t *buflen) | |||
| 263 | { | |||
| 264 | char *bp; | |||
| 265 | int *vector, *vp; | |||
| 266 | error_t err; | |||
| 267 | vm_address_t origbuf = *buf; | |||
| 268 | ||||
| 269 | err = get_vector (t, loc, &vector); | |||
| 270 | if (err) | |||
| 271 | return err; | |||
| 272 | ||||
| 273 | bp = (char *) *buf; | |||
| 274 | for (vp = vector; *vp; ++vp) | |||
| 275 | { | |||
| 276 | char *string; | |||
| 277 | size_t len; | |||
| 278 | ||||
| 279 | err = get_string (t, *vp, &string, &len); | |||
| 280 | if (err) | |||
| 281 | { | |||
| 282 | free (vector); | |||
| 283 | if (*buf != origbuf) | |||
| 284 | munmap ((caddr_t) *buf, *buflen); | |||
| 285 | return err; | |||
| 286 | } | |||
| 287 | ||||
| 288 | if (len > (char *) *buf + *buflen - bp) | |||
| 289 | { | |||
| 290 | char *newbuf; | |||
| 291 | vm_size_t prev_len = bp - (char *) *buf; | |||
| 292 | vm_size_t newsize = *buflen * 2; | |||
| 293 | ||||
| 294 | if (newsize < prev_len + len) | |||
| 295 | /* Since we will mmap whole pages anyway, | |||
| 296 | notice how much space we really have. */ | |||
| 297 | newsize = round_page (prev_len + len)((((vm_offset_t) (prev_len + len) + __vm_page_size - 1) / __vm_page_size ) * __vm_page_size); | |||
| 298 | ||||
| 299 | newbuf = mmap (0, newsize, PROT_READ0x04|PROT_WRITE0x02, MAP_ANON0x0002, 0, 0); | |||
| 300 | if (newbuf == MAP_FAILED((void *) -1)) | |||
| 301 | { | |||
| 302 | err = errno(*__errno_location ()); | |||
| 303 | free (string); | |||
| 304 | free (vector); | |||
| 305 | if (*buf != origbuf) | |||
| 306 | munmap ((caddr_t) *buf, *buflen); | |||
| 307 | return err; | |||
| 308 | } | |||
| 309 | ||||
| 310 | memcpy (newbuf, (char *) *buf, prev_len); | |||
| 311 | bp = newbuf + prev_len; | |||
| 312 | if (*buf != origbuf) | |||
| 313 | munmap ((caddr_t) *buf, *buflen); | |||
| 314 | ||||
| 315 | *buf = (vm_address_t) newbuf; | |||
| 316 | *buflen = newsize; | |||
| 317 | } | |||
| 318 | ||||
| 319 | memcpy (bp, string, len); | |||
| 320 | bp += len; | |||
| 321 | free (string); | |||
| 322 | } | |||
| 323 | ||||
| 324 | free (vector); | |||
| 325 | *buflen = bp - (char *) *buf; | |||
| 326 | return 0; | |||
| 327 | } | |||
| 328 | ||||
| 329 | ||||
| 330 | /* Implement proc_getprocargs as described in <hurd/process.defs>. */ | |||
| 331 | kern_return_t | |||
| 332 | S_proc_getprocargs (struct proc *callerp, | |||
| 333 | pid_t pid, | |||
| 334 | char **buf, | |||
| 335 | size_t *buflen) | |||
| 336 | { | |||
| 337 | struct proc *p = pid_find (pid); | |||
| 338 | ||||
| 339 | /* No need to check CALLERP here; we don't use it. */ | |||
| 340 | ||||
| 341 | if (!p) | |||
| 342 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 343 | ||||
| 344 | return get_string_array (p->p_task, p->p_argv, (vm_address_t *) buf, buflen); | |||
| 345 | } | |||
| 346 | ||||
| 347 | /* Implement proc_getprocenv as described in <hurd/process.defs>. */ | |||
| 348 | kern_return_t | |||
| 349 | S_proc_getprocenv (struct proc *callerp, | |||
| 350 | pid_t pid, | |||
| 351 | char **buf, | |||
| 352 | size_t *buflen) | |||
| 353 | { | |||
| 354 | struct proc *p = pid_find (pid); | |||
| 355 | ||||
| 356 | /* No need to check CALLERP here; we don't use it. */ | |||
| 357 | ||||
| 358 | if (!p) | |||
| 359 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 360 | ||||
| 361 | return get_string_array (p->p_task, p->p_envp, (vm_address_t *)buf, buflen); | |||
| 362 | } | |||
| 363 | ||||
| 364 | /* Handy abbreviation for all the various thread details. */ | |||
| 365 | #define PI_FETCH_THREAD_DETAILS(0x0008 | 0x0004 | 0x0010) \ | |||
| 366 | (PI_FETCH_THREAD_SCHED0x0008 | PI_FETCH_THREAD_BASIC0x0004 | PI_FETCH_THREAD_WAITS0x0010) | |||
| 367 | ||||
| 368 | /* Implement proc_getprocinfo as described in <hurd/process.defs>. */ | |||
| 369 | kern_return_t | |||
| 370 | S_proc_getprocinfo (struct proc *callerp, | |||
| 371 | pid_t pid, | |||
| 372 | int *flags, | |||
| 373 | int **piarray, | |||
| 374 | size_t *piarraylen, | |||
| 375 | char **waits, mach_msg_type_number_t *waits_len) | |||
| 376 | { | |||
| 377 | struct proc *p = pid_find (pid); | |||
| 378 | struct procinfo *pi; | |||
| 379 | size_t nthreads; | |||
| 380 | thread_t *thds; | |||
| ||||
| 381 | error_t err = 0; | |||
| 382 | size_t structsize; | |||
| 383 | int i; | |||
| 384 | int pi_alloced = 0, waits_alloced = 0; | |||
| 385 | /* The amount of WAITS we've filled in so far. */ | |||
| 386 | mach_msg_type_number_t waits_used = 0; | |||
| 387 | size_t tkcount, thcount; | |||
| 388 | struct proc *tp; | |||
| 389 | task_t task; /* P's task port. */ | |||
| 390 | mach_port_t msgport; /* P's msgport, or MACH_PORT_NULL if none. */ | |||
| 391 | ||||
| 392 | /* No need to check CALLERP here; we don't use it. */ | |||
| 393 | ||||
| 394 | if (!p) | |||
| 395 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 396 | ||||
| 397 | task = p->p_task; | |||
| 398 | ||||
| 399 | check_msgport_death (p); | |||
| 400 | msgport = p->p_msgport; | |||
| 401 | ||||
| 402 | if (*flags & PI_FETCH_THREAD_DETAILS(0x0008 | 0x0004 | 0x0010)) | |||
| 403 | *flags |= PI_FETCH_THREADS0x0002; | |||
| 404 | ||||
| 405 | if (*flags & PI_FETCH_THREADS0x0002) | |||
| 406 | { | |||
| 407 | err = task_threads (p->p_task, &thds, &nthreads); | |||
| 408 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 409 | err = ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 410 | if (err) | |||
| 411 | return err; | |||
| 412 | } | |||
| 413 | else | |||
| 414 | nthreads = 0; | |||
| 415 | ||||
| 416 | structsize = sizeof (struct procinfo); | |||
| 417 | if (*flags & PI_FETCH_THREAD_DETAILS(0x0008 | 0x0004 | 0x0010)) | |||
| 418 | structsize += nthreads * sizeof (pi->threadinfos[0]); | |||
| 419 | ||||
| 420 | if (structsize / sizeof (int) > *piarraylen) | |||
| 421 | { | |||
| 422 | *piarray = mmap (0, structsize, PROT_READ0x04|PROT_WRITE0x02, MAP_ANON0x0002, 0, 0); | |||
| 423 | if (*piarray == MAP_FAILED((void *) -1)) | |||
| 424 | { | |||
| 425 | err = errno(*__errno_location ()); | |||
| 426 | if (*flags & PI_FETCH_THREADS0x0002) | |||
| 427 | { | |||
| 428 | for (i = 0; i < nthreads; i++) | |||
| 429 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), thds[i]); | |||
| 430 | munmap (thds, nthreads * sizeof (thread_t)); | |||
| 431 | } | |||
| 432 | return err; | |||
| 433 | } | |||
| 434 | pi_alloced = 1; | |||
| 435 | } | |||
| 436 | *piarraylen = structsize / sizeof (int); | |||
| 437 | pi = (struct procinfo *) *piarray; | |||
| 438 | ||||
| 439 | pi->state = | |||
| 440 | ((p->p_stopped ? PI_STOPPED0x00000001 : 0) | |||
| 441 | | (p->p_exec ? PI_EXECED0x00000002 : 0) | |||
| 442 | | (p->p_waiting ? PI_WAITING0x00000004 : 0) | |||
| 443 | | (!p->p_pgrp->pg_orphcnt ? PI_ORPHAN0x00000008 : 0) | |||
| 444 | | (p->p_msgport == MACH_PORT_NULL((mach_port_t) 0) ? PI_NOMSG0x00000010 : 0) | |||
| 445 | | (p->p_pgrp->pg_session->s_sid == p->p_pid ? PI_SESSLD0x00000020 : 0) | |||
| 446 | | (p->p_noowner ? PI_NOTOWNED0x0000040 : 0) | |||
| 447 | | (!p->p_parentset ? PI_NOPARENT0x0000080 : 0) | |||
| 448 | | (p->p_traced ? PI_TRACED0x00000200 : 0) | |||
| 449 | | (p->p_msgportwait ? PI_GETMSG0x00000400 : 0) | |||
| 450 | | (p->p_loginleader ? PI_LOGINLD0x00000800 : 0)); | |||
| 451 | pi->owner = p->p_owner; | |||
| 452 | pi->ppid = p->p_parent->p_pid; | |||
| 453 | pi->pgrp = p->p_pgrp->pg_pgid; | |||
| 454 | pi->session = p->p_pgrp->pg_session->s_sid; | |||
| 455 | for (tp = p; !tp->p_loginleader; tp = tp->p_parent) | |||
| 456 | assert (tp)((tp) ? (void) (0) : __assert_fail ("tp", "../../proc/info.c" , 456, __PRETTY_FUNCTION__)); | |||
| 457 | pi->logincollection = tp->p_pid; | |||
| 458 | if (p->p_dead || p->p_stopped) | |||
| 459 | { | |||
| 460 | pi->exitstatus = p->p_status; | |||
| 461 | pi->sigcode = p->p_sigcode; | |||
| 462 | } | |||
| 463 | else | |||
| 464 | pi->exitstatus = pi->sigcode = 0; | |||
| 465 | ||||
| 466 | pi->nthreads = nthreads; | |||
| 467 | ||||
| 468 | /* Release GLOBAL_LOCK around time consuming bits, and more importatantly, | |||
| 469 | potential calls to P's msgport, which can block. */ | |||
| 470 | pthread_mutex_unlock (&global_lock); | |||
| 471 | ||||
| 472 | if (*flags & PI_FETCH_TASKINFO0x0001) | |||
| 473 | { | |||
| 474 | tkcount = TASK_BASIC_INFO_COUNT(sizeof(task_basic_info_data_t) / sizeof(natural_t)); | |||
| 475 | err = task_info (task, TASK_BASIC_INFO1, | |||
| 476 | (task_info_t) &pi->taskinfo, &tkcount); | |||
| 477 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 478 | err = ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 479 | #ifdef TASK_SCHED_TIMESHARE_INFO | |||
| 480 | if (!err) | |||
| 481 | { | |||
| 482 | tkcount = TASK_SCHED_TIMESHARE_INFO_COUNT; | |||
| 483 | err = task_info (task, TASK_SCHED_TIMESHARE_INFO, | |||
| 484 | (int *)&pi->timeshare_base_info, &tkcount); | |||
| 485 | if (err == KERN_INVALID_POLICY) | |||
| 486 | { | |||
| 487 | pi->timeshare_base_info.base_priority = -1; | |||
| 488 | err = 0; | |||
| 489 | } | |||
| 490 | } | |||
| 491 | #endif | |||
| 492 | } | |||
| 493 | if (*flags & PI_FETCH_TASKEVENTS0x0020) | |||
| 494 | { | |||
| 495 | tkcount = TASK_EVENTS_INFO_COUNT(sizeof(task_events_info_data_t) / sizeof(natural_t)); | |||
| 496 | err = task_info (task, TASK_EVENTS_INFO2, | |||
| 497 | (task_info_t) &pi->taskevents, &tkcount); | |||
| 498 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 499 | err = ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 500 | if (err) | |||
| 501 | { | |||
| 502 | /* Something screwy, give up on this bit of info. */ | |||
| 503 | *flags &= ~PI_FETCH_TASKEVENTS0x0020; | |||
| 504 | err = 0; | |||
| 505 | } | |||
| 506 | } | |||
| 507 | ||||
| 508 | for (i = 0; i < nthreads; i++) | |||
| 509 | { | |||
| 510 | if (*flags & PI_FETCH_THREAD_DETAILS(0x0008 | 0x0004 | 0x0010)) | |||
| 511 | pi->threadinfos[i].died = 0; | |||
| 512 | if (*flags & PI_FETCH_THREAD_BASIC0x0004) | |||
| 513 | { | |||
| 514 | thcount = THREAD_BASIC_INFO_COUNT(sizeof(thread_basic_info_data_t) / sizeof(natural_t)); | |||
| 515 | err = thread_info (thds[i], THREAD_BASIC_INFO1, | |||
| 516 | (thread_info_t) &pi->threadinfos[i].pis_bi, | |||
| 517 | &thcount); | |||
| 518 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 519 | { | |||
| 520 | pi->threadinfos[i].died = 1; | |||
| 521 | err = 0; | |||
| 522 | continue; | |||
| 523 | } | |||
| 524 | else if (err) | |||
| 525 | /* Something screwy, give up on this bit of info. */ | |||
| 526 | { | |||
| 527 | *flags &= ~PI_FETCH_THREAD_BASIC0x0004; | |||
| 528 | err = 0; | |||
| 529 | } | |||
| 530 | } | |||
| 531 | ||||
| 532 | if (*flags & PI_FETCH_THREAD_SCHED0x0008) | |||
| 533 | { | |||
| 534 | thcount = THREAD_SCHED_INFO_COUNT(sizeof(thread_sched_info_data_t) / sizeof(natural_t)); | |||
| 535 | err = thread_info (thds[i], THREAD_SCHED_INFO2, | |||
| 536 | (thread_info_t) &pi->threadinfos[i].pis_si, | |||
| 537 | &thcount); | |||
| 538 | if (err == MACH_SEND_INVALID_DEST0x10000003) | |||
| 539 | { | |||
| 540 | pi->threadinfos[i].died = 1; | |||
| 541 | err = 0; | |||
| 542 | continue; | |||
| 543 | } | |||
| 544 | if (err) | |||
| 545 | /* Something screwy, give up on this bit of info. */ | |||
| 546 | { | |||
| 547 | *flags &= ~PI_FETCH_THREAD_SCHED0x0008; | |||
| 548 | err = 0; | |||
| 549 | } | |||
| 550 | } | |||
| 551 | ||||
| 552 | /* Note that there are thread wait entries only for those threads | |||
| 553 | not marked dead. */ | |||
| 554 | ||||
| 555 | if (*flags & PI_FETCH_THREAD_WAITS0x0010) | |||
| 556 | { | |||
| 557 | /* See what thread I is waiting on. */ | |||
| 558 | if (msgport == MACH_PORT_NULL((mach_port_t) 0)) | |||
| 559 | *flags &= ~PI_FETCH_THREAD_WAITS0x0010; /* Can't return much... */ | |||
| 560 | else | |||
| 561 | { | |||
| 562 | string_t desc; | |||
| 563 | size_t desc_len; | |||
| 564 | ||||
| 565 | if (msg_report_wait (msgport, thds[i], | |||
| 566 | desc, &pi->threadinfos[i].rpc_block)) | |||
| 567 | desc[0] = '\0'; /* Don't know. */ | |||
| 568 | ||||
| 569 | /* See how long DESC is, being sure not to barf if it's | |||
| 570 | unterminated (string_t's are fixed length). */ | |||
| 571 | desc_len = strnlen (desc, sizeof desc); | |||
| 572 | ||||
| 573 | if (waits_used + desc_len + 1 > *waits_len) | |||
| 574 | /* Not enough room in WAITS, we must allocate more. */ | |||
| 575 | { | |||
| 576 | char *new_waits = 0; | |||
| 577 | mach_msg_type_number_t new_len = | |||
| 578 | round_page (waits_used + desc_len + 1)((((vm_offset_t) (waits_used + desc_len + 1) + __vm_page_size - 1) / __vm_page_size) * __vm_page_size); | |||
| 579 | ||||
| 580 | new_waits = mmap (0, new_len, PROT_READ0x04|PROT_WRITE0x02, | |||
| 581 | MAP_ANON0x0002, 0, 0); | |||
| 582 | err = (new_waits == MAP_FAILED((void *) -1)) ? errno(*__errno_location ()) : 0; | |||
| 583 | if (err) | |||
| 584 | /* Just don't return any more waits information. */ | |||
| 585 | *flags &= ~PI_FETCH_THREAD_WAITS0x0010; | |||
| 586 | else | |||
| 587 | { | |||
| 588 | if (waits_used > 0) | |||
| 589 | memcpy (new_waits, *waits, waits_used); | |||
| 590 | if (*waits_len > 0 && waits_alloced) | |||
| 591 | munmap (*waits, *waits_len); | |||
| 592 | *waits = new_waits; | |||
| 593 | *waits_len = new_len; | |||
| 594 | waits_alloced = 1; | |||
| 595 | } | |||
| 596 | } | |||
| 597 | ||||
| 598 | if (waits_used + desc_len + 1 <= *waits_len) | |||
| 599 | /* Append DESC to WAITS. */ | |||
| 600 | { | |||
| 601 | memcpy (*waits + waits_used, desc, desc_len); | |||
| 602 | waits_used += desc_len; | |||
| 603 | (*waits)[waits_used++] = '\0'; | |||
| 604 | } | |||
| 605 | } | |||
| 606 | } | |||
| 607 | ||||
| 608 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), thds[i]); | |||
| 609 | } | |||
| 610 | ||||
| 611 | if (*flags & PI_FETCH_THREADS0x0002) | |||
| 612 | munmap (thds, nthreads * sizeof (thread_t)); | |||
| ||||
| 613 | if (err && pi_alloced) | |||
| 614 | munmap (*piarray, structsize); | |||
| 615 | if (err && waits_alloced) | |||
| 616 | munmap (*waits, *waits_len); | |||
| 617 | else | |||
| 618 | *waits_len = waits_used; | |||
| 619 | ||||
| 620 | /* Reacquire GLOBAL_LOCK to make the central locking code happy. */ | |||
| 621 | pthread_mutex_lock (&global_lock); | |||
| 622 | ||||
| 623 | return err; | |||
| 624 | } | |||
| 625 | ||||
| 626 | /* Implement proc_make_login_coll as described in <hurd/process.defs>. */ | |||
| 627 | kern_return_t | |||
| 628 | S_proc_make_login_coll (struct proc *p) | |||
| 629 | { | |||
| 630 | if (!p) | |||
| 631 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 632 | p->p_loginleader = 1; | |||
| 633 | return 0; | |||
| 634 | } | |||
| 635 | ||||
| 636 | /* Implement proc_getloginid as described in <hurd/process.defs>. */ | |||
| 637 | kern_return_t | |||
| 638 | S_proc_getloginid (struct proc *callerp, | |||
| 639 | pid_t pid, | |||
| 640 | pid_t *leader) | |||
| 641 | { | |||
| 642 | struct proc *proc = pid_find (pid); | |||
| 643 | struct proc *p; | |||
| 644 | ||||
| 645 | /* No need to check CALLERP here; we don't use it. */ | |||
| 646 | ||||
| 647 | if (!proc) | |||
| 648 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 649 | ||||
| 650 | for (p = proc; !p->p_loginleader; p = p->p_parent) | |||
| 651 | assert (p)((p) ? (void) (0) : __assert_fail ("p", "../../proc/info.c", 651 , __PRETTY_FUNCTION__)); | |||
| 652 | ||||
| 653 | *leader = p->p_pid; | |||
| 654 | return 0; | |||
| 655 | } | |||
| 656 | ||||
| 657 | /* Implement proc_getloginpids as described in <hurd/process.defs>. */ | |||
| 658 | kern_return_t | |||
| 659 | S_proc_getloginpids (struct proc *callerp, | |||
| 660 | pid_t id, | |||
| 661 | pid_t **pids, | |||
| 662 | size_t *npids) | |||
| 663 | { | |||
| 664 | error_t err = 0; | |||
| 665 | struct proc *l = pid_find (id); | |||
| 666 | struct proc *p; | |||
| 667 | struct proc **tail, **new, **parray; | |||
| 668 | int parraysize; | |||
| 669 | int i; | |||
| 670 | ||||
| 671 | /* No need to check CALLERP here; we don't use it. */ | |||
| 672 | ||||
| 673 | if (!l || !l->p_loginleader) | |||
| 674 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 675 | ||||
| 676 | /* Simple breadth first search of the children of L. */ | |||
| 677 | parraysize = 50; | |||
| 678 | parray = malloc (sizeof (struct proc *) * parraysize); | |||
| 679 | if (! parray) | |||
| 680 | return ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 681 | ||||
| 682 | parray[0] = l; | |||
| 683 | for (tail = parray, new = &parray[1]; tail != new; tail++) | |||
| 684 | { | |||
| 685 | for (p = (*tail)->p_ochild; p; p = p->p_sib) | |||
| 686 | if (!p->p_loginleader) | |||
| 687 | { | |||
| 688 | /* Add P to the list at NEW */ | |||
| 689 | if (new - parray > parraysize) | |||
| 690 | { | |||
| 691 | struct proc **newparray; | |||
| 692 | newparray = realloc (parray, ((parraysize *= 2) | |||
| 693 | * sizeof (struct proc *))); | |||
| 694 | if (! newparray) | |||
| 695 | { | |||
| 696 | free (parray); | |||
| 697 | return ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 698 | } | |||
| 699 | ||||
| 700 | tail = newparray + (tail - parray); | |||
| 701 | new = newparray + (new - parray); | |||
| 702 | parray = newparray; | |||
| 703 | } | |||
| 704 | *new++ = p; | |||
| 705 | } | |||
| 706 | } | |||
| 707 | ||||
| 708 | if (*npids < new - parray) | |||
| 709 | { | |||
| 710 | *pids = mmap (0, (new - parray) * sizeof (pid_t), PROT_READ0x04|PROT_WRITE0x02, | |||
| 711 | MAP_ANON0x0002, 0, 0); | |||
| 712 | if (*pids == MAP_FAILED((void *) -1)) | |||
| 713 | err = errno(*__errno_location ()); | |||
| 714 | } | |||
| 715 | ||||
| 716 | if (! err) | |||
| 717 | { | |||
| 718 | *npids = new - parray; | |||
| 719 | for (i = 0; i < *npids; i++) | |||
| 720 | (*pids)[i] = parray[i]->p_pid; | |||
| 721 | } | |||
| 722 | ||||
| 723 | free (parray); | |||
| 724 | return err; | |||
| 725 | } | |||
| 726 | ||||
| 727 | /* Implement proc_setlogin as described in <hurd/process.defs>. */ | |||
| 728 | kern_return_t | |||
| 729 | S_proc_setlogin (struct proc *p, | |||
| 730 | char *login) | |||
| 731 | { | |||
| 732 | struct login *l; | |||
| 733 | ||||
| 734 | if (!p) | |||
| 735 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 736 | ||||
| 737 | if (!check_uid (p, 0)) | |||
| 738 | return EPERM((0x10 << 26) | ((1) & 0x3fff)); | |||
| 739 | ||||
| 740 | l = malloc (sizeof (struct login) + strlen (login) + 1); | |||
| 741 | if (! l) | |||
| 742 | return ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 743 | ||||
| 744 | l->l_refcnt = 1; | |||
| 745 | strcpy (l->l_name, login); | |||
| 746 | if (!--p->p_login->l_refcnt) | |||
| 747 | free (p->p_login); | |||
| 748 | p->p_login = l; | |||
| 749 | return 0; | |||
| 750 | } | |||
| 751 | ||||
| 752 | /* Implement proc_getlogin as described in <hurd/process.defs>. */ | |||
| 753 | kern_return_t | |||
| 754 | S_proc_getlogin (struct proc *p, | |||
| 755 | char *login) | |||
| 756 | { | |||
| 757 | if (!p) | |||
| 758 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 759 | strcpy (login, p->p_login->l_name); | |||
| 760 | return 0; | |||
| 761 | } | |||
| 762 | ||||
| 763 | /* Implement proc_get_tty as described in <hurd/process.defs>. */ | |||
| 764 | kern_return_t | |||
| 765 | S_proc_get_tty (struct proc *p, pid_t pid, | |||
| 766 | mach_port_t *tty, mach_msg_type_name_t *tty_type) | |||
| 767 | { | |||
| 768 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); /* XXX */ | |||
| 769 | } | |||
| 770 | ||||
| 771 | /* Implement proc_getnports as described in <hurd/process.defs>. */ | |||
| 772 | kern_return_t | |||
| 773 | S_proc_getnports (struct proc *callerp, | |||
| 774 | pid_t pid, | |||
| 775 | mach_msg_type_number_t *nports) | |||
| 776 | { | |||
| 777 | struct proc *p = pid_find (pid); | |||
| 778 | mach_port_array_t names; | |||
| 779 | mach_msg_type_number_t ncount; | |||
| 780 | mach_port_type_array_t types; | |||
| 781 | mach_msg_type_number_t tcount; | |||
| 782 | error_t err = 0; | |||
| 783 | ||||
| 784 | /* No need to check CALLERP here; we don't use it. */ | |||
| 785 | ||||
| 786 | if (!p) | |||
| 787 | return ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 788 | ||||
| 789 | err = mach_port_names (p->p_task, &names, &ncount, &types, &tcount); | |||
| 790 | if (err == KERN_INVALID_TASK16) | |||
| 791 | err = ESRCH((0x10 << 26) | ((3) & 0x3fff)); | |||
| 792 | ||||
| 793 | if (!err) { | |||
| 794 | *nports = ncount; | |||
| 795 | ||||
| 796 | munmap (names, ncount * sizeof (mach_port_t)); | |||
| 797 | munmap (types, tcount * sizeof (mach_port_type_t)); | |||
| 798 | } | |||
| 799 | ||||
| 800 | return err; | |||
| 801 | } |