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