1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 2017 Dell EMC 5 * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org> 6 * Copyright (c) 1988, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include <sys/param.h> 42 #include <sys/elf.h> 43 #include <sys/time.h> 44 #include <sys/resourcevar.h> 45 #define _WANT_UCRED 46 #include <sys/ucred.h> 47 #undef _WANT_UCRED 48 #include <sys/proc.h> 49 #include <sys/user.h> 50 #include <sys/stat.h> 51 #include <sys/vnode.h> 52 #include <sys/socket.h> 53 #define _WANT_SOCKET 54 #include <sys/socketvar.h> 55 #include <sys/domain.h> 56 #include <sys/protosw.h> 57 #include <sys/un.h> 58 #define _WANT_UNPCB 59 #include <sys/unpcb.h> 60 #include <sys/sysctl.h> 61 #include <sys/tty.h> 62 #include <sys/filedesc.h> 63 #include <sys/queue.h> 64 #define _WANT_FILE 65 #include <sys/file.h> 66 #include <sys/conf.h> 67 #include <sys/ksem.h> 68 #include <sys/mman.h> 69 #include <sys/capsicum.h> 70 #include <sys/ptrace.h> 71 #define _WANT_MOUNT 72 #include <sys/mount.h> 73 #include <sys/filedesc.h> 74 #include <sys/pipe.h> 75 #include <fs/devfs/devfs.h> 76 #include <fs/devfs/devfs_int.h> 77 #include <nfs/nfsproto.h> 78 #include <nfsclient/nfs.h> 79 #include <nfsclient/nfsnode.h> 80 81 #include <vm/vm.h> 82 #include <vm/vm_map.h> 83 #include <vm/vm_object.h> 84 85 #include <net/route.h> 86 #include <netinet/in.h> 87 #include <netinet/in_systm.h> 88 #include <netinet/ip.h> 89 #define _WANT_INPCB 90 #include <netinet/in_pcb.h> 91 92 #include <assert.h> 93 #include <ctype.h> 94 #include <err.h> 95 #include <fcntl.h> 96 #include <kvm.h> 97 #include <libutil.h> 98 #include <limits.h> 99 #include <paths.h> 100 #include <pwd.h> 101 #include <stdio.h> 102 #include <stdlib.h> 103 #include <stddef.h> 104 #include <string.h> 105 #include <unistd.h> 106 #include <netdb.h> 107 108 #include <libprocstat.h> 109 #include "libprocstat_internal.h" 110 #include "common_kvm.h" 111 #include "core.h" 112 113 int statfs(const char *, struct statfs *); /* XXX */ 114 115 #define PROCSTAT_KVM 1 116 #define PROCSTAT_SYSCTL 2 117 #define PROCSTAT_CORE 3 118 119 static char **getargv(struct procstat *procstat, struct kinfo_proc *kp, 120 size_t nchr, int env); 121 static char *getmnton(kvm_t *kd, struct mount *m); 122 static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core, 123 int *cntp); 124 static Elf_Auxinfo *procstat_getauxv_core(struct procstat_core *core, 125 unsigned int *cntp); 126 static Elf_Auxinfo *procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp); 127 static struct filestat_list *procstat_getfiles_kvm( 128 struct procstat *procstat, struct kinfo_proc *kp, int mmapped); 129 static struct filestat_list *procstat_getfiles_sysctl( 130 struct procstat *procstat, struct kinfo_proc *kp, int mmapped); 131 static int procstat_get_pipe_info_sysctl(struct filestat *fst, 132 struct pipestat *pipe, char *errbuf); 133 static int procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, 134 struct pipestat *pipe, char *errbuf); 135 static int procstat_get_pts_info_sysctl(struct filestat *fst, 136 struct ptsstat *pts, char *errbuf); 137 static int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, 138 struct ptsstat *pts, char *errbuf); 139 static int procstat_get_sem_info_sysctl(struct filestat *fst, 140 struct semstat *sem, char *errbuf); 141 static int procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst, 142 struct semstat *sem, char *errbuf); 143 static int procstat_get_shm_info_sysctl(struct filestat *fst, 144 struct shmstat *shm, char *errbuf); 145 static int procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst, 146 struct shmstat *shm, char *errbuf); 147 static int procstat_get_socket_info_sysctl(struct filestat *fst, 148 struct sockstat *sock, char *errbuf); 149 static int procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, 150 struct sockstat *sock, char *errbuf); 151 static int to_filestat_flags(int flags); 152 static int procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, 153 struct vnstat *vn, char *errbuf); 154 static int procstat_get_vnode_info_sysctl(struct filestat *fst, 155 struct vnstat *vn, char *errbuf); 156 static gid_t *procstat_getgroups_core(struct procstat_core *core, 157 unsigned int *count); 158 static gid_t * procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, 159 unsigned int *count); 160 static gid_t *procstat_getgroups_sysctl(pid_t pid, unsigned int *count); 161 static struct kinfo_kstack *procstat_getkstack_sysctl(pid_t pid, 162 int *cntp); 163 static int procstat_getosrel_core(struct procstat_core *core, 164 int *osrelp); 165 static int procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, 166 int *osrelp); 167 static int procstat_getosrel_sysctl(pid_t pid, int *osrelp); 168 static int procstat_getpathname_core(struct procstat_core *core, 169 char *pathname, size_t maxlen); 170 static int procstat_getpathname_sysctl(pid_t pid, char *pathname, 171 size_t maxlen); 172 static int procstat_getrlimit_core(struct procstat_core *core, int which, 173 struct rlimit* rlimit); 174 static int procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, 175 int which, struct rlimit* rlimit); 176 static int procstat_getrlimit_sysctl(pid_t pid, int which, 177 struct rlimit* rlimit); 178 static int procstat_getumask_core(struct procstat_core *core, 179 unsigned short *maskp); 180 static int procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, 181 unsigned short *maskp); 182 static int procstat_getumask_sysctl(pid_t pid, unsigned short *maskp); 183 static int vntype2psfsttype(int type); 184 185 void 186 procstat_close(struct procstat *procstat) 187 { 188 189 assert(procstat); 190 if (procstat->type == PROCSTAT_KVM) 191 kvm_close(procstat->kd); 192 else if (procstat->type == PROCSTAT_CORE) 193 procstat_core_close(procstat->core); 194 procstat_freeargv(procstat); 195 procstat_freeenvv(procstat); 196 free(procstat); 197 } 198 199 struct procstat * 200 procstat_open_sysctl(void) 201 { 202 struct procstat *procstat; 203 204 procstat = calloc(1, sizeof(*procstat)); 205 if (procstat == NULL) { 206 warn("malloc()"); 207 return (NULL); 208 } 209 procstat->type = PROCSTAT_SYSCTL; 210 return (procstat); 211 } 212 213 struct procstat * 214 procstat_open_kvm(const char *nlistf, const char *memf) 215 { 216 struct procstat *procstat; 217 kvm_t *kd; 218 char buf[_POSIX2_LINE_MAX]; 219 220 procstat = calloc(1, sizeof(*procstat)); 221 if (procstat == NULL) { 222 warn("malloc()"); 223 return (NULL); 224 } 225 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 226 if (kd == NULL) { 227 warnx("kvm_openfiles(): %s", buf); 228 free(procstat); 229 return (NULL); 230 } 231 procstat->type = PROCSTAT_KVM; 232 procstat->kd = kd; 233 return (procstat); 234 } 235 236 struct procstat * 237 procstat_open_core(const char *filename) 238 { 239 struct procstat *procstat; 240 struct procstat_core *core; 241 242 procstat = calloc(1, sizeof(*procstat)); 243 if (procstat == NULL) { 244 warn("malloc()"); 245 return (NULL); 246 } 247 core = procstat_core_open(filename); 248 if (core == NULL) { 249 free(procstat); 250 return (NULL); 251 } 252 procstat->type = PROCSTAT_CORE; 253 procstat->core = core; 254 return (procstat); 255 } 256 257 struct kinfo_proc * 258 procstat_getprocs(struct procstat *procstat, int what, int arg, 259 unsigned int *count) 260 { 261 struct kinfo_proc *p0, *p; 262 size_t len, olen; 263 int name[4]; 264 int cnt; 265 int error; 266 267 assert(procstat); 268 assert(count); 269 p = NULL; 270 if (procstat->type == PROCSTAT_KVM) { 271 *count = 0; 272 p0 = kvm_getprocs(procstat->kd, what, arg, &cnt); 273 if (p0 == NULL || cnt <= 0) 274 return (NULL); 275 *count = cnt; 276 len = *count * sizeof(*p); 277 p = malloc(len); 278 if (p == NULL) { 279 warnx("malloc(%zu)", len); 280 goto fail; 281 } 282 bcopy(p0, p, len); 283 return (p); 284 } else if (procstat->type == PROCSTAT_SYSCTL) { 285 len = 0; 286 name[0] = CTL_KERN; 287 name[1] = KERN_PROC; 288 name[2] = what; 289 name[3] = arg; 290 error = sysctl(name, nitems(name), NULL, &len, NULL, 0); 291 if (error < 0 && errno != EPERM) { 292 warn("sysctl(kern.proc)"); 293 goto fail; 294 } 295 if (len == 0) { 296 warnx("no processes?"); 297 goto fail; 298 } 299 do { 300 len += len / 10; 301 p = reallocf(p, len); 302 if (p == NULL) { 303 warnx("reallocf(%zu)", len); 304 goto fail; 305 } 306 olen = len; 307 error = sysctl(name, nitems(name), p, &len, NULL, 0); 308 } while (error < 0 && errno == ENOMEM && olen == len); 309 if (error < 0 && errno != EPERM) { 310 warn("sysctl(kern.proc)"); 311 goto fail; 312 } 313 /* Perform simple consistency checks. */ 314 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) { 315 warnx("kinfo_proc structure size mismatch (len = %zu)", len); 316 goto fail; 317 } 318 *count = len / sizeof(*p); 319 return (p); 320 } else if (procstat->type == PROCSTAT_CORE) { 321 p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL, 322 &len); 323 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) { 324 warnx("kinfo_proc structure size mismatch"); 325 goto fail; 326 } 327 *count = len / sizeof(*p); 328 return (p); 329 } else { 330 warnx("unknown access method: %d", procstat->type); 331 return (NULL); 332 } 333 fail: 334 if (p) 335 free(p); 336 return (NULL); 337 } 338 339 void 340 procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p) 341 { 342 343 if (p != NULL) 344 free(p); 345 p = NULL; 346 } 347 348 struct filestat_list * 349 procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 350 { 351 352 switch(procstat->type) { 353 case PROCSTAT_KVM: 354 return (procstat_getfiles_kvm(procstat, kp, mmapped)); 355 case PROCSTAT_SYSCTL: 356 case PROCSTAT_CORE: 357 return (procstat_getfiles_sysctl(procstat, kp, mmapped)); 358 default: 359 warnx("unknown access method: %d", procstat->type); 360 return (NULL); 361 } 362 } 363 364 void 365 procstat_freefiles(struct procstat *procstat, struct filestat_list *head) 366 { 367 struct filestat *fst, *tmp; 368 369 STAILQ_FOREACH_SAFE(fst, head, next, tmp) { 370 if (fst->fs_path != NULL) 371 free(fst->fs_path); 372 free(fst); 373 } 374 free(head); 375 if (procstat->vmentries != NULL) { 376 free(procstat->vmentries); 377 procstat->vmentries = NULL; 378 } 379 if (procstat->files != NULL) { 380 free(procstat->files); 381 procstat->files = NULL; 382 } 383 } 384 385 static struct filestat * 386 filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags, 387 int refcount, off_t offset, char *path, cap_rights_t *cap_rightsp) 388 { 389 struct filestat *entry; 390 391 entry = calloc(1, sizeof(*entry)); 392 if (entry == NULL) { 393 warn("malloc()"); 394 return (NULL); 395 } 396 entry->fs_typedep = typedep; 397 entry->fs_fflags = fflags; 398 entry->fs_uflags = uflags; 399 entry->fs_fd = fd; 400 entry->fs_type = type; 401 entry->fs_ref_count = refcount; 402 entry->fs_offset = offset; 403 entry->fs_path = path; 404 if (cap_rightsp != NULL) 405 entry->fs_cap_rights = *cap_rightsp; 406 else 407 cap_rights_init(&entry->fs_cap_rights); 408 return (entry); 409 } 410 411 static struct vnode * 412 getctty(kvm_t *kd, struct kinfo_proc *kp) 413 { 414 struct pgrp pgrp; 415 struct proc proc; 416 struct session sess; 417 int error; 418 419 assert(kp); 420 error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 421 sizeof(proc)); 422 if (error == 0) { 423 warnx("can't read proc struct at %p for pid %d", 424 kp->ki_paddr, kp->ki_pid); 425 return (NULL); 426 } 427 if (proc.p_pgrp == NULL) 428 return (NULL); 429 error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp, 430 sizeof(pgrp)); 431 if (error == 0) { 432 warnx("can't read pgrp struct at %p for pid %d", 433 proc.p_pgrp, kp->ki_pid); 434 return (NULL); 435 } 436 error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess, 437 sizeof(sess)); 438 if (error == 0) { 439 warnx("can't read session struct at %p for pid %d", 440 pgrp.pg_session, kp->ki_pid); 441 return (NULL); 442 } 443 return (sess.s_ttyvp); 444 } 445 446 static int 447 procstat_vm_map_reader(void *token, vm_map_entry_t addr, vm_map_entry_t dest) 448 { 449 kvm_t *kd; 450 451 kd = (kvm_t *)token; 452 return (kvm_read_all(kd, (unsigned long)addr, dest, sizeof(*dest))); 453 } 454 455 static struct filestat_list * 456 procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 457 { 458 struct file file; 459 struct filedesc filed; 460 struct pwddesc pathsd; 461 struct fdescenttbl *fdt; 462 struct pwd pwd; 463 unsigned long pwd_addr; 464 struct vm_map_entry vmentry; 465 struct vm_object object; 466 struct vmspace vmspace; 467 vm_map_entry_t entryp; 468 vm_object_t objp; 469 struct vnode *vp; 470 struct filestat *entry; 471 struct filestat_list *head; 472 kvm_t *kd; 473 void *data; 474 int fflags; 475 unsigned int i; 476 int prot, type; 477 size_t fdt_size; 478 unsigned int nfiles; 479 bool haspwd; 480 481 assert(procstat); 482 kd = procstat->kd; 483 if (kd == NULL) 484 return (NULL); 485 if (kp->ki_fd == NULL || kp->ki_pd == NULL) 486 return (NULL); 487 if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed, 488 sizeof(filed))) { 489 warnx("can't read filedesc at %p", (void *)kp->ki_fd); 490 return (NULL); 491 } 492 if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pathsd, 493 sizeof(pathsd))) { 494 warnx("can't read pwddesc at %p", (void *)kp->ki_pd); 495 return (NULL); 496 } 497 haspwd = false; 498 pwd_addr = (unsigned long)(PWDDESC_KVM_LOAD_PWD(&pathsd)); 499 if (pwd_addr != 0) { 500 if (!kvm_read_all(kd, pwd_addr, &pwd, sizeof(pwd))) { 501 warnx("can't read fd_pwd at %p", (void *)pwd_addr); 502 return (NULL); 503 } 504 haspwd = true; 505 } 506 507 /* 508 * Allocate list head. 509 */ 510 head = malloc(sizeof(*head)); 511 if (head == NULL) 512 return (NULL); 513 STAILQ_INIT(head); 514 515 /* root directory vnode, if one. */ 516 if (haspwd) { 517 if (pwd.pwd_rdir) { 518 entry = filestat_new_entry(pwd.pwd_rdir, PS_FST_TYPE_VNODE, -1, 519 PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL, NULL); 520 if (entry != NULL) 521 STAILQ_INSERT_TAIL(head, entry, next); 522 } 523 /* current working directory vnode. */ 524 if (pwd.pwd_cdir) { 525 entry = filestat_new_entry(pwd.pwd_cdir, PS_FST_TYPE_VNODE, -1, 526 PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL, NULL); 527 if (entry != NULL) 528 STAILQ_INSERT_TAIL(head, entry, next); 529 } 530 /* jail root, if any. */ 531 if (pwd.pwd_jdir) { 532 entry = filestat_new_entry(pwd.pwd_jdir, PS_FST_TYPE_VNODE, -1, 533 PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL, NULL); 534 if (entry != NULL) 535 STAILQ_INSERT_TAIL(head, entry, next); 536 } 537 } 538 /* ktrace vnode, if one */ 539 if (kp->ki_tracep) { 540 entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1, 541 PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, 542 PS_FST_UFLAG_TRACE, 0, 0, NULL, NULL); 543 if (entry != NULL) 544 STAILQ_INSERT_TAIL(head, entry, next); 545 } 546 /* text vnode, if one */ 547 if (kp->ki_textvp) { 548 entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1, 549 PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL, NULL); 550 if (entry != NULL) 551 STAILQ_INSERT_TAIL(head, entry, next); 552 } 553 /* Controlling terminal. */ 554 if ((vp = getctty(kd, kp)) != NULL) { 555 entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1, 556 PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, 557 PS_FST_UFLAG_CTTY, 0, 0, NULL, NULL); 558 if (entry != NULL) 559 STAILQ_INSERT_TAIL(head, entry, next); 560 } 561 562 if (!kvm_read_all(kd, (unsigned long)filed.fd_files, &nfiles, 563 sizeof(nfiles))) { 564 warnx("can't read fd_files at %p", (void *)filed.fd_files); 565 return (NULL); 566 } 567 568 fdt_size = sizeof(*fdt) + nfiles * sizeof(struct filedescent); 569 fdt = malloc(fdt_size); 570 if (fdt == NULL) { 571 warn("malloc(%zu)", fdt_size); 572 goto do_mmapped; 573 } 574 if (!kvm_read_all(kd, (unsigned long)filed.fd_files, fdt, fdt_size)) { 575 warnx("cannot read file structures at %p", (void *)filed.fd_files); 576 free(fdt); 577 goto do_mmapped; 578 } 579 for (i = 0; i < nfiles; i++) { 580 if (fdt->fdt_ofiles[i].fde_file == NULL) { 581 continue; 582 } 583 if (!kvm_read_all(kd, (unsigned long)fdt->fdt_ofiles[i].fde_file, &file, 584 sizeof(struct file))) { 585 warnx("can't read file %d at %p", i, 586 (void *)fdt->fdt_ofiles[i].fde_file); 587 continue; 588 } 589 switch (file.f_type) { 590 case DTYPE_VNODE: 591 type = PS_FST_TYPE_VNODE; 592 data = file.f_vnode; 593 break; 594 case DTYPE_SOCKET: 595 type = PS_FST_TYPE_SOCKET; 596 data = file.f_data; 597 break; 598 case DTYPE_PIPE: 599 type = PS_FST_TYPE_PIPE; 600 data = file.f_data; 601 break; 602 case DTYPE_FIFO: 603 type = PS_FST_TYPE_FIFO; 604 data = file.f_vnode; 605 break; 606 #ifdef DTYPE_PTS 607 case DTYPE_PTS: 608 type = PS_FST_TYPE_PTS; 609 data = file.f_data; 610 break; 611 #endif 612 case DTYPE_SEM: 613 type = PS_FST_TYPE_SEM; 614 data = file.f_data; 615 break; 616 case DTYPE_SHM: 617 type = PS_FST_TYPE_SHM; 618 data = file.f_data; 619 break; 620 case DTYPE_PROCDESC: 621 type = PS_FST_TYPE_PROCDESC; 622 data = file.f_data; 623 break; 624 case DTYPE_DEV: 625 type = PS_FST_TYPE_DEV; 626 data = file.f_data; 627 break; 628 case DTYPE_EVENTFD: 629 type = PS_FST_TYPE_EVENTFD; 630 data = file.f_data; 631 break; 632 default: 633 continue; 634 } 635 /* XXXRW: No capability rights support for kvm yet. */ 636 entry = filestat_new_entry(data, type, i, 637 to_filestat_flags(file.f_flag), 0, 0, 0, NULL, NULL); 638 if (entry != NULL) 639 STAILQ_INSERT_TAIL(head, entry, next); 640 } 641 free(fdt); 642 643 do_mmapped: 644 645 /* 646 * Process mmapped files if requested. 647 */ 648 if (mmapped) { 649 if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace, 650 sizeof(vmspace))) { 651 warnx("can't read vmspace at %p", 652 (void *)kp->ki_vmspace); 653 goto exit; 654 } 655 656 vmentry = vmspace.vm_map.header; 657 for (entryp = vm_map_entry_read_succ(kd, &vmentry, procstat_vm_map_reader); 658 entryp != NULL && entryp != &kp->ki_vmspace->vm_map.header; 659 entryp = vm_map_entry_read_succ(kd, &vmentry, procstat_vm_map_reader)) { 660 if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP) 661 continue; 662 if ((objp = vmentry.object.vm_object) == NULL) 663 continue; 664 for (; objp; objp = object.backing_object) { 665 if (!kvm_read_all(kd, (unsigned long)objp, 666 &object, sizeof(object))) { 667 warnx("can't read vm_object at %p", 668 (void *)objp); 669 break; 670 } 671 } 672 673 /* We want only vnode objects. */ 674 if (object.type != OBJT_VNODE) 675 continue; 676 677 prot = vmentry.protection; 678 fflags = 0; 679 if (prot & VM_PROT_READ) 680 fflags = PS_FST_FFLAG_READ; 681 if ((vmentry.eflags & MAP_ENTRY_COW) == 0 && 682 prot & VM_PROT_WRITE) 683 fflags |= PS_FST_FFLAG_WRITE; 684 685 /* 686 * Create filestat entry. 687 */ 688 entry = filestat_new_entry(object.handle, 689 PS_FST_TYPE_VNODE, -1, fflags, 690 PS_FST_UFLAG_MMAP, 0, 0, NULL, NULL); 691 if (entry != NULL) 692 STAILQ_INSERT_TAIL(head, entry, next); 693 } 694 if (entryp == NULL) 695 warnx("can't read vm_map_entry"); 696 } 697 exit: 698 return (head); 699 } 700 701 /* 702 * kinfo types to filestat translation. 703 */ 704 static int 705 kinfo_type2fst(int kftype) 706 { 707 static struct { 708 int kf_type; 709 int fst_type; 710 } kftypes2fst[] = { 711 { KF_TYPE_PROCDESC, PS_FST_TYPE_PROCDESC }, 712 { KF_TYPE_DEV, PS_FST_TYPE_DEV }, 713 { KF_TYPE_FIFO, PS_FST_TYPE_FIFO }, 714 { KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE }, 715 { KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE }, 716 { KF_TYPE_NONE, PS_FST_TYPE_NONE }, 717 { KF_TYPE_PIPE, PS_FST_TYPE_PIPE }, 718 { KF_TYPE_PTS, PS_FST_TYPE_PTS }, 719 { KF_TYPE_SEM, PS_FST_TYPE_SEM }, 720 { KF_TYPE_SHM, PS_FST_TYPE_SHM }, 721 { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET }, 722 { KF_TYPE_VNODE, PS_FST_TYPE_VNODE }, 723 { KF_TYPE_EVENTFD, PS_FST_TYPE_EVENTFD }, 724 { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN } 725 }; 726 #define NKFTYPES (sizeof(kftypes2fst) / sizeof(*kftypes2fst)) 727 unsigned int i; 728 729 for (i = 0; i < NKFTYPES; i++) 730 if (kftypes2fst[i].kf_type == kftype) 731 break; 732 if (i == NKFTYPES) 733 return (PS_FST_TYPE_UNKNOWN); 734 return (kftypes2fst[i].fst_type); 735 } 736 737 /* 738 * kinfo flags to filestat translation. 739 */ 740 static int 741 kinfo_fflags2fst(int kfflags) 742 { 743 static struct { 744 int kf_flag; 745 int fst_flag; 746 } kfflags2fst[] = { 747 { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND }, 748 { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC }, 749 { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT }, 750 { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT }, 751 { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL }, 752 { KF_FLAG_EXEC, PS_FST_FFLAG_EXEC }, 753 { KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK }, 754 { KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC }, 755 { KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK }, 756 { KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 757 { KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 758 { KF_FLAG_READ, PS_FST_FFLAG_READ }, 759 { KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK }, 760 { KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC }, 761 { KF_FLAG_WRITE, PS_FST_FFLAG_WRITE } 762 }; 763 #define NKFFLAGS (sizeof(kfflags2fst) / sizeof(*kfflags2fst)) 764 unsigned int i; 765 int flags; 766 767 flags = 0; 768 for (i = 0; i < NKFFLAGS; i++) 769 if ((kfflags & kfflags2fst[i].kf_flag) != 0) 770 flags |= kfflags2fst[i].fst_flag; 771 return (flags); 772 } 773 774 static int 775 kinfo_uflags2fst(int fd) 776 { 777 778 switch (fd) { 779 case KF_FD_TYPE_CTTY: 780 return (PS_FST_UFLAG_CTTY); 781 case KF_FD_TYPE_CWD: 782 return (PS_FST_UFLAG_CDIR); 783 case KF_FD_TYPE_JAIL: 784 return (PS_FST_UFLAG_JAIL); 785 case KF_FD_TYPE_TEXT: 786 return (PS_FST_UFLAG_TEXT); 787 case KF_FD_TYPE_TRACE: 788 return (PS_FST_UFLAG_TRACE); 789 case KF_FD_TYPE_ROOT: 790 return (PS_FST_UFLAG_RDIR); 791 } 792 return (0); 793 } 794 795 static struct kinfo_file * 796 kinfo_getfile_core(struct procstat_core *core, int *cntp) 797 { 798 int cnt; 799 size_t len; 800 char *buf, *bp, *eb; 801 struct kinfo_file *kif, *kp, *kf; 802 803 buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len); 804 if (buf == NULL) 805 return (NULL); 806 /* 807 * XXXMG: The code below is just copy&past from libutil. 808 * The code duplication can be avoided if libutil 809 * is extended to provide something like: 810 * struct kinfo_file *kinfo_getfile_from_buf(const char *buf, 811 * size_t len, int *cntp); 812 */ 813 814 /* Pass 1: count items */ 815 cnt = 0; 816 bp = buf; 817 eb = buf + len; 818 while (bp < eb) { 819 kf = (struct kinfo_file *)(uintptr_t)bp; 820 if (kf->kf_structsize == 0) 821 break; 822 bp += kf->kf_structsize; 823 cnt++; 824 } 825 826 kif = calloc(cnt, sizeof(*kif)); 827 if (kif == NULL) { 828 free(buf); 829 return (NULL); 830 } 831 bp = buf; 832 eb = buf + len; 833 kp = kif; 834 /* Pass 2: unpack */ 835 while (bp < eb) { 836 kf = (struct kinfo_file *)(uintptr_t)bp; 837 if (kf->kf_structsize == 0) 838 break; 839 /* Copy/expand into pre-zeroed buffer */ 840 memcpy(kp, kf, kf->kf_structsize); 841 /* Advance to next packed record */ 842 bp += kf->kf_structsize; 843 /* Set field size to fixed length, advance */ 844 kp->kf_structsize = sizeof(*kp); 845 kp++; 846 } 847 free(buf); 848 *cntp = cnt; 849 return (kif); /* Caller must free() return value */ 850 } 851 852 static struct filestat_list * 853 procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, 854 int mmapped) 855 { 856 struct kinfo_file *kif, *files; 857 struct kinfo_vmentry *kve, *vmentries; 858 struct filestat_list *head; 859 struct filestat *entry; 860 char *path; 861 off_t offset; 862 int cnt, fd, fflags; 863 int i, type, uflags; 864 int refcount; 865 cap_rights_t cap_rights; 866 867 assert(kp); 868 if (kp->ki_fd == NULL) 869 return (NULL); 870 switch(procstat->type) { 871 case PROCSTAT_SYSCTL: 872 files = kinfo_getfile(kp->ki_pid, &cnt); 873 break; 874 case PROCSTAT_CORE: 875 files = kinfo_getfile_core(procstat->core, &cnt); 876 break; 877 default: 878 assert(!"invalid type"); 879 } 880 if (files == NULL && errno != EPERM) { 881 warn("kinfo_getfile()"); 882 return (NULL); 883 } 884 procstat->files = files; 885 886 /* 887 * Allocate list head. 888 */ 889 head = malloc(sizeof(*head)); 890 if (head == NULL) 891 return (NULL); 892 STAILQ_INIT(head); 893 for (i = 0; i < cnt; i++) { 894 kif = &files[i]; 895 896 type = kinfo_type2fst(kif->kf_type); 897 fd = kif->kf_fd >= 0 ? kif->kf_fd : -1; 898 fflags = kinfo_fflags2fst(kif->kf_flags); 899 uflags = kinfo_uflags2fst(kif->kf_fd); 900 refcount = kif->kf_ref_count; 901 offset = kif->kf_offset; 902 if (*kif->kf_path != '\0') 903 path = strdup(kif->kf_path); 904 else 905 path = NULL; 906 cap_rights = kif->kf_cap_rights; 907 908 /* 909 * Create filestat entry. 910 */ 911 entry = filestat_new_entry(kif, type, fd, fflags, uflags, 912 refcount, offset, path, &cap_rights); 913 if (entry != NULL) 914 STAILQ_INSERT_TAIL(head, entry, next); 915 } 916 if (mmapped != 0) { 917 vmentries = procstat_getvmmap(procstat, kp, &cnt); 918 procstat->vmentries = vmentries; 919 if (vmentries == NULL || cnt == 0) 920 goto fail; 921 for (i = 0; i < cnt; i++) { 922 kve = &vmentries[i]; 923 if (kve->kve_type != KVME_TYPE_VNODE) 924 continue; 925 fflags = 0; 926 if (kve->kve_protection & KVME_PROT_READ) 927 fflags = PS_FST_FFLAG_READ; 928 if ((kve->kve_flags & KVME_FLAG_COW) == 0 && 929 kve->kve_protection & KVME_PROT_WRITE) 930 fflags |= PS_FST_FFLAG_WRITE; 931 offset = kve->kve_offset; 932 refcount = kve->kve_ref_count; 933 if (*kve->kve_path != '\0') 934 path = strdup(kve->kve_path); 935 else 936 path = NULL; 937 entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1, 938 fflags, PS_FST_UFLAG_MMAP, refcount, offset, path, 939 NULL); 940 if (entry != NULL) 941 STAILQ_INSERT_TAIL(head, entry, next); 942 } 943 } 944 fail: 945 return (head); 946 } 947 948 int 949 procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, 950 struct pipestat *ps, char *errbuf) 951 { 952 953 assert(ps); 954 if (procstat->type == PROCSTAT_KVM) { 955 return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps, 956 errbuf)); 957 } else if (procstat->type == PROCSTAT_SYSCTL || 958 procstat->type == PROCSTAT_CORE) { 959 return (procstat_get_pipe_info_sysctl(fst, ps, errbuf)); 960 } else { 961 warnx("unknown access method: %d", procstat->type); 962 if (errbuf != NULL) 963 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 964 return (1); 965 } 966 } 967 968 static int 969 procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, 970 struct pipestat *ps, char *errbuf) 971 { 972 struct pipe pi; 973 void *pipep; 974 975 assert(kd); 976 assert(ps); 977 assert(fst); 978 bzero(ps, sizeof(*ps)); 979 pipep = fst->fs_typedep; 980 if (pipep == NULL) 981 goto fail; 982 if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) { 983 warnx("can't read pipe at %p", (void *)pipep); 984 goto fail; 985 } 986 ps->addr = (uintptr_t)pipep; 987 ps->peer = (uintptr_t)pi.pipe_peer; 988 ps->buffer_cnt = pi.pipe_buffer.cnt; 989 return (0); 990 991 fail: 992 if (errbuf != NULL) 993 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 994 return (1); 995 } 996 997 static int 998 procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps, 999 char *errbuf __unused) 1000 { 1001 struct kinfo_file *kif; 1002 1003 assert(ps); 1004 assert(fst); 1005 bzero(ps, sizeof(*ps)); 1006 kif = fst->fs_typedep; 1007 if (kif == NULL) 1008 return (1); 1009 ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr; 1010 ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer; 1011 ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt; 1012 return (0); 1013 } 1014 1015 int 1016 procstat_get_pts_info(struct procstat *procstat, struct filestat *fst, 1017 struct ptsstat *pts, char *errbuf) 1018 { 1019 1020 assert(pts); 1021 if (procstat->type == PROCSTAT_KVM) { 1022 return (procstat_get_pts_info_kvm(procstat->kd, fst, pts, 1023 errbuf)); 1024 } else if (procstat->type == PROCSTAT_SYSCTL || 1025 procstat->type == PROCSTAT_CORE) { 1026 return (procstat_get_pts_info_sysctl(fst, pts, errbuf)); 1027 } else { 1028 warnx("unknown access method: %d", procstat->type); 1029 if (errbuf != NULL) 1030 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1031 return (1); 1032 } 1033 } 1034 1035 static int 1036 procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, 1037 struct ptsstat *pts, char *errbuf) 1038 { 1039 struct tty tty; 1040 void *ttyp; 1041 1042 assert(kd); 1043 assert(pts); 1044 assert(fst); 1045 bzero(pts, sizeof(*pts)); 1046 ttyp = fst->fs_typedep; 1047 if (ttyp == NULL) 1048 goto fail; 1049 if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) { 1050 warnx("can't read tty at %p", (void *)ttyp); 1051 goto fail; 1052 } 1053 pts->dev = dev2udev(kd, tty.t_dev); 1054 (void)kdevtoname(kd, tty.t_dev, pts->devname); 1055 return (0); 1056 1057 fail: 1058 if (errbuf != NULL) 1059 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1060 return (1); 1061 } 1062 1063 static int 1064 procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts, 1065 char *errbuf __unused) 1066 { 1067 struct kinfo_file *kif; 1068 1069 assert(pts); 1070 assert(fst); 1071 bzero(pts, sizeof(*pts)); 1072 kif = fst->fs_typedep; 1073 if (kif == NULL) 1074 return (0); 1075 pts->dev = kif->kf_un.kf_pts.kf_pts_dev; 1076 strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname)); 1077 return (0); 1078 } 1079 1080 int 1081 procstat_get_sem_info(struct procstat *procstat, struct filestat *fst, 1082 struct semstat *sem, char *errbuf) 1083 { 1084 1085 assert(sem); 1086 if (procstat->type == PROCSTAT_KVM) { 1087 return (procstat_get_sem_info_kvm(procstat->kd, fst, sem, 1088 errbuf)); 1089 } else if (procstat->type == PROCSTAT_SYSCTL || 1090 procstat->type == PROCSTAT_CORE) { 1091 return (procstat_get_sem_info_sysctl(fst, sem, errbuf)); 1092 } else { 1093 warnx("unknown access method: %d", procstat->type); 1094 if (errbuf != NULL) 1095 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1096 return (1); 1097 } 1098 } 1099 1100 static int 1101 procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst, 1102 struct semstat *sem, char *errbuf) 1103 { 1104 struct ksem ksem; 1105 void *ksemp; 1106 char *path; 1107 int i; 1108 1109 assert(kd); 1110 assert(sem); 1111 assert(fst); 1112 bzero(sem, sizeof(*sem)); 1113 ksemp = fst->fs_typedep; 1114 if (ksemp == NULL) 1115 goto fail; 1116 if (!kvm_read_all(kd, (unsigned long)ksemp, &ksem, 1117 sizeof(struct ksem))) { 1118 warnx("can't read ksem at %p", (void *)ksemp); 1119 goto fail; 1120 } 1121 sem->mode = S_IFREG | ksem.ks_mode; 1122 sem->value = ksem.ks_value; 1123 if (fst->fs_path == NULL && ksem.ks_path != NULL) { 1124 path = malloc(MAXPATHLEN); 1125 for (i = 0; i < MAXPATHLEN - 1; i++) { 1126 if (!kvm_read_all(kd, (unsigned long)ksem.ks_path + i, 1127 path + i, 1)) 1128 break; 1129 if (path[i] == '\0') 1130 break; 1131 } 1132 path[i] = '\0'; 1133 if (i == 0) 1134 free(path); 1135 else 1136 fst->fs_path = path; 1137 } 1138 return (0); 1139 1140 fail: 1141 if (errbuf != NULL) 1142 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1143 return (1); 1144 } 1145 1146 static int 1147 procstat_get_sem_info_sysctl(struct filestat *fst, struct semstat *sem, 1148 char *errbuf __unused) 1149 { 1150 struct kinfo_file *kif; 1151 1152 assert(sem); 1153 assert(fst); 1154 bzero(sem, sizeof(*sem)); 1155 kif = fst->fs_typedep; 1156 if (kif == NULL) 1157 return (0); 1158 sem->value = kif->kf_un.kf_sem.kf_sem_value; 1159 sem->mode = kif->kf_un.kf_sem.kf_sem_mode; 1160 return (0); 1161 } 1162 1163 int 1164 procstat_get_shm_info(struct procstat *procstat, struct filestat *fst, 1165 struct shmstat *shm, char *errbuf) 1166 { 1167 1168 assert(shm); 1169 if (procstat->type == PROCSTAT_KVM) { 1170 return (procstat_get_shm_info_kvm(procstat->kd, fst, shm, 1171 errbuf)); 1172 } else if (procstat->type == PROCSTAT_SYSCTL || 1173 procstat->type == PROCSTAT_CORE) { 1174 return (procstat_get_shm_info_sysctl(fst, shm, errbuf)); 1175 } else { 1176 warnx("unknown access method: %d", procstat->type); 1177 if (errbuf != NULL) 1178 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1179 return (1); 1180 } 1181 } 1182 1183 static int 1184 procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst, 1185 struct shmstat *shm, char *errbuf) 1186 { 1187 struct shmfd shmfd; 1188 void *shmfdp; 1189 char *path; 1190 int i; 1191 1192 assert(kd); 1193 assert(shm); 1194 assert(fst); 1195 bzero(shm, sizeof(*shm)); 1196 shmfdp = fst->fs_typedep; 1197 if (shmfdp == NULL) 1198 goto fail; 1199 if (!kvm_read_all(kd, (unsigned long)shmfdp, &shmfd, 1200 sizeof(struct shmfd))) { 1201 warnx("can't read shmfd at %p", (void *)shmfdp); 1202 goto fail; 1203 } 1204 shm->mode = S_IFREG | shmfd.shm_mode; 1205 shm->size = shmfd.shm_size; 1206 if (fst->fs_path == NULL && shmfd.shm_path != NULL) { 1207 path = malloc(MAXPATHLEN); 1208 for (i = 0; i < MAXPATHLEN - 1; i++) { 1209 if (!kvm_read_all(kd, (unsigned long)shmfd.shm_path + i, 1210 path + i, 1)) 1211 break; 1212 if (path[i] == '\0') 1213 break; 1214 } 1215 path[i] = '\0'; 1216 if (i == 0) 1217 free(path); 1218 else 1219 fst->fs_path = path; 1220 } 1221 return (0); 1222 1223 fail: 1224 if (errbuf != NULL) 1225 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1226 return (1); 1227 } 1228 1229 static int 1230 procstat_get_shm_info_sysctl(struct filestat *fst, struct shmstat *shm, 1231 char *errbuf __unused) 1232 { 1233 struct kinfo_file *kif; 1234 1235 assert(shm); 1236 assert(fst); 1237 bzero(shm, sizeof(*shm)); 1238 kif = fst->fs_typedep; 1239 if (kif == NULL) 1240 return (0); 1241 shm->size = kif->kf_un.kf_file.kf_file_size; 1242 shm->mode = kif->kf_un.kf_file.kf_file_mode; 1243 return (0); 1244 } 1245 1246 int 1247 procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, 1248 struct vnstat *vn, char *errbuf) 1249 { 1250 1251 assert(vn); 1252 if (procstat->type == PROCSTAT_KVM) { 1253 return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn, 1254 errbuf)); 1255 } else if (procstat->type == PROCSTAT_SYSCTL || 1256 procstat->type == PROCSTAT_CORE) { 1257 return (procstat_get_vnode_info_sysctl(fst, vn, errbuf)); 1258 } else { 1259 warnx("unknown access method: %d", procstat->type); 1260 if (errbuf != NULL) 1261 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1262 return (1); 1263 } 1264 } 1265 1266 static int 1267 procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, 1268 struct vnstat *vn, char *errbuf) 1269 { 1270 /* Filesystem specific handlers. */ 1271 #define FSTYPE(fst) {#fst, fst##_filestat} 1272 struct { 1273 const char *tag; 1274 int (*handler)(kvm_t *kd, struct vnode *vp, 1275 struct vnstat *vn); 1276 } fstypes[] = { 1277 FSTYPE(devfs), 1278 FSTYPE(isofs), 1279 FSTYPE(msdosfs), 1280 FSTYPE(nfs), 1281 FSTYPE(smbfs), 1282 FSTYPE(udf), 1283 FSTYPE(ufs), 1284 #ifdef LIBPROCSTAT_ZFS 1285 FSTYPE(zfs), 1286 #endif 1287 }; 1288 #define NTYPES (sizeof(fstypes) / sizeof(*fstypes)) 1289 struct vnode vnode; 1290 char tagstr[12]; 1291 void *vp; 1292 int error; 1293 unsigned int i; 1294 1295 assert(kd); 1296 assert(vn); 1297 assert(fst); 1298 vp = fst->fs_typedep; 1299 if (vp == NULL) 1300 goto fail; 1301 error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode)); 1302 if (error == 0) { 1303 warnx("can't read vnode at %p", (void *)vp); 1304 goto fail; 1305 } 1306 bzero(vn, sizeof(*vn)); 1307 vn->vn_type = vntype2psfsttype(vnode.v_type); 1308 if (vnode.v_type == VNON || vnode.v_type == VBAD) 1309 return (0); 1310 error = kvm_read_all(kd, (unsigned long)vnode.v_lock.lock_object.lo_name, 1311 tagstr, sizeof(tagstr)); 1312 if (error == 0) { 1313 warnx("can't read lo_name at %p", (void *)vp); 1314 goto fail; 1315 } 1316 tagstr[sizeof(tagstr) - 1] = '\0'; 1317 1318 /* 1319 * Find appropriate handler. 1320 */ 1321 for (i = 0; i < NTYPES; i++) 1322 if (!strcmp(fstypes[i].tag, tagstr)) { 1323 if (fstypes[i].handler(kd, &vnode, vn) != 0) { 1324 goto fail; 1325 } 1326 break; 1327 } 1328 if (i == NTYPES) { 1329 if (errbuf != NULL) 1330 snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr); 1331 return (1); 1332 } 1333 vn->vn_mntdir = getmnton(kd, vnode.v_mount); 1334 if ((vnode.v_type == VBLK || vnode.v_type == VCHR) && 1335 vnode.v_rdev != NULL){ 1336 vn->vn_dev = dev2udev(kd, vnode.v_rdev); 1337 (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname); 1338 } else { 1339 vn->vn_dev = -1; 1340 } 1341 return (0); 1342 1343 fail: 1344 if (errbuf != NULL) 1345 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1346 return (1); 1347 } 1348 1349 /* 1350 * kinfo vnode type to filestat translation. 1351 */ 1352 static int 1353 kinfo_vtype2fst(int kfvtype) 1354 { 1355 static struct { 1356 int kf_vtype; 1357 int fst_vtype; 1358 } kfvtypes2fst[] = { 1359 { KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD }, 1360 { KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK }, 1361 { KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR }, 1362 { KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR }, 1363 { KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO }, 1364 { KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK }, 1365 { KF_VTYPE_VNON, PS_FST_VTYPE_VNON }, 1366 { KF_VTYPE_VREG, PS_FST_VTYPE_VREG }, 1367 { KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK } 1368 }; 1369 #define NKFVTYPES (sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst)) 1370 unsigned int i; 1371 1372 for (i = 0; i < NKFVTYPES; i++) 1373 if (kfvtypes2fst[i].kf_vtype == kfvtype) 1374 break; 1375 if (i == NKFVTYPES) 1376 return (PS_FST_VTYPE_UNKNOWN); 1377 return (kfvtypes2fst[i].fst_vtype); 1378 } 1379 1380 static int 1381 procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn, 1382 char *errbuf) 1383 { 1384 struct statfs stbuf; 1385 struct kinfo_file *kif; 1386 struct kinfo_vmentry *kve; 1387 char *name, *path; 1388 uint64_t fileid; 1389 uint64_t size; 1390 uint64_t fsid; 1391 uint64_t rdev; 1392 uint16_t mode; 1393 int vntype; 1394 int status; 1395 1396 assert(fst); 1397 assert(vn); 1398 bzero(vn, sizeof(*vn)); 1399 if (fst->fs_typedep == NULL) 1400 return (1); 1401 if (fst->fs_uflags & PS_FST_UFLAG_MMAP) { 1402 kve = fst->fs_typedep; 1403 fileid = kve->kve_vn_fileid; 1404 fsid = kve->kve_vn_fsid; 1405 mode = kve->kve_vn_mode; 1406 path = kve->kve_path; 1407 rdev = kve->kve_vn_rdev; 1408 size = kve->kve_vn_size; 1409 vntype = kinfo_vtype2fst(kve->kve_vn_type); 1410 status = kve->kve_status; 1411 } else { 1412 kif = fst->fs_typedep; 1413 fileid = kif->kf_un.kf_file.kf_file_fileid; 1414 fsid = kif->kf_un.kf_file.kf_file_fsid; 1415 mode = kif->kf_un.kf_file.kf_file_mode; 1416 path = kif->kf_path; 1417 rdev = kif->kf_un.kf_file.kf_file_rdev; 1418 size = kif->kf_un.kf_file.kf_file_size; 1419 vntype = kinfo_vtype2fst(kif->kf_vnode_type); 1420 status = kif->kf_status; 1421 } 1422 vn->vn_type = vntype; 1423 if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD) 1424 return (0); 1425 if ((status & KF_ATTR_VALID) == 0) { 1426 if (errbuf != NULL) { 1427 snprintf(errbuf, _POSIX2_LINE_MAX, 1428 "? (no info available)"); 1429 } 1430 return (1); 1431 } 1432 if (path && *path) { 1433 statfs(path, &stbuf); 1434 vn->vn_mntdir = strdup(stbuf.f_mntonname); 1435 } else 1436 vn->vn_mntdir = strdup("-"); 1437 vn->vn_dev = rdev; 1438 if (vntype == PS_FST_VTYPE_VBLK) { 1439 name = devname(rdev, S_IFBLK); 1440 if (name != NULL) 1441 strlcpy(vn->vn_devname, name, 1442 sizeof(vn->vn_devname)); 1443 } else if (vntype == PS_FST_VTYPE_VCHR) { 1444 name = devname(vn->vn_dev, S_IFCHR); 1445 if (name != NULL) 1446 strlcpy(vn->vn_devname, name, 1447 sizeof(vn->vn_devname)); 1448 } 1449 vn->vn_fsid = fsid; 1450 vn->vn_fileid = fileid; 1451 vn->vn_size = size; 1452 vn->vn_mode = mode; 1453 return (0); 1454 } 1455 1456 int 1457 procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, 1458 struct sockstat *sock, char *errbuf) 1459 { 1460 1461 assert(sock); 1462 if (procstat->type == PROCSTAT_KVM) { 1463 return (procstat_get_socket_info_kvm(procstat->kd, fst, sock, 1464 errbuf)); 1465 } else if (procstat->type == PROCSTAT_SYSCTL || 1466 procstat->type == PROCSTAT_CORE) { 1467 return (procstat_get_socket_info_sysctl(fst, sock, errbuf)); 1468 } else { 1469 warnx("unknown access method: %d", procstat->type); 1470 if (errbuf != NULL) 1471 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1472 return (1); 1473 } 1474 } 1475 1476 static int 1477 procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, 1478 struct sockstat *sock, char *errbuf) 1479 { 1480 struct domain dom; 1481 struct inpcb inpcb; 1482 struct protosw proto; 1483 struct socket s; 1484 struct unpcb unpcb; 1485 ssize_t len; 1486 void *so; 1487 1488 assert(kd); 1489 assert(sock); 1490 assert(fst); 1491 bzero(sock, sizeof(*sock)); 1492 so = fst->fs_typedep; 1493 if (so == NULL) 1494 goto fail; 1495 sock->so_addr = (uintptr_t)so; 1496 /* fill in socket */ 1497 if (!kvm_read_all(kd, (unsigned long)so, &s, 1498 sizeof(struct socket))) { 1499 warnx("can't read sock at %p", (void *)so); 1500 goto fail; 1501 } 1502 /* fill in protosw entry */ 1503 if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto, 1504 sizeof(struct protosw))) { 1505 warnx("can't read protosw at %p", (void *)s.so_proto); 1506 goto fail; 1507 } 1508 /* fill in domain */ 1509 if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom, 1510 sizeof(struct domain))) { 1511 warnx("can't read domain at %p", 1512 (void *)proto.pr_domain); 1513 goto fail; 1514 } 1515 if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname, 1516 sizeof(sock->dname) - 1)) < 0) { 1517 warnx("can't read domain name at %p", (void *)dom.dom_name); 1518 sock->dname[0] = '\0'; 1519 } 1520 else 1521 sock->dname[len] = '\0'; 1522 1523 /* 1524 * Fill in known data. 1525 */ 1526 sock->type = s.so_type; 1527 sock->proto = proto.pr_protocol; 1528 sock->dom_family = dom.dom_family; 1529 sock->so_pcb = (uintptr_t)s.so_pcb; 1530 1531 /* 1532 * Protocol specific data. 1533 */ 1534 switch(dom.dom_family) { 1535 case AF_INET: 1536 case AF_INET6: 1537 if (proto.pr_protocol == IPPROTO_TCP) { 1538 if (s.so_pcb) { 1539 if (kvm_read(kd, (u_long)s.so_pcb, 1540 (char *)&inpcb, sizeof(struct inpcb)) 1541 != sizeof(struct inpcb)) { 1542 warnx("can't read inpcb at %p", 1543 (void *)s.so_pcb); 1544 } else 1545 sock->inp_ppcb = 1546 (uintptr_t)inpcb.inp_ppcb; 1547 sock->sendq = s.so_snd.sb_ccc; 1548 sock->recvq = s.so_rcv.sb_ccc; 1549 } 1550 } 1551 break; 1552 case AF_UNIX: 1553 if (s.so_pcb) { 1554 if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb, 1555 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 1556 warnx("can't read unpcb at %p", 1557 (void *)s.so_pcb); 1558 } else if (unpcb.unp_conn) { 1559 sock->so_rcv_sb_state = s.so_rcv.sb_state; 1560 sock->so_snd_sb_state = s.so_snd.sb_state; 1561 sock->unp_conn = (uintptr_t)unpcb.unp_conn; 1562 sock->sendq = s.so_snd.sb_ccc; 1563 sock->recvq = s.so_rcv.sb_ccc; 1564 } 1565 } 1566 break; 1567 default: 1568 break; 1569 } 1570 return (0); 1571 1572 fail: 1573 if (errbuf != NULL) 1574 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1575 return (1); 1576 } 1577 1578 static int 1579 procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, 1580 char *errbuf __unused) 1581 { 1582 struct kinfo_file *kif; 1583 1584 assert(sock); 1585 assert(fst); 1586 bzero(sock, sizeof(*sock)); 1587 kif = fst->fs_typedep; 1588 if (kif == NULL) 1589 return (0); 1590 1591 /* 1592 * Fill in known data. 1593 */ 1594 sock->type = kif->kf_sock_type; 1595 sock->proto = kif->kf_sock_protocol; 1596 sock->dom_family = kif->kf_sock_domain; 1597 sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb; 1598 strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname)); 1599 bcopy(&kif->kf_un.kf_sock.kf_sa_local, &sock->sa_local, 1600 kif->kf_un.kf_sock.kf_sa_local.ss_len); 1601 bcopy(&kif->kf_un.kf_sock.kf_sa_peer, &sock->sa_peer, 1602 kif->kf_un.kf_sock.kf_sa_peer.ss_len); 1603 1604 /* 1605 * Protocol specific data. 1606 */ 1607 switch(sock->dom_family) { 1608 case AF_INET: 1609 case AF_INET6: 1610 if (sock->proto == IPPROTO_TCP) { 1611 sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb; 1612 sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq; 1613 sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq; 1614 } 1615 break; 1616 case AF_UNIX: 1617 if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) { 1618 sock->so_rcv_sb_state = 1619 kif->kf_un.kf_sock.kf_sock_rcv_sb_state; 1620 sock->so_snd_sb_state = 1621 kif->kf_un.kf_sock.kf_sock_snd_sb_state; 1622 sock->unp_conn = 1623 kif->kf_un.kf_sock.kf_sock_unpconn; 1624 sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq; 1625 sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq; 1626 } 1627 break; 1628 default: 1629 break; 1630 } 1631 return (0); 1632 } 1633 1634 /* 1635 * Descriptor flags to filestat translation. 1636 */ 1637 static int 1638 to_filestat_flags(int flags) 1639 { 1640 static struct { 1641 int flag; 1642 int fst_flag; 1643 } fstflags[] = { 1644 { FREAD, PS_FST_FFLAG_READ }, 1645 { FWRITE, PS_FST_FFLAG_WRITE }, 1646 { O_APPEND, PS_FST_FFLAG_APPEND }, 1647 { O_ASYNC, PS_FST_FFLAG_ASYNC }, 1648 { O_CREAT, PS_FST_FFLAG_CREAT }, 1649 { O_DIRECT, PS_FST_FFLAG_DIRECT }, 1650 { O_EXCL, PS_FST_FFLAG_EXCL }, 1651 { O_EXEC, PS_FST_FFLAG_EXEC }, 1652 { O_EXLOCK, PS_FST_FFLAG_EXLOCK }, 1653 { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 1654 { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 1655 { O_SHLOCK, PS_FST_FFLAG_SHLOCK }, 1656 { O_SYNC, PS_FST_FFLAG_SYNC }, 1657 { O_TRUNC, PS_FST_FFLAG_TRUNC } 1658 }; 1659 #define NFSTFLAGS (sizeof(fstflags) / sizeof(*fstflags)) 1660 int fst_flags; 1661 unsigned int i; 1662 1663 fst_flags = 0; 1664 for (i = 0; i < NFSTFLAGS; i++) 1665 if (flags & fstflags[i].flag) 1666 fst_flags |= fstflags[i].fst_flag; 1667 return (fst_flags); 1668 } 1669 1670 /* 1671 * Vnode type to filestate translation. 1672 */ 1673 static int 1674 vntype2psfsttype(int type) 1675 { 1676 static struct { 1677 int vtype; 1678 int fst_vtype; 1679 } vt2fst[] = { 1680 { VBAD, PS_FST_VTYPE_VBAD }, 1681 { VBLK, PS_FST_VTYPE_VBLK }, 1682 { VCHR, PS_FST_VTYPE_VCHR }, 1683 { VDIR, PS_FST_VTYPE_VDIR }, 1684 { VFIFO, PS_FST_VTYPE_VFIFO }, 1685 { VLNK, PS_FST_VTYPE_VLNK }, 1686 { VNON, PS_FST_VTYPE_VNON }, 1687 { VREG, PS_FST_VTYPE_VREG }, 1688 { VSOCK, PS_FST_VTYPE_VSOCK } 1689 }; 1690 #define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst)) 1691 unsigned int i, fst_type; 1692 1693 fst_type = PS_FST_VTYPE_UNKNOWN; 1694 for (i = 0; i < NVFTYPES; i++) { 1695 if (type == vt2fst[i].vtype) { 1696 fst_type = vt2fst[i].fst_vtype; 1697 break; 1698 } 1699 } 1700 return (fst_type); 1701 } 1702 1703 static char * 1704 getmnton(kvm_t *kd, struct mount *m) 1705 { 1706 struct mount mnt; 1707 static struct mtab { 1708 struct mtab *next; 1709 struct mount *m; 1710 char mntonname[MNAMELEN + 1]; 1711 } *mhead = NULL; 1712 struct mtab *mt; 1713 1714 for (mt = mhead; mt != NULL; mt = mt->next) 1715 if (m == mt->m) 1716 return (mt->mntonname); 1717 if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) { 1718 warnx("can't read mount table at %p", (void *)m); 1719 return (NULL); 1720 } 1721 if ((mt = malloc(sizeof (struct mtab))) == NULL) 1722 err(1, NULL); 1723 mt->m = m; 1724 bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); 1725 mt->mntonname[MNAMELEN] = '\0'; 1726 mt->next = mhead; 1727 mhead = mt; 1728 return (mt->mntonname); 1729 } 1730 1731 /* 1732 * Auxiliary structures and functions to get process environment or 1733 * command line arguments. 1734 */ 1735 struct argvec { 1736 char *buf; 1737 size_t bufsize; 1738 char **argv; 1739 size_t argc; 1740 }; 1741 1742 static struct argvec * 1743 argvec_alloc(size_t bufsize) 1744 { 1745 struct argvec *av; 1746 1747 av = malloc(sizeof(*av)); 1748 if (av == NULL) 1749 return (NULL); 1750 av->bufsize = bufsize; 1751 av->buf = malloc(av->bufsize); 1752 if (av->buf == NULL) { 1753 free(av); 1754 return (NULL); 1755 } 1756 av->argc = 32; 1757 av->argv = malloc(sizeof(char *) * av->argc); 1758 if (av->argv == NULL) { 1759 free(av->buf); 1760 free(av); 1761 return (NULL); 1762 } 1763 return av; 1764 } 1765 1766 static void 1767 argvec_free(struct argvec * av) 1768 { 1769 1770 free(av->argv); 1771 free(av->buf); 1772 free(av); 1773 } 1774 1775 static char ** 1776 getargv(struct procstat *procstat, struct kinfo_proc *kp, size_t nchr, int env) 1777 { 1778 int error, name[4], argc, i; 1779 struct argvec *av, **avp; 1780 enum psc_type type; 1781 size_t len; 1782 char *p, **argv; 1783 1784 assert(procstat); 1785 assert(kp); 1786 if (procstat->type == PROCSTAT_KVM) { 1787 warnx("can't use kvm access method"); 1788 return (NULL); 1789 } 1790 if (procstat->type != PROCSTAT_SYSCTL && 1791 procstat->type != PROCSTAT_CORE) { 1792 warnx("unknown access method: %d", procstat->type); 1793 return (NULL); 1794 } 1795 1796 if (nchr == 0 || nchr > ARG_MAX) 1797 nchr = ARG_MAX; 1798 1799 avp = (struct argvec **)(env ? &procstat->argv : &procstat->envv); 1800 av = *avp; 1801 1802 if (av == NULL) 1803 { 1804 av = argvec_alloc(nchr); 1805 if (av == NULL) 1806 { 1807 warn("malloc(%zu)", nchr); 1808 return (NULL); 1809 } 1810 *avp = av; 1811 } else if (av->bufsize < nchr) { 1812 av->buf = reallocf(av->buf, nchr); 1813 if (av->buf == NULL) { 1814 warn("malloc(%zu)", nchr); 1815 return (NULL); 1816 } 1817 } 1818 if (procstat->type == PROCSTAT_SYSCTL) { 1819 name[0] = CTL_KERN; 1820 name[1] = KERN_PROC; 1821 name[2] = env ? KERN_PROC_ENV : KERN_PROC_ARGS; 1822 name[3] = kp->ki_pid; 1823 len = nchr; 1824 error = sysctl(name, nitems(name), av->buf, &len, NULL, 0); 1825 if (error != 0 && errno != ESRCH && errno != EPERM) 1826 warn("sysctl(kern.proc.%s)", env ? "env" : "args"); 1827 if (error != 0 || len == 0) 1828 return (NULL); 1829 } else /* procstat->type == PROCSTAT_CORE */ { 1830 type = env ? PSC_TYPE_ENVV : PSC_TYPE_ARGV; 1831 len = nchr; 1832 if (procstat_core_get(procstat->core, type, av->buf, &len) 1833 == NULL) { 1834 return (NULL); 1835 } 1836 } 1837 1838 argv = av->argv; 1839 argc = av->argc; 1840 i = 0; 1841 for (p = av->buf; p < av->buf + len; p += strlen(p) + 1) { 1842 argv[i++] = p; 1843 if (i < argc) 1844 continue; 1845 /* Grow argv. */ 1846 argc += argc; 1847 argv = realloc(argv, sizeof(char *) * argc); 1848 if (argv == NULL) { 1849 warn("malloc(%zu)", sizeof(char *) * argc); 1850 return (NULL); 1851 } 1852 av->argv = argv; 1853 av->argc = argc; 1854 } 1855 argv[i] = NULL; 1856 1857 return (argv); 1858 } 1859 1860 /* 1861 * Return process command line arguments. 1862 */ 1863 char ** 1864 procstat_getargv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr) 1865 { 1866 1867 return (getargv(procstat, p, nchr, 0)); 1868 } 1869 1870 /* 1871 * Free the buffer allocated by procstat_getargv(). 1872 */ 1873 void 1874 procstat_freeargv(struct procstat *procstat) 1875 { 1876 1877 if (procstat->argv != NULL) { 1878 argvec_free(procstat->argv); 1879 procstat->argv = NULL; 1880 } 1881 } 1882 1883 /* 1884 * Return process environment. 1885 */ 1886 char ** 1887 procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr) 1888 { 1889 1890 return (getargv(procstat, p, nchr, 1)); 1891 } 1892 1893 /* 1894 * Free the buffer allocated by procstat_getenvv(). 1895 */ 1896 void 1897 procstat_freeenvv(struct procstat *procstat) 1898 { 1899 if (procstat->envv != NULL) { 1900 argvec_free(procstat->envv); 1901 procstat->envv = NULL; 1902 } 1903 } 1904 1905 static struct kinfo_vmentry * 1906 kinfo_getvmmap_core(struct procstat_core *core, int *cntp) 1907 { 1908 int cnt; 1909 size_t len; 1910 char *buf, *bp, *eb; 1911 struct kinfo_vmentry *kiv, *kp, *kv; 1912 1913 buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len); 1914 if (buf == NULL) 1915 return (NULL); 1916 1917 /* 1918 * XXXMG: The code below is just copy&past from libutil. 1919 * The code duplication can be avoided if libutil 1920 * is extended to provide something like: 1921 * struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf, 1922 * size_t len, int *cntp); 1923 */ 1924 1925 /* Pass 1: count items */ 1926 cnt = 0; 1927 bp = buf; 1928 eb = buf + len; 1929 while (bp < eb) { 1930 kv = (struct kinfo_vmentry *)(uintptr_t)bp; 1931 if (kv->kve_structsize == 0) 1932 break; 1933 bp += kv->kve_structsize; 1934 cnt++; 1935 } 1936 1937 kiv = calloc(cnt, sizeof(*kiv)); 1938 if (kiv == NULL) { 1939 free(buf); 1940 return (NULL); 1941 } 1942 bp = buf; 1943 eb = buf + len; 1944 kp = kiv; 1945 /* Pass 2: unpack */ 1946 while (bp < eb) { 1947 kv = (struct kinfo_vmentry *)(uintptr_t)bp; 1948 if (kv->kve_structsize == 0) 1949 break; 1950 /* Copy/expand into pre-zeroed buffer */ 1951 memcpy(kp, kv, kv->kve_structsize); 1952 /* Advance to next packed record */ 1953 bp += kv->kve_structsize; 1954 /* Set field size to fixed length, advance */ 1955 kp->kve_structsize = sizeof(*kp); 1956 kp++; 1957 } 1958 free(buf); 1959 *cntp = cnt; 1960 return (kiv); /* Caller must free() return value */ 1961 } 1962 1963 struct kinfo_vmentry * 1964 procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp, 1965 unsigned int *cntp) 1966 { 1967 1968 switch(procstat->type) { 1969 case PROCSTAT_KVM: 1970 warnx("kvm method is not supported"); 1971 return (NULL); 1972 case PROCSTAT_SYSCTL: 1973 return (kinfo_getvmmap(kp->ki_pid, cntp)); 1974 case PROCSTAT_CORE: 1975 return (kinfo_getvmmap_core(procstat->core, cntp)); 1976 default: 1977 warnx("unknown access method: %d", procstat->type); 1978 return (NULL); 1979 } 1980 } 1981 1982 void 1983 procstat_freevmmap(struct procstat *procstat __unused, 1984 struct kinfo_vmentry *vmmap) 1985 { 1986 1987 free(vmmap); 1988 } 1989 1990 static gid_t * 1991 procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp) 1992 { 1993 struct proc proc; 1994 struct ucred ucred; 1995 gid_t *groups; 1996 size_t len; 1997 1998 assert(kd != NULL); 1999 assert(kp != NULL); 2000 if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 2001 sizeof(proc))) { 2002 warnx("can't read proc struct at %p for pid %d", 2003 kp->ki_paddr, kp->ki_pid); 2004 return (NULL); 2005 } 2006 if (proc.p_ucred == NOCRED) 2007 return (NULL); 2008 if (!kvm_read_all(kd, (unsigned long)proc.p_ucred, &ucred, 2009 sizeof(ucred))) { 2010 warnx("can't read ucred struct at %p for pid %d", 2011 proc.p_ucred, kp->ki_pid); 2012 return (NULL); 2013 } 2014 len = ucred.cr_ngroups * sizeof(gid_t); 2015 groups = malloc(len); 2016 if (groups == NULL) { 2017 warn("malloc(%zu)", len); 2018 return (NULL); 2019 } 2020 if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) { 2021 warnx("can't read groups at %p for pid %d", 2022 ucred.cr_groups, kp->ki_pid); 2023 free(groups); 2024 return (NULL); 2025 } 2026 *cntp = ucred.cr_ngroups; 2027 return (groups); 2028 } 2029 2030 static gid_t * 2031 procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp) 2032 { 2033 int mib[4]; 2034 size_t len; 2035 gid_t *groups; 2036 2037 mib[0] = CTL_KERN; 2038 mib[1] = KERN_PROC; 2039 mib[2] = KERN_PROC_GROUPS; 2040 mib[3] = pid; 2041 len = (sysconf(_SC_NGROUPS_MAX) + 1) * sizeof(gid_t); 2042 groups = malloc(len); 2043 if (groups == NULL) { 2044 warn("malloc(%zu)", len); 2045 return (NULL); 2046 } 2047 if (sysctl(mib, nitems(mib), groups, &len, NULL, 0) == -1) { 2048 warn("sysctl: kern.proc.groups: %d", pid); 2049 free(groups); 2050 return (NULL); 2051 } 2052 *cntp = len / sizeof(gid_t); 2053 return (groups); 2054 } 2055 2056 static gid_t * 2057 procstat_getgroups_core(struct procstat_core *core, unsigned int *cntp) 2058 { 2059 size_t len; 2060 gid_t *groups; 2061 2062 groups = procstat_core_get(core, PSC_TYPE_GROUPS, NULL, &len); 2063 if (groups == NULL) 2064 return (NULL); 2065 *cntp = len / sizeof(gid_t); 2066 return (groups); 2067 } 2068 2069 gid_t * 2070 procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp, 2071 unsigned int *cntp) 2072 { 2073 switch(procstat->type) { 2074 case PROCSTAT_KVM: 2075 return (procstat_getgroups_kvm(procstat->kd, kp, cntp)); 2076 case PROCSTAT_SYSCTL: 2077 return (procstat_getgroups_sysctl(kp->ki_pid, cntp)); 2078 case PROCSTAT_CORE: 2079 return (procstat_getgroups_core(procstat->core, cntp)); 2080 default: 2081 warnx("unknown access method: %d", procstat->type); 2082 return (NULL); 2083 } 2084 } 2085 2086 void 2087 procstat_freegroups(struct procstat *procstat __unused, gid_t *groups) 2088 { 2089 2090 free(groups); 2091 } 2092 2093 static int 2094 procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp) 2095 { 2096 struct pwddesc pd; 2097 2098 assert(kd != NULL); 2099 assert(kp != NULL); 2100 if (kp->ki_pd == NULL) 2101 return (-1); 2102 if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pd, sizeof(pd))) { 2103 warnx("can't read pwddesc at %p for pid %d", kp->ki_pd, 2104 kp->ki_pid); 2105 return (-1); 2106 } 2107 *maskp = pd.pd_cmask; 2108 return (0); 2109 } 2110 2111 static int 2112 procstat_getumask_sysctl(pid_t pid, unsigned short *maskp) 2113 { 2114 int error; 2115 int mib[4]; 2116 size_t len; 2117 2118 mib[0] = CTL_KERN; 2119 mib[1] = KERN_PROC; 2120 mib[2] = KERN_PROC_UMASK; 2121 mib[3] = pid; 2122 len = sizeof(*maskp); 2123 error = sysctl(mib, nitems(mib), maskp, &len, NULL, 0); 2124 if (error != 0 && errno != ESRCH && errno != EPERM) 2125 warn("sysctl: kern.proc.umask: %d", pid); 2126 return (error); 2127 } 2128 2129 static int 2130 procstat_getumask_core(struct procstat_core *core, unsigned short *maskp) 2131 { 2132 size_t len; 2133 unsigned short *buf; 2134 2135 buf = procstat_core_get(core, PSC_TYPE_UMASK, NULL, &len); 2136 if (buf == NULL) 2137 return (-1); 2138 if (len < sizeof(*maskp)) { 2139 free(buf); 2140 return (-1); 2141 } 2142 *maskp = *buf; 2143 free(buf); 2144 return (0); 2145 } 2146 2147 int 2148 procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp, 2149 unsigned short *maskp) 2150 { 2151 switch(procstat->type) { 2152 case PROCSTAT_KVM: 2153 return (procstat_getumask_kvm(procstat->kd, kp, maskp)); 2154 case PROCSTAT_SYSCTL: 2155 return (procstat_getumask_sysctl(kp->ki_pid, maskp)); 2156 case PROCSTAT_CORE: 2157 return (procstat_getumask_core(procstat->core, maskp)); 2158 default: 2159 warnx("unknown access method: %d", procstat->type); 2160 return (-1); 2161 } 2162 } 2163 2164 static int 2165 procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, int which, 2166 struct rlimit* rlimit) 2167 { 2168 struct proc proc; 2169 unsigned long offset; 2170 2171 assert(kd != NULL); 2172 assert(kp != NULL); 2173 assert(which >= 0 && which < RLIM_NLIMITS); 2174 if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 2175 sizeof(proc))) { 2176 warnx("can't read proc struct at %p for pid %d", 2177 kp->ki_paddr, kp->ki_pid); 2178 return (-1); 2179 } 2180 if (proc.p_limit == NULL) 2181 return (-1); 2182 offset = (unsigned long)proc.p_limit + sizeof(struct rlimit) * which; 2183 if (!kvm_read_all(kd, offset, rlimit, sizeof(*rlimit))) { 2184 warnx("can't read rlimit struct at %p for pid %d", 2185 (void *)offset, kp->ki_pid); 2186 return (-1); 2187 } 2188 return (0); 2189 } 2190 2191 static int 2192 procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit) 2193 { 2194 int error, name[5]; 2195 size_t len; 2196 2197 name[0] = CTL_KERN; 2198 name[1] = KERN_PROC; 2199 name[2] = KERN_PROC_RLIMIT; 2200 name[3] = pid; 2201 name[4] = which; 2202 len = sizeof(struct rlimit); 2203 error = sysctl(name, nitems(name), rlimit, &len, NULL, 0); 2204 if (error < 0 && errno != ESRCH) { 2205 warn("sysctl: kern.proc.rlimit: %d", pid); 2206 return (-1); 2207 } 2208 if (error < 0 || len != sizeof(struct rlimit)) 2209 return (-1); 2210 return (0); 2211 } 2212 2213 static int 2214 procstat_getrlimit_core(struct procstat_core *core, int which, 2215 struct rlimit* rlimit) 2216 { 2217 size_t len; 2218 struct rlimit* rlimits; 2219 2220 if (which < 0 || which >= RLIM_NLIMITS) { 2221 errno = EINVAL; 2222 warn("getrlimit: which"); 2223 return (-1); 2224 } 2225 rlimits = procstat_core_get(core, PSC_TYPE_RLIMIT, NULL, &len); 2226 if (rlimits == NULL) 2227 return (-1); 2228 if (len < sizeof(struct rlimit) * RLIM_NLIMITS) { 2229 free(rlimits); 2230 return (-1); 2231 } 2232 *rlimit = rlimits[which]; 2233 free(rlimits); 2234 return (0); 2235 } 2236 2237 int 2238 procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, int which, 2239 struct rlimit* rlimit) 2240 { 2241 switch(procstat->type) { 2242 case PROCSTAT_KVM: 2243 return (procstat_getrlimit_kvm(procstat->kd, kp, which, 2244 rlimit)); 2245 case PROCSTAT_SYSCTL: 2246 return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit)); 2247 case PROCSTAT_CORE: 2248 return (procstat_getrlimit_core(procstat->core, which, rlimit)); 2249 default: 2250 warnx("unknown access method: %d", procstat->type); 2251 return (-1); 2252 } 2253 } 2254 2255 static int 2256 procstat_getpathname_sysctl(pid_t pid, char *pathname, size_t maxlen) 2257 { 2258 int error, name[4]; 2259 size_t len; 2260 2261 name[0] = CTL_KERN; 2262 name[1] = KERN_PROC; 2263 name[2] = KERN_PROC_PATHNAME; 2264 name[3] = pid; 2265 len = maxlen; 2266 error = sysctl(name, nitems(name), pathname, &len, NULL, 0); 2267 if (error != 0 && errno != ESRCH) 2268 warn("sysctl: kern.proc.pathname: %d", pid); 2269 if (len == 0) 2270 pathname[0] = '\0'; 2271 return (error); 2272 } 2273 2274 static int 2275 procstat_getpathname_core(struct procstat_core *core, char *pathname, 2276 size_t maxlen) 2277 { 2278 struct kinfo_file *files; 2279 int cnt, i, result; 2280 2281 files = kinfo_getfile_core(core, &cnt); 2282 if (files == NULL) 2283 return (-1); 2284 result = -1; 2285 for (i = 0; i < cnt; i++) { 2286 if (files[i].kf_fd != KF_FD_TYPE_TEXT) 2287 continue; 2288 strncpy(pathname, files[i].kf_path, maxlen); 2289 result = 0; 2290 break; 2291 } 2292 free(files); 2293 return (result); 2294 } 2295 2296 int 2297 procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp, 2298 char *pathname, size_t maxlen) 2299 { 2300 switch(procstat->type) { 2301 case PROCSTAT_KVM: 2302 /* XXX: Return empty string. */ 2303 if (maxlen > 0) 2304 pathname[0] = '\0'; 2305 return (0); 2306 case PROCSTAT_SYSCTL: 2307 return (procstat_getpathname_sysctl(kp->ki_pid, pathname, 2308 maxlen)); 2309 case PROCSTAT_CORE: 2310 return (procstat_getpathname_core(procstat->core, pathname, 2311 maxlen)); 2312 default: 2313 warnx("unknown access method: %d", procstat->type); 2314 return (-1); 2315 } 2316 } 2317 2318 static int 2319 procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, int *osrelp) 2320 { 2321 struct proc proc; 2322 2323 assert(kd != NULL); 2324 assert(kp != NULL); 2325 if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 2326 sizeof(proc))) { 2327 warnx("can't read proc struct at %p for pid %d", 2328 kp->ki_paddr, kp->ki_pid); 2329 return (-1); 2330 } 2331 *osrelp = proc.p_osrel; 2332 return (0); 2333 } 2334 2335 static int 2336 procstat_getosrel_sysctl(pid_t pid, int *osrelp) 2337 { 2338 int error, name[4]; 2339 size_t len; 2340 2341 name[0] = CTL_KERN; 2342 name[1] = KERN_PROC; 2343 name[2] = KERN_PROC_OSREL; 2344 name[3] = pid; 2345 len = sizeof(*osrelp); 2346 error = sysctl(name, nitems(name), osrelp, &len, NULL, 0); 2347 if (error != 0 && errno != ESRCH) 2348 warn("sysctl: kern.proc.osrel: %d", pid); 2349 return (error); 2350 } 2351 2352 static int 2353 procstat_getosrel_core(struct procstat_core *core, int *osrelp) 2354 { 2355 size_t len; 2356 int *buf; 2357 2358 buf = procstat_core_get(core, PSC_TYPE_OSREL, NULL, &len); 2359 if (buf == NULL) 2360 return (-1); 2361 if (len < sizeof(*osrelp)) { 2362 free(buf); 2363 return (-1); 2364 } 2365 *osrelp = *buf; 2366 free(buf); 2367 return (0); 2368 } 2369 2370 int 2371 procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp, int *osrelp) 2372 { 2373 switch(procstat->type) { 2374 case PROCSTAT_KVM: 2375 return (procstat_getosrel_kvm(procstat->kd, kp, osrelp)); 2376 case PROCSTAT_SYSCTL: 2377 return (procstat_getosrel_sysctl(kp->ki_pid, osrelp)); 2378 case PROCSTAT_CORE: 2379 return (procstat_getosrel_core(procstat->core, osrelp)); 2380 default: 2381 warnx("unknown access method: %d", procstat->type); 2382 return (-1); 2383 } 2384 } 2385 2386 #define PROC_AUXV_MAX 256 2387 2388 #if __ELF_WORD_SIZE == 64 2389 static const char *elf32_sv_names[] = { 2390 "Linux ELF32", 2391 "FreeBSD ELF32", 2392 }; 2393 2394 static int 2395 is_elf32_sysctl(pid_t pid) 2396 { 2397 int error, name[4]; 2398 size_t len, i; 2399 static char sv_name[256]; 2400 2401 name[0] = CTL_KERN; 2402 name[1] = KERN_PROC; 2403 name[2] = KERN_PROC_SV_NAME; 2404 name[3] = pid; 2405 len = sizeof(sv_name); 2406 error = sysctl(name, nitems(name), sv_name, &len, NULL, 0); 2407 if (error != 0 || len == 0) 2408 return (0); 2409 for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) { 2410 if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0) 2411 return (1); 2412 } 2413 return (0); 2414 } 2415 2416 static Elf_Auxinfo * 2417 procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp) 2418 { 2419 Elf_Auxinfo *auxv; 2420 Elf32_Auxinfo *auxv32; 2421 void *ptr; 2422 size_t len; 2423 unsigned int i, count; 2424 int name[4]; 2425 2426 name[0] = CTL_KERN; 2427 name[1] = KERN_PROC; 2428 name[2] = KERN_PROC_AUXV; 2429 name[3] = pid; 2430 len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo); 2431 auxv = NULL; 2432 auxv32 = malloc(len); 2433 if (auxv32 == NULL) { 2434 warn("malloc(%zu)", len); 2435 goto out; 2436 } 2437 if (sysctl(name, nitems(name), auxv32, &len, NULL, 0) == -1) { 2438 if (errno != ESRCH && errno != EPERM) 2439 warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); 2440 goto out; 2441 } 2442 count = len / sizeof(Elf_Auxinfo); 2443 auxv = malloc(count * sizeof(Elf_Auxinfo)); 2444 if (auxv == NULL) { 2445 warn("malloc(%zu)", count * sizeof(Elf_Auxinfo)); 2446 goto out; 2447 } 2448 for (i = 0; i < count; i++) { 2449 /* 2450 * XXX: We expect that values for a_type on a 32-bit platform 2451 * are directly mapped to values on 64-bit one, which is not 2452 * necessarily true. 2453 */ 2454 auxv[i].a_type = auxv32[i].a_type; 2455 ptr = &auxv32[i].a_un; 2456 auxv[i].a_un.a_val = *((uint32_t *)ptr); 2457 } 2458 *cntp = count; 2459 out: 2460 free(auxv32); 2461 return (auxv); 2462 } 2463 #endif /* __ELF_WORD_SIZE == 64 */ 2464 2465 static Elf_Auxinfo * 2466 procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp) 2467 { 2468 Elf_Auxinfo *auxv; 2469 int name[4]; 2470 size_t len; 2471 2472 #if __ELF_WORD_SIZE == 64 2473 if (is_elf32_sysctl(pid)) 2474 return (procstat_getauxv32_sysctl(pid, cntp)); 2475 #endif 2476 name[0] = CTL_KERN; 2477 name[1] = KERN_PROC; 2478 name[2] = KERN_PROC_AUXV; 2479 name[3] = pid; 2480 len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo); 2481 auxv = malloc(len); 2482 if (auxv == NULL) { 2483 warn("malloc(%zu)", len); 2484 return (NULL); 2485 } 2486 if (sysctl(name, nitems(name), auxv, &len, NULL, 0) == -1) { 2487 if (errno != ESRCH && errno != EPERM) 2488 warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); 2489 free(auxv); 2490 return (NULL); 2491 } 2492 *cntp = len / sizeof(Elf_Auxinfo); 2493 return (auxv); 2494 } 2495 2496 static Elf_Auxinfo * 2497 procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp) 2498 { 2499 Elf_Auxinfo *auxv; 2500 size_t len; 2501 2502 auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len); 2503 if (auxv == NULL) 2504 return (NULL); 2505 *cntp = len / sizeof(Elf_Auxinfo); 2506 return (auxv); 2507 } 2508 2509 Elf_Auxinfo * 2510 procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp, 2511 unsigned int *cntp) 2512 { 2513 switch(procstat->type) { 2514 case PROCSTAT_KVM: 2515 warnx("kvm method is not supported"); 2516 return (NULL); 2517 case PROCSTAT_SYSCTL: 2518 return (procstat_getauxv_sysctl(kp->ki_pid, cntp)); 2519 case PROCSTAT_CORE: 2520 return (procstat_getauxv_core(procstat->core, cntp)); 2521 default: 2522 warnx("unknown access method: %d", procstat->type); 2523 return (NULL); 2524 } 2525 } 2526 2527 void 2528 procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv) 2529 { 2530 2531 free(auxv); 2532 } 2533 2534 static struct ptrace_lwpinfo * 2535 procstat_getptlwpinfo_core(struct procstat_core *core, unsigned int *cntp) 2536 { 2537 void *buf; 2538 struct ptrace_lwpinfo *pl; 2539 unsigned int cnt; 2540 size_t len; 2541 2542 cnt = procstat_core_note_count(core, PSC_TYPE_PTLWPINFO); 2543 if (cnt == 0) 2544 return (NULL); 2545 2546 len = cnt * sizeof(*pl); 2547 buf = calloc(1, len); 2548 pl = procstat_core_get(core, PSC_TYPE_PTLWPINFO, buf, &len); 2549 if (pl == NULL) { 2550 free(buf); 2551 return (NULL); 2552 } 2553 *cntp = len / sizeof(*pl); 2554 return (pl); 2555 } 2556 2557 struct ptrace_lwpinfo * 2558 procstat_getptlwpinfo(struct procstat *procstat, unsigned int *cntp) 2559 { 2560 switch (procstat->type) { 2561 case PROCSTAT_KVM: 2562 warnx("kvm method is not supported"); 2563 return (NULL); 2564 case PROCSTAT_SYSCTL: 2565 warnx("sysctl method is not supported"); 2566 return (NULL); 2567 case PROCSTAT_CORE: 2568 return (procstat_getptlwpinfo_core(procstat->core, cntp)); 2569 default: 2570 warnx("unknown access method: %d", procstat->type); 2571 return (NULL); 2572 } 2573 } 2574 2575 void 2576 procstat_freeptlwpinfo(struct procstat *procstat __unused, 2577 struct ptrace_lwpinfo *pl) 2578 { 2579 free(pl); 2580 } 2581 2582 static struct kinfo_kstack * 2583 procstat_getkstack_sysctl(pid_t pid, int *cntp) 2584 { 2585 struct kinfo_kstack *kkstp; 2586 int error, name[4]; 2587 size_t len; 2588 2589 name[0] = CTL_KERN; 2590 name[1] = KERN_PROC; 2591 name[2] = KERN_PROC_KSTACK; 2592 name[3] = pid; 2593 2594 len = 0; 2595 error = sysctl(name, nitems(name), NULL, &len, NULL, 0); 2596 if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) { 2597 warn("sysctl: kern.proc.kstack: %d", pid); 2598 return (NULL); 2599 } 2600 if (error == -1 && errno == ENOENT) { 2601 warnx("sysctl: kern.proc.kstack unavailable" 2602 " (options DDB or options STACK required in kernel)"); 2603 return (NULL); 2604 } 2605 if (error == -1) 2606 return (NULL); 2607 kkstp = malloc(len); 2608 if (kkstp == NULL) { 2609 warn("malloc(%zu)", len); 2610 return (NULL); 2611 } 2612 if (sysctl(name, nitems(name), kkstp, &len, NULL, 0) == -1 && 2613 errno != ENOMEM) { 2614 warn("sysctl: kern.proc.pid: %d", pid); 2615 free(kkstp); 2616 return (NULL); 2617 } 2618 *cntp = len / sizeof(*kkstp); 2619 2620 return (kkstp); 2621 } 2622 2623 struct kinfo_kstack * 2624 procstat_getkstack(struct procstat *procstat, struct kinfo_proc *kp, 2625 unsigned int *cntp) 2626 { 2627 switch(procstat->type) { 2628 case PROCSTAT_KVM: 2629 warnx("kvm method is not supported"); 2630 return (NULL); 2631 case PROCSTAT_SYSCTL: 2632 return (procstat_getkstack_sysctl(kp->ki_pid, cntp)); 2633 case PROCSTAT_CORE: 2634 warnx("core method is not supported"); 2635 return (NULL); 2636 default: 2637 warnx("unknown access method: %d", procstat->type); 2638 return (NULL); 2639 } 2640 } 2641 2642 void 2643 procstat_freekstack(struct procstat *procstat __unused, 2644 struct kinfo_kstack *kkstp) 2645 { 2646 2647 free(kkstp); 2648 } 2649