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 uint64_t fileid; 1341 uint64_t size; 1342 char *name, *path; 1343 uint32_t fsid; 1344 uint16_t mode; 1345 uint32_t rdev; 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 } 1501 } 1502 break; 1503 case AF_UNIX: 1504 if (s.so_pcb) { 1505 if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb, 1506 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 1507 warnx("can't read unpcb at %p", 1508 (void *)s.so_pcb); 1509 } else if (unpcb.unp_conn) { 1510 sock->so_rcv_sb_state = s.so_rcv.sb_state; 1511 sock->so_snd_sb_state = s.so_snd.sb_state; 1512 sock->unp_conn = (uintptr_t)unpcb.unp_conn; 1513 } 1514 } 1515 break; 1516 default: 1517 break; 1518 } 1519 return (0); 1520 1521 fail: 1522 if (errbuf != NULL) 1523 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1524 return (1); 1525 } 1526 1527 static int 1528 procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, 1529 char *errbuf __unused) 1530 { 1531 struct kinfo_file *kif; 1532 1533 assert(sock); 1534 assert(fst); 1535 bzero(sock, sizeof(*sock)); 1536 kif = fst->fs_typedep; 1537 if (kif == NULL) 1538 return (0); 1539 1540 /* 1541 * Fill in known data. 1542 */ 1543 sock->type = kif->kf_sock_type; 1544 sock->proto = kif->kf_sock_protocol; 1545 sock->dom_family = kif->kf_sock_domain; 1546 sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb; 1547 strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname)); 1548 bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len); 1549 bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len); 1550 1551 /* 1552 * Protocol specific data. 1553 */ 1554 switch(sock->dom_family) { 1555 case AF_INET: 1556 case AF_INET6: 1557 if (sock->proto == IPPROTO_TCP) 1558 sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb; 1559 break; 1560 case AF_UNIX: 1561 if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) { 1562 sock->so_rcv_sb_state = 1563 kif->kf_un.kf_sock.kf_sock_rcv_sb_state; 1564 sock->so_snd_sb_state = 1565 kif->kf_un.kf_sock.kf_sock_snd_sb_state; 1566 sock->unp_conn = 1567 kif->kf_un.kf_sock.kf_sock_unpconn; 1568 } 1569 break; 1570 default: 1571 break; 1572 } 1573 return (0); 1574 } 1575 1576 /* 1577 * Descriptor flags to filestat translation. 1578 */ 1579 static int 1580 to_filestat_flags(int flags) 1581 { 1582 static struct { 1583 int flag; 1584 int fst_flag; 1585 } fstflags[] = { 1586 { FREAD, PS_FST_FFLAG_READ }, 1587 { FWRITE, PS_FST_FFLAG_WRITE }, 1588 { O_APPEND, PS_FST_FFLAG_APPEND }, 1589 { O_ASYNC, PS_FST_FFLAG_ASYNC }, 1590 { O_CREAT, PS_FST_FFLAG_CREAT }, 1591 { O_DIRECT, PS_FST_FFLAG_DIRECT }, 1592 { O_EXCL, PS_FST_FFLAG_EXCL }, 1593 { O_EXEC, PS_FST_FFLAG_EXEC }, 1594 { O_EXLOCK, PS_FST_FFLAG_EXLOCK }, 1595 { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 1596 { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 1597 { O_SHLOCK, PS_FST_FFLAG_SHLOCK }, 1598 { O_SYNC, PS_FST_FFLAG_SYNC }, 1599 { O_TRUNC, PS_FST_FFLAG_TRUNC } 1600 }; 1601 #define NFSTFLAGS (sizeof(fstflags) / sizeof(*fstflags)) 1602 int fst_flags; 1603 unsigned int i; 1604 1605 fst_flags = 0; 1606 for (i = 0; i < NFSTFLAGS; i++) 1607 if (flags & fstflags[i].flag) 1608 fst_flags |= fstflags[i].fst_flag; 1609 return (fst_flags); 1610 } 1611 1612 /* 1613 * Vnode type to filestate translation. 1614 */ 1615 static int 1616 vntype2psfsttype(int type) 1617 { 1618 static struct { 1619 int vtype; 1620 int fst_vtype; 1621 } vt2fst[] = { 1622 { VBAD, PS_FST_VTYPE_VBAD }, 1623 { VBLK, PS_FST_VTYPE_VBLK }, 1624 { VCHR, PS_FST_VTYPE_VCHR }, 1625 { VDIR, PS_FST_VTYPE_VDIR }, 1626 { VFIFO, PS_FST_VTYPE_VFIFO }, 1627 { VLNK, PS_FST_VTYPE_VLNK }, 1628 { VNON, PS_FST_VTYPE_VNON }, 1629 { VREG, PS_FST_VTYPE_VREG }, 1630 { VSOCK, PS_FST_VTYPE_VSOCK } 1631 }; 1632 #define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst)) 1633 unsigned int i, fst_type; 1634 1635 fst_type = PS_FST_VTYPE_UNKNOWN; 1636 for (i = 0; i < NVFTYPES; i++) { 1637 if (type == vt2fst[i].vtype) { 1638 fst_type = vt2fst[i].fst_vtype; 1639 break; 1640 } 1641 } 1642 return (fst_type); 1643 } 1644 1645 static char * 1646 getmnton(kvm_t *kd, struct mount *m) 1647 { 1648 struct mount mnt; 1649 static struct mtab { 1650 struct mtab *next; 1651 struct mount *m; 1652 char mntonname[MNAMELEN + 1]; 1653 } *mhead = NULL; 1654 struct mtab *mt; 1655 1656 for (mt = mhead; mt != NULL; mt = mt->next) 1657 if (m == mt->m) 1658 return (mt->mntonname); 1659 if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) { 1660 warnx("can't read mount table at %p", (void *)m); 1661 return (NULL); 1662 } 1663 if ((mt = malloc(sizeof (struct mtab))) == NULL) 1664 err(1, NULL); 1665 mt->m = m; 1666 bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); 1667 mt->mntonname[MNAMELEN] = '\0'; 1668 mt->next = mhead; 1669 mhead = mt; 1670 return (mt->mntonname); 1671 } 1672 1673 /* 1674 * Auxiliary structures and functions to get process environment or 1675 * command line arguments. 1676 */ 1677 struct argvec { 1678 char *buf; 1679 size_t bufsize; 1680 char **argv; 1681 size_t argc; 1682 }; 1683 1684 static struct argvec * 1685 argvec_alloc(size_t bufsize) 1686 { 1687 struct argvec *av; 1688 1689 av = malloc(sizeof(*av)); 1690 if (av == NULL) 1691 return (NULL); 1692 av->bufsize = bufsize; 1693 av->buf = malloc(av->bufsize); 1694 if (av->buf == NULL) { 1695 free(av); 1696 return (NULL); 1697 } 1698 av->argc = 32; 1699 av->argv = malloc(sizeof(char *) * av->argc); 1700 if (av->argv == NULL) { 1701 free(av->buf); 1702 free(av); 1703 return (NULL); 1704 } 1705 return av; 1706 } 1707 1708 static void 1709 argvec_free(struct argvec * av) 1710 { 1711 1712 free(av->argv); 1713 free(av->buf); 1714 free(av); 1715 } 1716 1717 static char ** 1718 getargv(struct procstat *procstat, struct kinfo_proc *kp, size_t nchr, int env) 1719 { 1720 int error, name[4], argc, i; 1721 struct argvec *av, **avp; 1722 enum psc_type type; 1723 size_t len; 1724 char *p, **argv; 1725 1726 assert(procstat); 1727 assert(kp); 1728 if (procstat->type == PROCSTAT_KVM) { 1729 warnx("can't use kvm access method"); 1730 return (NULL); 1731 } 1732 if (procstat->type != PROCSTAT_SYSCTL && 1733 procstat->type != PROCSTAT_CORE) { 1734 warnx("unknown access method: %d", procstat->type); 1735 return (NULL); 1736 } 1737 1738 if (nchr == 0 || nchr > ARG_MAX) 1739 nchr = ARG_MAX; 1740 1741 avp = (struct argvec **)(env ? &procstat->argv : &procstat->envv); 1742 av = *avp; 1743 1744 if (av == NULL) 1745 { 1746 av = argvec_alloc(nchr); 1747 if (av == NULL) 1748 { 1749 warn("malloc(%zu)", nchr); 1750 return (NULL); 1751 } 1752 *avp = av; 1753 } else if (av->bufsize < nchr) { 1754 av->buf = reallocf(av->buf, nchr); 1755 if (av->buf == NULL) { 1756 warn("malloc(%zu)", nchr); 1757 return (NULL); 1758 } 1759 } 1760 if (procstat->type == PROCSTAT_SYSCTL) { 1761 name[0] = CTL_KERN; 1762 name[1] = KERN_PROC; 1763 name[2] = env ? KERN_PROC_ENV : KERN_PROC_ARGS; 1764 name[3] = kp->ki_pid; 1765 len = nchr; 1766 error = sysctl(name, nitems(name), av->buf, &len, NULL, 0); 1767 if (error != 0 && errno != ESRCH && errno != EPERM) 1768 warn("sysctl(kern.proc.%s)", env ? "env" : "args"); 1769 if (error != 0 || len == 0) 1770 return (NULL); 1771 } else /* procstat->type == PROCSTAT_CORE */ { 1772 type = env ? PSC_TYPE_ENVV : PSC_TYPE_ARGV; 1773 len = nchr; 1774 if (procstat_core_get(procstat->core, type, av->buf, &len) 1775 == NULL) { 1776 return (NULL); 1777 } 1778 } 1779 1780 argv = av->argv; 1781 argc = av->argc; 1782 i = 0; 1783 for (p = av->buf; p < av->buf + len; p += strlen(p) + 1) { 1784 argv[i++] = p; 1785 if (i < argc) 1786 continue; 1787 /* Grow argv. */ 1788 argc += argc; 1789 argv = realloc(argv, sizeof(char *) * argc); 1790 if (argv == NULL) { 1791 warn("malloc(%zu)", sizeof(char *) * argc); 1792 return (NULL); 1793 } 1794 av->argv = argv; 1795 av->argc = argc; 1796 } 1797 argv[i] = NULL; 1798 1799 return (argv); 1800 } 1801 1802 /* 1803 * Return process command line arguments. 1804 */ 1805 char ** 1806 procstat_getargv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr) 1807 { 1808 1809 return (getargv(procstat, p, nchr, 0)); 1810 } 1811 1812 /* 1813 * Free the buffer allocated by procstat_getargv(). 1814 */ 1815 void 1816 procstat_freeargv(struct procstat *procstat) 1817 { 1818 1819 if (procstat->argv != NULL) { 1820 argvec_free(procstat->argv); 1821 procstat->argv = NULL; 1822 } 1823 } 1824 1825 /* 1826 * Return process environment. 1827 */ 1828 char ** 1829 procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr) 1830 { 1831 1832 return (getargv(procstat, p, nchr, 1)); 1833 } 1834 1835 /* 1836 * Free the buffer allocated by procstat_getenvv(). 1837 */ 1838 void 1839 procstat_freeenvv(struct procstat *procstat) 1840 { 1841 if (procstat->envv != NULL) { 1842 argvec_free(procstat->envv); 1843 procstat->envv = NULL; 1844 } 1845 } 1846 1847 static struct kinfo_vmentry * 1848 kinfo_getvmmap_core(struct procstat_core *core, int *cntp) 1849 { 1850 int cnt; 1851 size_t len; 1852 char *buf, *bp, *eb; 1853 struct kinfo_vmentry *kiv, *kp, *kv; 1854 1855 buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len); 1856 if (buf == NULL) 1857 return (NULL); 1858 1859 /* 1860 * XXXMG: The code below is just copy&past from libutil. 1861 * The code duplication can be avoided if libutil 1862 * is extended to provide something like: 1863 * struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf, 1864 * size_t len, int *cntp); 1865 */ 1866 1867 /* Pass 1: count items */ 1868 cnt = 0; 1869 bp = buf; 1870 eb = buf + len; 1871 while (bp < eb) { 1872 kv = (struct kinfo_vmentry *)(uintptr_t)bp; 1873 if (kv->kve_structsize == 0) 1874 break; 1875 bp += kv->kve_structsize; 1876 cnt++; 1877 } 1878 1879 kiv = calloc(cnt, sizeof(*kiv)); 1880 if (kiv == NULL) { 1881 free(buf); 1882 return (NULL); 1883 } 1884 bp = buf; 1885 eb = buf + len; 1886 kp = kiv; 1887 /* Pass 2: unpack */ 1888 while (bp < eb) { 1889 kv = (struct kinfo_vmentry *)(uintptr_t)bp; 1890 if (kv->kve_structsize == 0) 1891 break; 1892 /* Copy/expand into pre-zeroed buffer */ 1893 memcpy(kp, kv, kv->kve_structsize); 1894 /* Advance to next packed record */ 1895 bp += kv->kve_structsize; 1896 /* Set field size to fixed length, advance */ 1897 kp->kve_structsize = sizeof(*kp); 1898 kp++; 1899 } 1900 free(buf); 1901 *cntp = cnt; 1902 return (kiv); /* Caller must free() return value */ 1903 } 1904 1905 struct kinfo_vmentry * 1906 procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp, 1907 unsigned int *cntp) 1908 { 1909 1910 switch(procstat->type) { 1911 case PROCSTAT_KVM: 1912 warnx("kvm method is not supported"); 1913 return (NULL); 1914 case PROCSTAT_SYSCTL: 1915 return (kinfo_getvmmap(kp->ki_pid, cntp)); 1916 case PROCSTAT_CORE: 1917 return (kinfo_getvmmap_core(procstat->core, cntp)); 1918 default: 1919 warnx("unknown access method: %d", procstat->type); 1920 return (NULL); 1921 } 1922 } 1923 1924 void 1925 procstat_freevmmap(struct procstat *procstat __unused, 1926 struct kinfo_vmentry *vmmap) 1927 { 1928 1929 free(vmmap); 1930 } 1931 1932 static gid_t * 1933 procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp) 1934 { 1935 struct proc proc; 1936 struct ucred ucred; 1937 gid_t *groups; 1938 size_t len; 1939 1940 assert(kd != NULL); 1941 assert(kp != NULL); 1942 if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 1943 sizeof(proc))) { 1944 warnx("can't read proc struct at %p for pid %d", 1945 kp->ki_paddr, kp->ki_pid); 1946 return (NULL); 1947 } 1948 if (proc.p_ucred == NOCRED) 1949 return (NULL); 1950 if (!kvm_read_all(kd, (unsigned long)proc.p_ucred, &ucred, 1951 sizeof(ucred))) { 1952 warnx("can't read ucred struct at %p for pid %d", 1953 proc.p_ucred, kp->ki_pid); 1954 return (NULL); 1955 } 1956 len = ucred.cr_ngroups * sizeof(gid_t); 1957 groups = malloc(len); 1958 if (groups == NULL) { 1959 warn("malloc(%zu)", len); 1960 return (NULL); 1961 } 1962 if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) { 1963 warnx("can't read groups at %p for pid %d", 1964 ucred.cr_groups, kp->ki_pid); 1965 free(groups); 1966 return (NULL); 1967 } 1968 *cntp = ucred.cr_ngroups; 1969 return (groups); 1970 } 1971 1972 static gid_t * 1973 procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp) 1974 { 1975 int mib[4]; 1976 size_t len; 1977 gid_t *groups; 1978 1979 mib[0] = CTL_KERN; 1980 mib[1] = KERN_PROC; 1981 mib[2] = KERN_PROC_GROUPS; 1982 mib[3] = pid; 1983 len = (sysconf(_SC_NGROUPS_MAX) + 1) * sizeof(gid_t); 1984 groups = malloc(len); 1985 if (groups == NULL) { 1986 warn("malloc(%zu)", len); 1987 return (NULL); 1988 } 1989 if (sysctl(mib, nitems(mib), groups, &len, NULL, 0) == -1) { 1990 warn("sysctl: kern.proc.groups: %d", pid); 1991 free(groups); 1992 return (NULL); 1993 } 1994 *cntp = len / sizeof(gid_t); 1995 return (groups); 1996 } 1997 1998 static gid_t * 1999 procstat_getgroups_core(struct procstat_core *core, unsigned int *cntp) 2000 { 2001 size_t len; 2002 gid_t *groups; 2003 2004 groups = procstat_core_get(core, PSC_TYPE_GROUPS, NULL, &len); 2005 if (groups == NULL) 2006 return (NULL); 2007 *cntp = len / sizeof(gid_t); 2008 return (groups); 2009 } 2010 2011 gid_t * 2012 procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp, 2013 unsigned int *cntp) 2014 { 2015 switch(procstat->type) { 2016 case PROCSTAT_KVM: 2017 return (procstat_getgroups_kvm(procstat->kd, kp, cntp)); 2018 case PROCSTAT_SYSCTL: 2019 return (procstat_getgroups_sysctl(kp->ki_pid, cntp)); 2020 case PROCSTAT_CORE: 2021 return (procstat_getgroups_core(procstat->core, cntp)); 2022 default: 2023 warnx("unknown access method: %d", procstat->type); 2024 return (NULL); 2025 } 2026 } 2027 2028 void 2029 procstat_freegroups(struct procstat *procstat __unused, gid_t *groups) 2030 { 2031 2032 free(groups); 2033 } 2034 2035 static int 2036 procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp) 2037 { 2038 struct filedesc fd; 2039 2040 assert(kd != NULL); 2041 assert(kp != NULL); 2042 if (kp->ki_fd == NULL) 2043 return (-1); 2044 if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &fd, sizeof(fd))) { 2045 warnx("can't read filedesc at %p for pid %d", kp->ki_fd, 2046 kp->ki_pid); 2047 return (-1); 2048 } 2049 *maskp = fd.fd_cmask; 2050 return (0); 2051 } 2052 2053 static int 2054 procstat_getumask_sysctl(pid_t pid, unsigned short *maskp) 2055 { 2056 int error; 2057 int mib[4]; 2058 size_t len; 2059 2060 mib[0] = CTL_KERN; 2061 mib[1] = KERN_PROC; 2062 mib[2] = KERN_PROC_UMASK; 2063 mib[3] = pid; 2064 len = sizeof(*maskp); 2065 error = sysctl(mib, nitems(mib), maskp, &len, NULL, 0); 2066 if (error != 0 && errno != ESRCH && errno != EPERM) 2067 warn("sysctl: kern.proc.umask: %d", pid); 2068 return (error); 2069 } 2070 2071 static int 2072 procstat_getumask_core(struct procstat_core *core, unsigned short *maskp) 2073 { 2074 size_t len; 2075 unsigned short *buf; 2076 2077 buf = procstat_core_get(core, PSC_TYPE_UMASK, NULL, &len); 2078 if (buf == NULL) 2079 return (-1); 2080 if (len < sizeof(*maskp)) { 2081 free(buf); 2082 return (-1); 2083 } 2084 *maskp = *buf; 2085 free(buf); 2086 return (0); 2087 } 2088 2089 int 2090 procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp, 2091 unsigned short *maskp) 2092 { 2093 switch(procstat->type) { 2094 case PROCSTAT_KVM: 2095 return (procstat_getumask_kvm(procstat->kd, kp, maskp)); 2096 case PROCSTAT_SYSCTL: 2097 return (procstat_getumask_sysctl(kp->ki_pid, maskp)); 2098 case PROCSTAT_CORE: 2099 return (procstat_getumask_core(procstat->core, maskp)); 2100 default: 2101 warnx("unknown access method: %d", procstat->type); 2102 return (-1); 2103 } 2104 } 2105 2106 static int 2107 procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, int which, 2108 struct rlimit* rlimit) 2109 { 2110 struct proc proc; 2111 unsigned long offset; 2112 2113 assert(kd != NULL); 2114 assert(kp != NULL); 2115 assert(which >= 0 && which < RLIM_NLIMITS); 2116 if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 2117 sizeof(proc))) { 2118 warnx("can't read proc struct at %p for pid %d", 2119 kp->ki_paddr, kp->ki_pid); 2120 return (-1); 2121 } 2122 if (proc.p_limit == NULL) 2123 return (-1); 2124 offset = (unsigned long)proc.p_limit + sizeof(struct rlimit) * which; 2125 if (!kvm_read_all(kd, offset, rlimit, sizeof(*rlimit))) { 2126 warnx("can't read rlimit struct at %p for pid %d", 2127 (void *)offset, kp->ki_pid); 2128 return (-1); 2129 } 2130 return (0); 2131 } 2132 2133 static int 2134 procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit) 2135 { 2136 int error, name[5]; 2137 size_t len; 2138 2139 name[0] = CTL_KERN; 2140 name[1] = KERN_PROC; 2141 name[2] = KERN_PROC_RLIMIT; 2142 name[3] = pid; 2143 name[4] = which; 2144 len = sizeof(struct rlimit); 2145 error = sysctl(name, nitems(name), rlimit, &len, NULL, 0); 2146 if (error < 0 && errno != ESRCH) { 2147 warn("sysctl: kern.proc.rlimit: %d", pid); 2148 return (-1); 2149 } 2150 if (error < 0 || len != sizeof(struct rlimit)) 2151 return (-1); 2152 return (0); 2153 } 2154 2155 static int 2156 procstat_getrlimit_core(struct procstat_core *core, int which, 2157 struct rlimit* rlimit) 2158 { 2159 size_t len; 2160 struct rlimit* rlimits; 2161 2162 if (which < 0 || which >= RLIM_NLIMITS) { 2163 errno = EINVAL; 2164 warn("getrlimit: which"); 2165 return (-1); 2166 } 2167 rlimits = procstat_core_get(core, PSC_TYPE_RLIMIT, NULL, &len); 2168 if (rlimits == NULL) 2169 return (-1); 2170 if (len < sizeof(struct rlimit) * RLIM_NLIMITS) { 2171 free(rlimits); 2172 return (-1); 2173 } 2174 *rlimit = rlimits[which]; 2175 return (0); 2176 } 2177 2178 int 2179 procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, int which, 2180 struct rlimit* rlimit) 2181 { 2182 switch(procstat->type) { 2183 case PROCSTAT_KVM: 2184 return (procstat_getrlimit_kvm(procstat->kd, kp, which, 2185 rlimit)); 2186 case PROCSTAT_SYSCTL: 2187 return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit)); 2188 case PROCSTAT_CORE: 2189 return (procstat_getrlimit_core(procstat->core, which, rlimit)); 2190 default: 2191 warnx("unknown access method: %d", procstat->type); 2192 return (-1); 2193 } 2194 } 2195 2196 static int 2197 procstat_getpathname_sysctl(pid_t pid, char *pathname, size_t maxlen) 2198 { 2199 int error, name[4]; 2200 size_t len; 2201 2202 name[0] = CTL_KERN; 2203 name[1] = KERN_PROC; 2204 name[2] = KERN_PROC_PATHNAME; 2205 name[3] = pid; 2206 len = maxlen; 2207 error = sysctl(name, nitems(name), pathname, &len, NULL, 0); 2208 if (error != 0 && errno != ESRCH) 2209 warn("sysctl: kern.proc.pathname: %d", pid); 2210 if (len == 0) 2211 pathname[0] = '\0'; 2212 return (error); 2213 } 2214 2215 static int 2216 procstat_getpathname_core(struct procstat_core *core, char *pathname, 2217 size_t maxlen) 2218 { 2219 struct kinfo_file *files; 2220 int cnt, i, result; 2221 2222 files = kinfo_getfile_core(core, &cnt); 2223 if (files == NULL) 2224 return (-1); 2225 result = -1; 2226 for (i = 0; i < cnt; i++) { 2227 if (files[i].kf_fd != KF_FD_TYPE_TEXT) 2228 continue; 2229 strncpy(pathname, files[i].kf_path, maxlen); 2230 result = 0; 2231 break; 2232 } 2233 free(files); 2234 return (result); 2235 } 2236 2237 int 2238 procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp, 2239 char *pathname, size_t maxlen) 2240 { 2241 switch(procstat->type) { 2242 case PROCSTAT_KVM: 2243 /* XXX: Return empty string. */ 2244 if (maxlen > 0) 2245 pathname[0] = '\0'; 2246 return (0); 2247 case PROCSTAT_SYSCTL: 2248 return (procstat_getpathname_sysctl(kp->ki_pid, pathname, 2249 maxlen)); 2250 case PROCSTAT_CORE: 2251 return (procstat_getpathname_core(procstat->core, pathname, 2252 maxlen)); 2253 default: 2254 warnx("unknown access method: %d", procstat->type); 2255 return (-1); 2256 } 2257 } 2258 2259 static int 2260 procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, int *osrelp) 2261 { 2262 struct proc proc; 2263 2264 assert(kd != NULL); 2265 assert(kp != NULL); 2266 if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 2267 sizeof(proc))) { 2268 warnx("can't read proc struct at %p for pid %d", 2269 kp->ki_paddr, kp->ki_pid); 2270 return (-1); 2271 } 2272 *osrelp = proc.p_osrel; 2273 return (0); 2274 } 2275 2276 static int 2277 procstat_getosrel_sysctl(pid_t pid, int *osrelp) 2278 { 2279 int error, name[4]; 2280 size_t len; 2281 2282 name[0] = CTL_KERN; 2283 name[1] = KERN_PROC; 2284 name[2] = KERN_PROC_OSREL; 2285 name[3] = pid; 2286 len = sizeof(*osrelp); 2287 error = sysctl(name, nitems(name), osrelp, &len, NULL, 0); 2288 if (error != 0 && errno != ESRCH) 2289 warn("sysctl: kern.proc.osrel: %d", pid); 2290 return (error); 2291 } 2292 2293 static int 2294 procstat_getosrel_core(struct procstat_core *core, int *osrelp) 2295 { 2296 size_t len; 2297 int *buf; 2298 2299 buf = procstat_core_get(core, PSC_TYPE_OSREL, NULL, &len); 2300 if (buf == NULL) 2301 return (-1); 2302 if (len < sizeof(*osrelp)) { 2303 free(buf); 2304 return (-1); 2305 } 2306 *osrelp = *buf; 2307 free(buf); 2308 return (0); 2309 } 2310 2311 int 2312 procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp, int *osrelp) 2313 { 2314 switch(procstat->type) { 2315 case PROCSTAT_KVM: 2316 return (procstat_getosrel_kvm(procstat->kd, kp, osrelp)); 2317 case PROCSTAT_SYSCTL: 2318 return (procstat_getosrel_sysctl(kp->ki_pid, osrelp)); 2319 case PROCSTAT_CORE: 2320 return (procstat_getosrel_core(procstat->core, osrelp)); 2321 default: 2322 warnx("unknown access method: %d", procstat->type); 2323 return (-1); 2324 } 2325 } 2326 2327 #define PROC_AUXV_MAX 256 2328 2329 #if __ELF_WORD_SIZE == 64 2330 static const char *elf32_sv_names[] = { 2331 "Linux ELF32", 2332 "FreeBSD ELF32", 2333 }; 2334 2335 static int 2336 is_elf32_sysctl(pid_t pid) 2337 { 2338 int error, name[4]; 2339 size_t len, i; 2340 static char sv_name[256]; 2341 2342 name[0] = CTL_KERN; 2343 name[1] = KERN_PROC; 2344 name[2] = KERN_PROC_SV_NAME; 2345 name[3] = pid; 2346 len = sizeof(sv_name); 2347 error = sysctl(name, nitems(name), sv_name, &len, NULL, 0); 2348 if (error != 0 || len == 0) 2349 return (0); 2350 for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) { 2351 if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0) 2352 return (1); 2353 } 2354 return (0); 2355 } 2356 2357 static Elf_Auxinfo * 2358 procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp) 2359 { 2360 Elf_Auxinfo *auxv; 2361 Elf32_Auxinfo *auxv32; 2362 void *ptr; 2363 size_t len; 2364 unsigned int i, count; 2365 int name[4]; 2366 2367 name[0] = CTL_KERN; 2368 name[1] = KERN_PROC; 2369 name[2] = KERN_PROC_AUXV; 2370 name[3] = pid; 2371 len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo); 2372 auxv = NULL; 2373 auxv32 = malloc(len); 2374 if (auxv32 == NULL) { 2375 warn("malloc(%zu)", len); 2376 goto out; 2377 } 2378 if (sysctl(name, nitems(name), auxv32, &len, NULL, 0) == -1) { 2379 if (errno != ESRCH && errno != EPERM) 2380 warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); 2381 goto out; 2382 } 2383 count = len / sizeof(Elf_Auxinfo); 2384 auxv = malloc(count * sizeof(Elf_Auxinfo)); 2385 if (auxv == NULL) { 2386 warn("malloc(%zu)", count * sizeof(Elf_Auxinfo)); 2387 goto out; 2388 } 2389 for (i = 0; i < count; i++) { 2390 /* 2391 * XXX: We expect that values for a_type on a 32-bit platform 2392 * are directly mapped to values on 64-bit one, which is not 2393 * necessarily true. 2394 */ 2395 auxv[i].a_type = auxv32[i].a_type; 2396 ptr = &auxv32[i].a_un; 2397 auxv[i].a_un.a_val = *((uint32_t *)ptr); 2398 } 2399 *cntp = count; 2400 out: 2401 free(auxv32); 2402 return (auxv); 2403 } 2404 #endif /* __ELF_WORD_SIZE == 64 */ 2405 2406 static Elf_Auxinfo * 2407 procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp) 2408 { 2409 Elf_Auxinfo *auxv; 2410 int name[4]; 2411 size_t len; 2412 2413 #if __ELF_WORD_SIZE == 64 2414 if (is_elf32_sysctl(pid)) 2415 return (procstat_getauxv32_sysctl(pid, cntp)); 2416 #endif 2417 name[0] = CTL_KERN; 2418 name[1] = KERN_PROC; 2419 name[2] = KERN_PROC_AUXV; 2420 name[3] = pid; 2421 len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo); 2422 auxv = malloc(len); 2423 if (auxv == NULL) { 2424 warn("malloc(%zu)", len); 2425 return (NULL); 2426 } 2427 if (sysctl(name, nitems(name), auxv, &len, NULL, 0) == -1) { 2428 if (errno != ESRCH && errno != EPERM) 2429 warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); 2430 free(auxv); 2431 return (NULL); 2432 } 2433 *cntp = len / sizeof(Elf_Auxinfo); 2434 return (auxv); 2435 } 2436 2437 static Elf_Auxinfo * 2438 procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp) 2439 { 2440 Elf_Auxinfo *auxv; 2441 size_t len; 2442 2443 auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len); 2444 if (auxv == NULL) 2445 return (NULL); 2446 *cntp = len / sizeof(Elf_Auxinfo); 2447 return (auxv); 2448 } 2449 2450 Elf_Auxinfo * 2451 procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp, 2452 unsigned int *cntp) 2453 { 2454 switch(procstat->type) { 2455 case PROCSTAT_KVM: 2456 warnx("kvm method is not supported"); 2457 return (NULL); 2458 case PROCSTAT_SYSCTL: 2459 return (procstat_getauxv_sysctl(kp->ki_pid, cntp)); 2460 case PROCSTAT_CORE: 2461 return (procstat_getauxv_core(procstat->core, cntp)); 2462 default: 2463 warnx("unknown access method: %d", procstat->type); 2464 return (NULL); 2465 } 2466 } 2467 2468 void 2469 procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv) 2470 { 2471 2472 free(auxv); 2473 } 2474 2475 static struct ptrace_lwpinfo * 2476 procstat_getptlwpinfo_core(struct procstat_core *core, unsigned int *cntp) 2477 { 2478 void *buf; 2479 struct ptrace_lwpinfo *pl; 2480 unsigned int cnt; 2481 size_t len; 2482 2483 cnt = procstat_core_note_count(core, PSC_TYPE_PTLWPINFO); 2484 if (cnt == 0) 2485 return (NULL); 2486 2487 len = cnt * sizeof(*pl); 2488 buf = calloc(1, len); 2489 pl = procstat_core_get(core, PSC_TYPE_PTLWPINFO, buf, &len); 2490 if (pl == NULL) { 2491 free(buf); 2492 return (NULL); 2493 } 2494 *cntp = len / sizeof(*pl); 2495 return (pl); 2496 } 2497 2498 struct ptrace_lwpinfo * 2499 procstat_getptlwpinfo(struct procstat *procstat, unsigned int *cntp) 2500 { 2501 switch (procstat->type) { 2502 case PROCSTAT_CORE: 2503 return (procstat_getptlwpinfo_core(procstat->core, cntp)); 2504 default: 2505 warnx("unknown access method: %d", procstat->type); 2506 return (NULL); 2507 } 2508 } 2509 2510 void 2511 procstat_freeptlwpinfo(struct procstat *procstat __unused, 2512 struct ptrace_lwpinfo *pl) 2513 { 2514 free(pl); 2515 } 2516 2517 static struct kinfo_kstack * 2518 procstat_getkstack_sysctl(pid_t pid, int *cntp) 2519 { 2520 struct kinfo_kstack *kkstp; 2521 int error, name[4]; 2522 size_t len; 2523 2524 name[0] = CTL_KERN; 2525 name[1] = KERN_PROC; 2526 name[2] = KERN_PROC_KSTACK; 2527 name[3] = pid; 2528 2529 len = 0; 2530 error = sysctl(name, nitems(name), NULL, &len, NULL, 0); 2531 if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) { 2532 warn("sysctl: kern.proc.kstack: %d", pid); 2533 return (NULL); 2534 } 2535 if (error == -1 && errno == ENOENT) { 2536 warnx("sysctl: kern.proc.kstack unavailable" 2537 " (options DDB or options STACK required in kernel)"); 2538 return (NULL); 2539 } 2540 if (error == -1) 2541 return (NULL); 2542 kkstp = malloc(len); 2543 if (kkstp == NULL) { 2544 warn("malloc(%zu)", len); 2545 return (NULL); 2546 } 2547 if (sysctl(name, nitems(name), kkstp, &len, NULL, 0) == -1) { 2548 warn("sysctl: kern.proc.pid: %d", pid); 2549 free(kkstp); 2550 return (NULL); 2551 } 2552 *cntp = len / sizeof(*kkstp); 2553 2554 return (kkstp); 2555 } 2556 2557 struct kinfo_kstack * 2558 procstat_getkstack(struct procstat *procstat, struct kinfo_proc *kp, 2559 unsigned int *cntp) 2560 { 2561 switch(procstat->type) { 2562 case PROCSTAT_KVM: 2563 warnx("kvm method is not supported"); 2564 return (NULL); 2565 case PROCSTAT_SYSCTL: 2566 return (procstat_getkstack_sysctl(kp->ki_pid, cntp)); 2567 case PROCSTAT_CORE: 2568 warnx("core method is not supported"); 2569 return (NULL); 2570 default: 2571 warnx("unknown access method: %d", procstat->type); 2572 return (NULL); 2573 } 2574 } 2575 2576 void 2577 procstat_freekstack(struct procstat *procstat __unused, 2578 struct kinfo_kstack *kkstp) 2579 { 2580 2581 free(kkstp); 2582 } 2583