1 /*- 2 * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org> 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include <sys/param.h> 39 #include <sys/time.h> 40 #include <sys/proc.h> 41 #include <sys/user.h> 42 #include <sys/stat.h> 43 #include <sys/vnode.h> 44 #include <sys/socket.h> 45 #include <sys/socketvar.h> 46 #include <sys/domain.h> 47 #include <sys/protosw.h> 48 #include <sys/un.h> 49 #include <sys/unpcb.h> 50 #include <sys/sysctl.h> 51 #include <sys/tty.h> 52 #include <sys/filedesc.h> 53 #include <sys/queue.h> 54 #define _WANT_FILE 55 #include <sys/file.h> 56 #include <sys/conf.h> 57 #include <sys/mman.h> 58 #define _KERNEL 59 #include <sys/mount.h> 60 #include <sys/pipe.h> 61 #include <ufs/ufs/quota.h> 62 #include <ufs/ufs/inode.h> 63 #include <fs/devfs/devfs.h> 64 #include <fs/devfs/devfs_int.h> 65 #undef _KERNEL 66 #include <nfs/nfsproto.h> 67 #include <nfsclient/nfs.h> 68 #include <nfsclient/nfsnode.h> 69 70 #include <vm/vm.h> 71 #include <vm/vm_map.h> 72 #include <vm/vm_object.h> 73 74 #include <net/route.h> 75 #include <netinet/in.h> 76 #include <netinet/in_systm.h> 77 #include <netinet/ip.h> 78 #include <netinet/in_pcb.h> 79 80 #include <assert.h> 81 #include <ctype.h> 82 #include <err.h> 83 #include <fcntl.h> 84 #include <kvm.h> 85 #include <libutil.h> 86 #include <limits.h> 87 #include <paths.h> 88 #include <pwd.h> 89 #include <stdio.h> 90 #include <stdlib.h> 91 #include <stddef.h> 92 #include <string.h> 93 #include <unistd.h> 94 #include <netdb.h> 95 96 #include <libprocstat.h> 97 #include "libprocstat_internal.h" 98 #include "common_kvm.h" 99 #include "core.h" 100 101 int statfs(const char *, struct statfs *); /* XXX */ 102 103 #define PROCSTAT_KVM 1 104 #define PROCSTAT_SYSCTL 2 105 #define PROCSTAT_CORE 3 106 107 static char *getmnton(kvm_t *kd, struct mount *m); 108 static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core, 109 int *cntp); 110 static struct filestat_list *procstat_getfiles_kvm( 111 struct procstat *procstat, struct kinfo_proc *kp, int mmapped); 112 static struct filestat_list *procstat_getfiles_sysctl( 113 struct procstat *procstat, struct kinfo_proc *kp, int mmapped); 114 static int procstat_get_pipe_info_sysctl(struct filestat *fst, 115 struct pipestat *pipe, char *errbuf); 116 static int procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, 117 struct pipestat *pipe, char *errbuf); 118 static int procstat_get_pts_info_sysctl(struct filestat *fst, 119 struct ptsstat *pts, char *errbuf); 120 static int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, 121 struct ptsstat *pts, char *errbuf); 122 static int procstat_get_shm_info_sysctl(struct filestat *fst, 123 struct shmstat *shm, char *errbuf); 124 static int procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst, 125 struct shmstat *shm, char *errbuf); 126 static int procstat_get_socket_info_sysctl(struct filestat *fst, 127 struct sockstat *sock, char *errbuf); 128 static int procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, 129 struct sockstat *sock, char *errbuf); 130 static int to_filestat_flags(int flags); 131 static int procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, 132 struct vnstat *vn, char *errbuf); 133 static int procstat_get_vnode_info_sysctl(struct filestat *fst, 134 struct vnstat *vn, char *errbuf); 135 static gid_t *procstat_getgroups_core(struct procstat_core *core, 136 unsigned int *count); 137 static gid_t *procstat_getgroups_sysctl(pid_t pid, unsigned int *count); 138 static int vntype2psfsttype(int type); 139 140 void 141 procstat_close(struct procstat *procstat) 142 { 143 144 assert(procstat); 145 if (procstat->type == PROCSTAT_KVM) 146 kvm_close(procstat->kd); 147 else if (procstat->type == PROCSTAT_CORE) 148 procstat_core_close(procstat->core); 149 free(procstat); 150 } 151 152 struct procstat * 153 procstat_open_sysctl(void) 154 { 155 struct procstat *procstat; 156 157 procstat = calloc(1, sizeof(*procstat)); 158 if (procstat == NULL) { 159 warn("malloc()"); 160 return (NULL); 161 } 162 procstat->type = PROCSTAT_SYSCTL; 163 return (procstat); 164 } 165 166 struct procstat * 167 procstat_open_kvm(const char *nlistf, const char *memf) 168 { 169 struct procstat *procstat; 170 kvm_t *kd; 171 char buf[_POSIX2_LINE_MAX]; 172 173 procstat = calloc(1, sizeof(*procstat)); 174 if (procstat == NULL) { 175 warn("malloc()"); 176 return (NULL); 177 } 178 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 179 if (kd == NULL) { 180 warnx("kvm_openfiles(): %s", buf); 181 free(procstat); 182 return (NULL); 183 } 184 procstat->type = PROCSTAT_KVM; 185 procstat->kd = kd; 186 return (procstat); 187 } 188 189 struct procstat * 190 procstat_open_core(const char *filename) 191 { 192 struct procstat *procstat; 193 struct procstat_core *core; 194 195 procstat = calloc(1, sizeof(*procstat)); 196 if (procstat == NULL) { 197 warn("malloc()"); 198 return (NULL); 199 } 200 core = procstat_core_open(filename); 201 if (core == NULL) { 202 free(procstat); 203 return (NULL); 204 } 205 procstat->type = PROCSTAT_CORE; 206 procstat->core = core; 207 return (procstat); 208 } 209 210 struct kinfo_proc * 211 procstat_getprocs(struct procstat *procstat, int what, int arg, 212 unsigned int *count) 213 { 214 struct kinfo_proc *p0, *p; 215 size_t len; 216 int name[4]; 217 int cnt; 218 int error; 219 220 assert(procstat); 221 assert(count); 222 p = NULL; 223 if (procstat->type == PROCSTAT_KVM) { 224 *count = 0; 225 p0 = kvm_getprocs(procstat->kd, what, arg, &cnt); 226 if (p0 == NULL || cnt <= 0) 227 return (NULL); 228 *count = cnt; 229 len = *count * sizeof(*p); 230 p = malloc(len); 231 if (p == NULL) { 232 warnx("malloc(%zu)", len); 233 goto fail; 234 } 235 bcopy(p0, p, len); 236 return (p); 237 } else if (procstat->type == PROCSTAT_SYSCTL) { 238 len = 0; 239 name[0] = CTL_KERN; 240 name[1] = KERN_PROC; 241 name[2] = what; 242 name[3] = arg; 243 error = sysctl(name, 4, NULL, &len, NULL, 0); 244 if (error < 0 && errno != EPERM) { 245 warn("sysctl(kern.proc)"); 246 goto fail; 247 } 248 if (len == 0) { 249 warnx("no processes?"); 250 goto fail; 251 } 252 p = malloc(len); 253 if (p == NULL) { 254 warnx("malloc(%zu)", len); 255 goto fail; 256 } 257 error = sysctl(name, 4, p, &len, NULL, 0); 258 if (error < 0 && errno != EPERM) { 259 warn("sysctl(kern.proc)"); 260 goto fail; 261 } 262 /* Perform simple consistency checks. */ 263 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) { 264 warnx("kinfo_proc structure size mismatch (len = %zu)", len); 265 goto fail; 266 } 267 *count = len / sizeof(*p); 268 return (p); 269 } else if (procstat->type == PROCSTAT_CORE) { 270 p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL, 271 &len); 272 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) { 273 warnx("kinfo_proc structure size mismatch"); 274 goto fail; 275 } 276 *count = len / sizeof(*p); 277 return (p); 278 } else { 279 warnx("unknown access method: %d", procstat->type); 280 return (NULL); 281 } 282 fail: 283 if (p) 284 free(p); 285 return (NULL); 286 } 287 288 void 289 procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p) 290 { 291 292 if (p != NULL) 293 free(p); 294 p = NULL; 295 } 296 297 struct filestat_list * 298 procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 299 { 300 301 switch(procstat->type) { 302 case PROCSTAT_KVM: 303 return (procstat_getfiles_kvm(procstat, kp, mmapped)); 304 case PROCSTAT_SYSCTL: 305 case PROCSTAT_CORE: 306 return (procstat_getfiles_sysctl(procstat, kp, mmapped)); 307 default: 308 warnx("unknown access method: %d", procstat->type); 309 return (NULL); 310 } 311 } 312 313 void 314 procstat_freefiles(struct procstat *procstat, struct filestat_list *head) 315 { 316 struct filestat *fst, *tmp; 317 318 STAILQ_FOREACH_SAFE(fst, head, next, tmp) { 319 if (fst->fs_path != NULL) 320 free(fst->fs_path); 321 free(fst); 322 } 323 free(head); 324 if (procstat->vmentries != NULL) { 325 free(procstat->vmentries); 326 procstat->vmentries = NULL; 327 } 328 if (procstat->files != NULL) { 329 free(procstat->files); 330 procstat->files = NULL; 331 } 332 } 333 334 static struct filestat * 335 filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags, 336 int refcount, off_t offset, char *path, cap_rights_t cap_rights) 337 { 338 struct filestat *entry; 339 340 entry = calloc(1, sizeof(*entry)); 341 if (entry == NULL) { 342 warn("malloc()"); 343 return (NULL); 344 } 345 entry->fs_typedep = typedep; 346 entry->fs_fflags = fflags; 347 entry->fs_uflags = uflags; 348 entry->fs_fd = fd; 349 entry->fs_type = type; 350 entry->fs_ref_count = refcount; 351 entry->fs_offset = offset; 352 entry->fs_path = path; 353 entry->fs_cap_rights = cap_rights; 354 return (entry); 355 } 356 357 static struct vnode * 358 getctty(kvm_t *kd, struct kinfo_proc *kp) 359 { 360 struct pgrp pgrp; 361 struct proc proc; 362 struct session sess; 363 int error; 364 365 assert(kp); 366 error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 367 sizeof(proc)); 368 if (error == 0) { 369 warnx("can't read proc struct at %p for pid %d", 370 kp->ki_paddr, kp->ki_pid); 371 return (NULL); 372 } 373 if (proc.p_pgrp == NULL) 374 return (NULL); 375 error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp, 376 sizeof(pgrp)); 377 if (error == 0) { 378 warnx("can't read pgrp struct at %p for pid %d", 379 proc.p_pgrp, kp->ki_pid); 380 return (NULL); 381 } 382 error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess, 383 sizeof(sess)); 384 if (error == 0) { 385 warnx("can't read session struct at %p for pid %d", 386 pgrp.pg_session, kp->ki_pid); 387 return (NULL); 388 } 389 return (sess.s_ttyvp); 390 } 391 392 static struct filestat_list * 393 procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 394 { 395 struct file file; 396 struct filedesc filed; 397 struct vm_map_entry vmentry; 398 struct vm_object object; 399 struct vmspace vmspace; 400 vm_map_entry_t entryp; 401 vm_map_t map; 402 vm_object_t objp; 403 struct vnode *vp; 404 struct file **ofiles; 405 struct filestat *entry; 406 struct filestat_list *head; 407 kvm_t *kd; 408 void *data; 409 int i, fflags; 410 int prot, type; 411 unsigned int nfiles; 412 413 assert(procstat); 414 kd = procstat->kd; 415 if (kd == NULL) 416 return (NULL); 417 if (kp->ki_fd == NULL) 418 return (NULL); 419 if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed, 420 sizeof(filed))) { 421 warnx("can't read filedesc at %p", (void *)kp->ki_fd); 422 return (NULL); 423 } 424 425 /* 426 * Allocate list head. 427 */ 428 head = malloc(sizeof(*head)); 429 if (head == NULL) 430 return (NULL); 431 STAILQ_INIT(head); 432 433 /* root directory vnode, if one. */ 434 if (filed.fd_rdir) { 435 entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1, 436 PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL, 0); 437 if (entry != NULL) 438 STAILQ_INSERT_TAIL(head, entry, next); 439 } 440 /* current working directory vnode. */ 441 if (filed.fd_cdir) { 442 entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1, 443 PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL, 0); 444 if (entry != NULL) 445 STAILQ_INSERT_TAIL(head, entry, next); 446 } 447 /* jail root, if any. */ 448 if (filed.fd_jdir) { 449 entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1, 450 PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL, 0); 451 if (entry != NULL) 452 STAILQ_INSERT_TAIL(head, entry, next); 453 } 454 /* ktrace vnode, if one */ 455 if (kp->ki_tracep) { 456 entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1, 457 PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, 458 PS_FST_UFLAG_TRACE, 0, 0, NULL, 0); 459 if (entry != NULL) 460 STAILQ_INSERT_TAIL(head, entry, next); 461 } 462 /* text vnode, if one */ 463 if (kp->ki_textvp) { 464 entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1, 465 PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL, 0); 466 if (entry != NULL) 467 STAILQ_INSERT_TAIL(head, entry, next); 468 } 469 /* Controlling terminal. */ 470 if ((vp = getctty(kd, kp)) != NULL) { 471 entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1, 472 PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, 473 PS_FST_UFLAG_CTTY, 0, 0, NULL, 0); 474 if (entry != NULL) 475 STAILQ_INSERT_TAIL(head, entry, next); 476 } 477 478 nfiles = filed.fd_lastfile + 1; 479 ofiles = malloc(nfiles * sizeof(struct file *)); 480 if (ofiles == NULL) { 481 warn("malloc(%zu)", nfiles * sizeof(struct file *)); 482 goto do_mmapped; 483 } 484 if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles, 485 nfiles * sizeof(struct file *))) { 486 warnx("cannot read file structures at %p", 487 (void *)filed.fd_ofiles); 488 free(ofiles); 489 goto do_mmapped; 490 } 491 for (i = 0; i <= filed.fd_lastfile; i++) { 492 if (ofiles[i] == NULL) 493 continue; 494 if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file, 495 sizeof(struct file))) { 496 warnx("can't read file %d at %p", i, 497 (void *)ofiles[i]); 498 continue; 499 } 500 switch (file.f_type) { 501 case DTYPE_VNODE: 502 type = PS_FST_TYPE_VNODE; 503 data = file.f_vnode; 504 break; 505 case DTYPE_SOCKET: 506 type = PS_FST_TYPE_SOCKET; 507 data = file.f_data; 508 break; 509 case DTYPE_PIPE: 510 type = PS_FST_TYPE_PIPE; 511 data = file.f_data; 512 break; 513 case DTYPE_FIFO: 514 type = PS_FST_TYPE_FIFO; 515 data = file.f_vnode; 516 break; 517 #ifdef DTYPE_PTS 518 case DTYPE_PTS: 519 type = PS_FST_TYPE_PTS; 520 data = file.f_data; 521 break; 522 #endif 523 case DTYPE_SHM: 524 type = PS_FST_TYPE_SHM; 525 data = file.f_data; 526 break; 527 default: 528 continue; 529 } 530 /* XXXRW: No capability rights support for kvm yet. */ 531 entry = filestat_new_entry(data, type, i, 532 to_filestat_flags(file.f_flag), 0, 0, 0, NULL, 0); 533 if (entry != NULL) 534 STAILQ_INSERT_TAIL(head, entry, next); 535 } 536 free(ofiles); 537 538 do_mmapped: 539 540 /* 541 * Process mmapped files if requested. 542 */ 543 if (mmapped) { 544 if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace, 545 sizeof(vmspace))) { 546 warnx("can't read vmspace at %p", 547 (void *)kp->ki_vmspace); 548 goto exit; 549 } 550 map = &vmspace.vm_map; 551 552 for (entryp = map->header.next; 553 entryp != &kp->ki_vmspace->vm_map.header; 554 entryp = vmentry.next) { 555 if (!kvm_read_all(kd, (unsigned long)entryp, &vmentry, 556 sizeof(vmentry))) { 557 warnx("can't read vm_map_entry at %p", 558 (void *)entryp); 559 continue; 560 } 561 if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP) 562 continue; 563 if ((objp = vmentry.object.vm_object) == NULL) 564 continue; 565 for (; objp; objp = object.backing_object) { 566 if (!kvm_read_all(kd, (unsigned long)objp, 567 &object, sizeof(object))) { 568 warnx("can't read vm_object at %p", 569 (void *)objp); 570 break; 571 } 572 } 573 574 /* We want only vnode objects. */ 575 if (object.type != OBJT_VNODE) 576 continue; 577 578 prot = vmentry.protection; 579 fflags = 0; 580 if (prot & VM_PROT_READ) 581 fflags = PS_FST_FFLAG_READ; 582 if ((vmentry.eflags & MAP_ENTRY_COW) == 0 && 583 prot & VM_PROT_WRITE) 584 fflags |= PS_FST_FFLAG_WRITE; 585 586 /* 587 * Create filestat entry. 588 */ 589 entry = filestat_new_entry(object.handle, 590 PS_FST_TYPE_VNODE, -1, fflags, 591 PS_FST_UFLAG_MMAP, 0, 0, NULL, 0); 592 if (entry != NULL) 593 STAILQ_INSERT_TAIL(head, entry, next); 594 } 595 } 596 exit: 597 return (head); 598 } 599 600 /* 601 * kinfo types to filestat translation. 602 */ 603 static int 604 kinfo_type2fst(int kftype) 605 { 606 static struct { 607 int kf_type; 608 int fst_type; 609 } kftypes2fst[] = { 610 { KF_TYPE_CRYPTO, PS_FST_TYPE_CRYPTO }, 611 { KF_TYPE_FIFO, PS_FST_TYPE_FIFO }, 612 { KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE }, 613 { KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE }, 614 { KF_TYPE_NONE, PS_FST_TYPE_NONE }, 615 { KF_TYPE_PIPE, PS_FST_TYPE_PIPE }, 616 { KF_TYPE_PTS, PS_FST_TYPE_PTS }, 617 { KF_TYPE_SEM, PS_FST_TYPE_SEM }, 618 { KF_TYPE_SHM, PS_FST_TYPE_SHM }, 619 { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET }, 620 { KF_TYPE_VNODE, PS_FST_TYPE_VNODE }, 621 { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN } 622 }; 623 #define NKFTYPES (sizeof(kftypes2fst) / sizeof(*kftypes2fst)) 624 unsigned int i; 625 626 for (i = 0; i < NKFTYPES; i++) 627 if (kftypes2fst[i].kf_type == kftype) 628 break; 629 if (i == NKFTYPES) 630 return (PS_FST_TYPE_UNKNOWN); 631 return (kftypes2fst[i].fst_type); 632 } 633 634 /* 635 * kinfo flags to filestat translation. 636 */ 637 static int 638 kinfo_fflags2fst(int kfflags) 639 { 640 static struct { 641 int kf_flag; 642 int fst_flag; 643 } kfflags2fst[] = { 644 { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND }, 645 { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC }, 646 { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT }, 647 { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT }, 648 { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL }, 649 { KF_FLAG_EXEC, PS_FST_FFLAG_EXEC }, 650 { KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK }, 651 { KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC }, 652 { KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK }, 653 { KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 654 { KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 655 { KF_FLAG_READ, PS_FST_FFLAG_READ }, 656 { KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK }, 657 { KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC }, 658 { KF_FLAG_WRITE, PS_FST_FFLAG_WRITE } 659 }; 660 #define NKFFLAGS (sizeof(kfflags2fst) / sizeof(*kfflags2fst)) 661 unsigned int i; 662 int flags; 663 664 flags = 0; 665 for (i = 0; i < NKFFLAGS; i++) 666 if ((kfflags & kfflags2fst[i].kf_flag) != 0) 667 flags |= kfflags2fst[i].fst_flag; 668 return (flags); 669 } 670 671 static int 672 kinfo_uflags2fst(int fd) 673 { 674 675 switch (fd) { 676 case KF_FD_TYPE_CTTY: 677 return (PS_FST_UFLAG_CTTY); 678 case KF_FD_TYPE_CWD: 679 return (PS_FST_UFLAG_CDIR); 680 case KF_FD_TYPE_JAIL: 681 return (PS_FST_UFLAG_JAIL); 682 case KF_FD_TYPE_TEXT: 683 return (PS_FST_UFLAG_TEXT); 684 case KF_FD_TYPE_TRACE: 685 return (PS_FST_UFLAG_TRACE); 686 case KF_FD_TYPE_ROOT: 687 return (PS_FST_UFLAG_RDIR); 688 } 689 return (0); 690 } 691 692 static struct kinfo_file * 693 kinfo_getfile_core(struct procstat_core *core, int *cntp) 694 { 695 int cnt; 696 size_t len; 697 char *buf, *bp, *eb; 698 struct kinfo_file *kif, *kp, *kf; 699 700 buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len); 701 if (buf == NULL) 702 return (NULL); 703 /* 704 * XXXMG: The code below is just copy&past from libutil. 705 * The code duplication can be avoided if libutil 706 * is extended to provide something like: 707 * struct kinfo_file *kinfo_getfile_from_buf(const char *buf, 708 * size_t len, int *cntp); 709 */ 710 711 /* Pass 1: count items */ 712 cnt = 0; 713 bp = buf; 714 eb = buf + len; 715 while (bp < eb) { 716 kf = (struct kinfo_file *)(uintptr_t)bp; 717 bp += kf->kf_structsize; 718 cnt++; 719 } 720 721 kif = calloc(cnt, sizeof(*kif)); 722 if (kif == NULL) { 723 free(buf); 724 return (NULL); 725 } 726 bp = buf; 727 eb = buf + len; 728 kp = kif; 729 /* Pass 2: unpack */ 730 while (bp < eb) { 731 kf = (struct kinfo_file *)(uintptr_t)bp; 732 /* Copy/expand into pre-zeroed buffer */ 733 memcpy(kp, kf, kf->kf_structsize); 734 /* Advance to next packed record */ 735 bp += kf->kf_structsize; 736 /* Set field size to fixed length, advance */ 737 kp->kf_structsize = sizeof(*kp); 738 kp++; 739 } 740 free(buf); 741 *cntp = cnt; 742 return (kif); /* Caller must free() return value */ 743 } 744 745 static struct filestat_list * 746 procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, 747 int mmapped) 748 { 749 struct kinfo_file *kif, *files; 750 struct kinfo_vmentry *kve, *vmentries; 751 struct filestat_list *head; 752 struct filestat *entry; 753 char *path; 754 off_t offset; 755 int cnt, fd, fflags; 756 int i, type, uflags; 757 int refcount; 758 cap_rights_t cap_rights; 759 760 assert(kp); 761 if (kp->ki_fd == NULL) 762 return (NULL); 763 switch(procstat->type) { 764 case PROCSTAT_SYSCTL: 765 files = kinfo_getfile(kp->ki_pid, &cnt); 766 break; 767 case PROCSTAT_CORE: 768 files = kinfo_getfile_core(procstat->core, &cnt); 769 break; 770 default: 771 assert(!"invalid type"); 772 } 773 if (files == NULL && errno != EPERM) { 774 warn("kinfo_getfile()"); 775 return (NULL); 776 } 777 procstat->files = files; 778 779 /* 780 * Allocate list head. 781 */ 782 head = malloc(sizeof(*head)); 783 if (head == NULL) 784 return (NULL); 785 STAILQ_INIT(head); 786 for (i = 0; i < cnt; i++) { 787 kif = &files[i]; 788 789 type = kinfo_type2fst(kif->kf_type); 790 fd = kif->kf_fd >= 0 ? kif->kf_fd : -1; 791 fflags = kinfo_fflags2fst(kif->kf_flags); 792 uflags = kinfo_uflags2fst(kif->kf_fd); 793 refcount = kif->kf_ref_count; 794 offset = kif->kf_offset; 795 if (*kif->kf_path != '\0') 796 path = strdup(kif->kf_path); 797 else 798 path = NULL; 799 cap_rights = kif->kf_cap_rights; 800 801 /* 802 * Create filestat entry. 803 */ 804 entry = filestat_new_entry(kif, type, fd, fflags, uflags, 805 refcount, offset, path, cap_rights); 806 if (entry != NULL) 807 STAILQ_INSERT_TAIL(head, entry, next); 808 } 809 if (mmapped != 0) { 810 vmentries = procstat_getvmmap(procstat, kp, &cnt); 811 procstat->vmentries = vmentries; 812 if (vmentries == NULL || cnt == 0) 813 goto fail; 814 for (i = 0; i < cnt; i++) { 815 kve = &vmentries[i]; 816 if (kve->kve_type != KVME_TYPE_VNODE) 817 continue; 818 fflags = 0; 819 if (kve->kve_protection & KVME_PROT_READ) 820 fflags = PS_FST_FFLAG_READ; 821 if ((kve->kve_flags & KVME_FLAG_COW) == 0 && 822 kve->kve_protection & KVME_PROT_WRITE) 823 fflags |= PS_FST_FFLAG_WRITE; 824 offset = kve->kve_offset; 825 refcount = kve->kve_ref_count; 826 if (*kve->kve_path != '\0') 827 path = strdup(kve->kve_path); 828 else 829 path = NULL; 830 entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1, 831 fflags, PS_FST_UFLAG_MMAP, refcount, offset, path, 832 0); 833 if (entry != NULL) 834 STAILQ_INSERT_TAIL(head, entry, next); 835 } 836 } 837 fail: 838 return (head); 839 } 840 841 int 842 procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, 843 struct pipestat *ps, char *errbuf) 844 { 845 846 assert(ps); 847 if (procstat->type == PROCSTAT_KVM) { 848 return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps, 849 errbuf)); 850 } else if (procstat->type == PROCSTAT_SYSCTL || 851 procstat->type == PROCSTAT_CORE) { 852 return (procstat_get_pipe_info_sysctl(fst, ps, errbuf)); 853 } else { 854 warnx("unknown access method: %d", procstat->type); 855 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 856 return (1); 857 } 858 } 859 860 static int 861 procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, 862 struct pipestat *ps, char *errbuf) 863 { 864 struct pipe pi; 865 void *pipep; 866 867 assert(kd); 868 assert(ps); 869 assert(fst); 870 bzero(ps, sizeof(*ps)); 871 pipep = fst->fs_typedep; 872 if (pipep == NULL) 873 goto fail; 874 if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) { 875 warnx("can't read pipe at %p", (void *)pipep); 876 goto fail; 877 } 878 ps->addr = (uintptr_t)pipep; 879 ps->peer = (uintptr_t)pi.pipe_peer; 880 ps->buffer_cnt = pi.pipe_buffer.cnt; 881 return (0); 882 883 fail: 884 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 885 return (1); 886 } 887 888 static int 889 procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps, 890 char *errbuf __unused) 891 { 892 struct kinfo_file *kif; 893 894 assert(ps); 895 assert(fst); 896 bzero(ps, sizeof(*ps)); 897 kif = fst->fs_typedep; 898 if (kif == NULL) 899 return (1); 900 ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr; 901 ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer; 902 ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt; 903 return (0); 904 } 905 906 int 907 procstat_get_pts_info(struct procstat *procstat, struct filestat *fst, 908 struct ptsstat *pts, char *errbuf) 909 { 910 911 assert(pts); 912 if (procstat->type == PROCSTAT_KVM) { 913 return (procstat_get_pts_info_kvm(procstat->kd, fst, pts, 914 errbuf)); 915 } else if (procstat->type == PROCSTAT_SYSCTL || 916 procstat->type == PROCSTAT_CORE) { 917 return (procstat_get_pts_info_sysctl(fst, pts, errbuf)); 918 } else { 919 warnx("unknown access method: %d", procstat->type); 920 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 921 return (1); 922 } 923 } 924 925 static int 926 procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, 927 struct ptsstat *pts, char *errbuf) 928 { 929 struct tty tty; 930 void *ttyp; 931 932 assert(kd); 933 assert(pts); 934 assert(fst); 935 bzero(pts, sizeof(*pts)); 936 ttyp = fst->fs_typedep; 937 if (ttyp == NULL) 938 goto fail; 939 if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) { 940 warnx("can't read tty at %p", (void *)ttyp); 941 goto fail; 942 } 943 pts->dev = dev2udev(kd, tty.t_dev); 944 (void)kdevtoname(kd, tty.t_dev, pts->devname); 945 return (0); 946 947 fail: 948 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 949 return (1); 950 } 951 952 static int 953 procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts, 954 char *errbuf __unused) 955 { 956 struct kinfo_file *kif; 957 958 assert(pts); 959 assert(fst); 960 bzero(pts, sizeof(*pts)); 961 kif = fst->fs_typedep; 962 if (kif == NULL) 963 return (0); 964 pts->dev = kif->kf_un.kf_pts.kf_pts_dev; 965 strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname)); 966 return (0); 967 } 968 969 int 970 procstat_get_shm_info(struct procstat *procstat, struct filestat *fst, 971 struct shmstat *shm, char *errbuf) 972 { 973 974 assert(shm); 975 if (procstat->type == PROCSTAT_KVM) { 976 return (procstat_get_shm_info_kvm(procstat->kd, fst, shm, 977 errbuf)); 978 } else if (procstat->type == PROCSTAT_SYSCTL || 979 procstat->type == PROCSTAT_CORE) { 980 return (procstat_get_shm_info_sysctl(fst, shm, errbuf)); 981 } else { 982 warnx("unknown access method: %d", procstat->type); 983 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 984 return (1); 985 } 986 } 987 988 static int 989 procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst, 990 struct shmstat *shm, char *errbuf) 991 { 992 struct shmfd shmfd; 993 void *shmfdp; 994 char *path; 995 int i; 996 997 assert(kd); 998 assert(shm); 999 assert(fst); 1000 bzero(shm, sizeof(*shm)); 1001 shmfdp = fst->fs_typedep; 1002 if (shmfdp == NULL) 1003 goto fail; 1004 if (!kvm_read_all(kd, (unsigned long)shmfdp, &shmfd, 1005 sizeof(struct shmfd))) { 1006 warnx("can't read shmfd at %p", (void *)shmfdp); 1007 goto fail; 1008 } 1009 shm->mode = S_IFREG | shmfd.shm_mode; 1010 shm->size = shmfd.shm_size; 1011 if (fst->fs_path == NULL && shmfd.shm_path != NULL) { 1012 path = malloc(MAXPATHLEN); 1013 for (i = 0; i < MAXPATHLEN - 1; i++) { 1014 if (!kvm_read_all(kd, (unsigned long)shmfd.shm_path + i, 1015 path + i, 1)) 1016 break; 1017 if (path[i] == '\0') 1018 break; 1019 } 1020 path[i] = '\0'; 1021 if (i == 0) 1022 free(path); 1023 else 1024 fst->fs_path = path; 1025 } 1026 return (0); 1027 1028 fail: 1029 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1030 return (1); 1031 } 1032 1033 static int 1034 procstat_get_shm_info_sysctl(struct filestat *fst, struct shmstat *shm, 1035 char *errbuf __unused) 1036 { 1037 struct kinfo_file *kif; 1038 1039 assert(shm); 1040 assert(fst); 1041 bzero(shm, sizeof(*shm)); 1042 kif = fst->fs_typedep; 1043 if (kif == NULL) 1044 return (0); 1045 shm->size = kif->kf_un.kf_file.kf_file_size; 1046 shm->mode = kif->kf_un.kf_file.kf_file_mode; 1047 return (0); 1048 } 1049 1050 int 1051 procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, 1052 struct vnstat *vn, char *errbuf) 1053 { 1054 1055 assert(vn); 1056 if (procstat->type == PROCSTAT_KVM) { 1057 return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn, 1058 errbuf)); 1059 } else if (procstat->type == PROCSTAT_SYSCTL || 1060 procstat->type == PROCSTAT_CORE) { 1061 return (procstat_get_vnode_info_sysctl(fst, vn, errbuf)); 1062 } else { 1063 warnx("unknown access method: %d", procstat->type); 1064 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1065 return (1); 1066 } 1067 } 1068 1069 static int 1070 procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, 1071 struct vnstat *vn, char *errbuf) 1072 { 1073 /* Filesystem specific handlers. */ 1074 #define FSTYPE(fst) {#fst, fst##_filestat} 1075 struct { 1076 const char *tag; 1077 int (*handler)(kvm_t *kd, struct vnode *vp, 1078 struct vnstat *vn); 1079 } fstypes[] = { 1080 FSTYPE(devfs), 1081 FSTYPE(isofs), 1082 FSTYPE(msdosfs), 1083 FSTYPE(nfs), 1084 FSTYPE(udf), 1085 FSTYPE(ufs), 1086 #ifdef LIBPROCSTAT_ZFS 1087 FSTYPE(zfs), 1088 #endif 1089 }; 1090 #define NTYPES (sizeof(fstypes) / sizeof(*fstypes)) 1091 struct vnode vnode; 1092 char tagstr[12]; 1093 void *vp; 1094 int error, found; 1095 unsigned int i; 1096 1097 assert(kd); 1098 assert(vn); 1099 assert(fst); 1100 vp = fst->fs_typedep; 1101 if (vp == NULL) 1102 goto fail; 1103 error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode)); 1104 if (error == 0) { 1105 warnx("can't read vnode at %p", (void *)vp); 1106 goto fail; 1107 } 1108 bzero(vn, sizeof(*vn)); 1109 vn->vn_type = vntype2psfsttype(vnode.v_type); 1110 if (vnode.v_type == VNON || vnode.v_type == VBAD) 1111 return (0); 1112 error = kvm_read_all(kd, (unsigned long)vnode.v_tag, tagstr, 1113 sizeof(tagstr)); 1114 if (error == 0) { 1115 warnx("can't read v_tag at %p", (void *)vp); 1116 goto fail; 1117 } 1118 tagstr[sizeof(tagstr) - 1] = '\0'; 1119 1120 /* 1121 * Find appropriate handler. 1122 */ 1123 for (i = 0, found = 0; i < NTYPES; i++) 1124 if (!strcmp(fstypes[i].tag, tagstr)) { 1125 if (fstypes[i].handler(kd, &vnode, vn) != 0) { 1126 goto fail; 1127 } 1128 break; 1129 } 1130 if (i == NTYPES) { 1131 snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr); 1132 return (1); 1133 } 1134 vn->vn_mntdir = getmnton(kd, vnode.v_mount); 1135 if ((vnode.v_type == VBLK || vnode.v_type == VCHR) && 1136 vnode.v_rdev != NULL){ 1137 vn->vn_dev = dev2udev(kd, vnode.v_rdev); 1138 (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname); 1139 } else { 1140 vn->vn_dev = -1; 1141 } 1142 return (0); 1143 1144 fail: 1145 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1146 return (1); 1147 } 1148 1149 /* 1150 * kinfo vnode type to filestat translation. 1151 */ 1152 static int 1153 kinfo_vtype2fst(int kfvtype) 1154 { 1155 static struct { 1156 int kf_vtype; 1157 int fst_vtype; 1158 } kfvtypes2fst[] = { 1159 { KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD }, 1160 { KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK }, 1161 { KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR }, 1162 { KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR }, 1163 { KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO }, 1164 { KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK }, 1165 { KF_VTYPE_VNON, PS_FST_VTYPE_VNON }, 1166 { KF_VTYPE_VREG, PS_FST_VTYPE_VREG }, 1167 { KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK } 1168 }; 1169 #define NKFVTYPES (sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst)) 1170 unsigned int i; 1171 1172 for (i = 0; i < NKFVTYPES; i++) 1173 if (kfvtypes2fst[i].kf_vtype == kfvtype) 1174 break; 1175 if (i == NKFVTYPES) 1176 return (PS_FST_VTYPE_UNKNOWN); 1177 return (kfvtypes2fst[i].fst_vtype); 1178 } 1179 1180 static int 1181 procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn, 1182 char *errbuf) 1183 { 1184 struct statfs stbuf; 1185 struct kinfo_file *kif; 1186 struct kinfo_vmentry *kve; 1187 uint64_t fileid; 1188 uint64_t size; 1189 char *name, *path; 1190 uint32_t fsid; 1191 uint16_t mode; 1192 uint32_t rdev; 1193 int vntype; 1194 int status; 1195 1196 assert(fst); 1197 assert(vn); 1198 bzero(vn, sizeof(*vn)); 1199 if (fst->fs_typedep == NULL) 1200 return (1); 1201 if (fst->fs_uflags & PS_FST_UFLAG_MMAP) { 1202 kve = fst->fs_typedep; 1203 fileid = kve->kve_vn_fileid; 1204 fsid = kve->kve_vn_fsid; 1205 mode = kve->kve_vn_mode; 1206 path = kve->kve_path; 1207 rdev = kve->kve_vn_rdev; 1208 size = kve->kve_vn_size; 1209 vntype = kinfo_vtype2fst(kve->kve_vn_type); 1210 status = kve->kve_status; 1211 } else { 1212 kif = fst->fs_typedep; 1213 fileid = kif->kf_un.kf_file.kf_file_fileid; 1214 fsid = kif->kf_un.kf_file.kf_file_fsid; 1215 mode = kif->kf_un.kf_file.kf_file_mode; 1216 path = kif->kf_path; 1217 rdev = kif->kf_un.kf_file.kf_file_rdev; 1218 size = kif->kf_un.kf_file.kf_file_size; 1219 vntype = kinfo_vtype2fst(kif->kf_vnode_type); 1220 status = kif->kf_status; 1221 } 1222 vn->vn_type = vntype; 1223 if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD) 1224 return (0); 1225 if ((status & KF_ATTR_VALID) == 0) { 1226 snprintf(errbuf, _POSIX2_LINE_MAX, "? (no info available)"); 1227 return (1); 1228 } 1229 if (path && *path) { 1230 statfs(path, &stbuf); 1231 vn->vn_mntdir = strdup(stbuf.f_mntonname); 1232 } else 1233 vn->vn_mntdir = strdup("-"); 1234 vn->vn_dev = rdev; 1235 if (vntype == PS_FST_VTYPE_VBLK) { 1236 name = devname(rdev, S_IFBLK); 1237 if (name != NULL) 1238 strlcpy(vn->vn_devname, name, 1239 sizeof(vn->vn_devname)); 1240 } else if (vntype == PS_FST_VTYPE_VCHR) { 1241 name = devname(vn->vn_dev, S_IFCHR); 1242 if (name != NULL) 1243 strlcpy(vn->vn_devname, name, 1244 sizeof(vn->vn_devname)); 1245 } 1246 vn->vn_fsid = fsid; 1247 vn->vn_fileid = fileid; 1248 vn->vn_size = size; 1249 vn->vn_mode = mode; 1250 return (0); 1251 } 1252 1253 int 1254 procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, 1255 struct sockstat *sock, char *errbuf) 1256 { 1257 1258 assert(sock); 1259 if (procstat->type == PROCSTAT_KVM) { 1260 return (procstat_get_socket_info_kvm(procstat->kd, fst, sock, 1261 errbuf)); 1262 } else if (procstat->type == PROCSTAT_SYSCTL || 1263 procstat->type == PROCSTAT_CORE) { 1264 return (procstat_get_socket_info_sysctl(fst, sock, errbuf)); 1265 } else { 1266 warnx("unknown access method: %d", procstat->type); 1267 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1268 return (1); 1269 } 1270 } 1271 1272 static int 1273 procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, 1274 struct sockstat *sock, char *errbuf) 1275 { 1276 struct domain dom; 1277 struct inpcb inpcb; 1278 struct protosw proto; 1279 struct socket s; 1280 struct unpcb unpcb; 1281 ssize_t len; 1282 void *so; 1283 1284 assert(kd); 1285 assert(sock); 1286 assert(fst); 1287 bzero(sock, sizeof(*sock)); 1288 so = fst->fs_typedep; 1289 if (so == NULL) 1290 goto fail; 1291 sock->so_addr = (uintptr_t)so; 1292 /* fill in socket */ 1293 if (!kvm_read_all(kd, (unsigned long)so, &s, 1294 sizeof(struct socket))) { 1295 warnx("can't read sock at %p", (void *)so); 1296 goto fail; 1297 } 1298 /* fill in protosw entry */ 1299 if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto, 1300 sizeof(struct protosw))) { 1301 warnx("can't read protosw at %p", (void *)s.so_proto); 1302 goto fail; 1303 } 1304 /* fill in domain */ 1305 if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom, 1306 sizeof(struct domain))) { 1307 warnx("can't read domain at %p", 1308 (void *)proto.pr_domain); 1309 goto fail; 1310 } 1311 if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname, 1312 sizeof(sock->dname) - 1)) < 0) { 1313 warnx("can't read domain name at %p", (void *)dom.dom_name); 1314 sock->dname[0] = '\0'; 1315 } 1316 else 1317 sock->dname[len] = '\0'; 1318 1319 /* 1320 * Fill in known data. 1321 */ 1322 sock->type = s.so_type; 1323 sock->proto = proto.pr_protocol; 1324 sock->dom_family = dom.dom_family; 1325 sock->so_pcb = (uintptr_t)s.so_pcb; 1326 1327 /* 1328 * Protocol specific data. 1329 */ 1330 switch(dom.dom_family) { 1331 case AF_INET: 1332 case AF_INET6: 1333 if (proto.pr_protocol == IPPROTO_TCP) { 1334 if (s.so_pcb) { 1335 if (kvm_read(kd, (u_long)s.so_pcb, 1336 (char *)&inpcb, sizeof(struct inpcb)) 1337 != sizeof(struct inpcb)) { 1338 warnx("can't read inpcb at %p", 1339 (void *)s.so_pcb); 1340 } else 1341 sock->inp_ppcb = 1342 (uintptr_t)inpcb.inp_ppcb; 1343 } 1344 } 1345 break; 1346 case AF_UNIX: 1347 if (s.so_pcb) { 1348 if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb, 1349 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 1350 warnx("can't read unpcb at %p", 1351 (void *)s.so_pcb); 1352 } else if (unpcb.unp_conn) { 1353 sock->so_rcv_sb_state = s.so_rcv.sb_state; 1354 sock->so_snd_sb_state = s.so_snd.sb_state; 1355 sock->unp_conn = (uintptr_t)unpcb.unp_conn; 1356 } 1357 } 1358 break; 1359 default: 1360 break; 1361 } 1362 return (0); 1363 1364 fail: 1365 snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1366 return (1); 1367 } 1368 1369 static int 1370 procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, 1371 char *errbuf __unused) 1372 { 1373 struct kinfo_file *kif; 1374 1375 assert(sock); 1376 assert(fst); 1377 bzero(sock, sizeof(*sock)); 1378 kif = fst->fs_typedep; 1379 if (kif == NULL) 1380 return (0); 1381 1382 /* 1383 * Fill in known data. 1384 */ 1385 sock->type = kif->kf_sock_type; 1386 sock->proto = kif->kf_sock_protocol; 1387 sock->dom_family = kif->kf_sock_domain; 1388 sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb; 1389 strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname)); 1390 bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len); 1391 bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len); 1392 1393 /* 1394 * Protocol specific data. 1395 */ 1396 switch(sock->dom_family) { 1397 case AF_INET: 1398 case AF_INET6: 1399 if (sock->proto == IPPROTO_TCP) 1400 sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb; 1401 break; 1402 case AF_UNIX: 1403 if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) { 1404 sock->so_rcv_sb_state = 1405 kif->kf_un.kf_sock.kf_sock_rcv_sb_state; 1406 sock->so_snd_sb_state = 1407 kif->kf_un.kf_sock.kf_sock_snd_sb_state; 1408 sock->unp_conn = 1409 kif->kf_un.kf_sock.kf_sock_unpconn; 1410 } 1411 break; 1412 default: 1413 break; 1414 } 1415 return (0); 1416 } 1417 1418 /* 1419 * Descriptor flags to filestat translation. 1420 */ 1421 static int 1422 to_filestat_flags(int flags) 1423 { 1424 static struct { 1425 int flag; 1426 int fst_flag; 1427 } fstflags[] = { 1428 { FREAD, PS_FST_FFLAG_READ }, 1429 { FWRITE, PS_FST_FFLAG_WRITE }, 1430 { O_APPEND, PS_FST_FFLAG_APPEND }, 1431 { O_ASYNC, PS_FST_FFLAG_ASYNC }, 1432 { O_CREAT, PS_FST_FFLAG_CREAT }, 1433 { O_DIRECT, PS_FST_FFLAG_DIRECT }, 1434 { O_EXCL, PS_FST_FFLAG_EXCL }, 1435 { O_EXEC, PS_FST_FFLAG_EXEC }, 1436 { O_EXLOCK, PS_FST_FFLAG_EXLOCK }, 1437 { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 1438 { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 1439 { O_SHLOCK, PS_FST_FFLAG_SHLOCK }, 1440 { O_SYNC, PS_FST_FFLAG_SYNC }, 1441 { O_TRUNC, PS_FST_FFLAG_TRUNC } 1442 }; 1443 #define NFSTFLAGS (sizeof(fstflags) / sizeof(*fstflags)) 1444 int fst_flags; 1445 unsigned int i; 1446 1447 fst_flags = 0; 1448 for (i = 0; i < NFSTFLAGS; i++) 1449 if (flags & fstflags[i].flag) 1450 fst_flags |= fstflags[i].fst_flag; 1451 return (fst_flags); 1452 } 1453 1454 /* 1455 * Vnode type to filestate translation. 1456 */ 1457 static int 1458 vntype2psfsttype(int type) 1459 { 1460 static struct { 1461 int vtype; 1462 int fst_vtype; 1463 } vt2fst[] = { 1464 { VBAD, PS_FST_VTYPE_VBAD }, 1465 { VBLK, PS_FST_VTYPE_VBLK }, 1466 { VCHR, PS_FST_VTYPE_VCHR }, 1467 { VDIR, PS_FST_VTYPE_VDIR }, 1468 { VFIFO, PS_FST_VTYPE_VFIFO }, 1469 { VLNK, PS_FST_VTYPE_VLNK }, 1470 { VNON, PS_FST_VTYPE_VNON }, 1471 { VREG, PS_FST_VTYPE_VREG }, 1472 { VSOCK, PS_FST_VTYPE_VSOCK } 1473 }; 1474 #define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst)) 1475 unsigned int i, fst_type; 1476 1477 fst_type = PS_FST_VTYPE_UNKNOWN; 1478 for (i = 0; i < NVFTYPES; i++) { 1479 if (type == vt2fst[i].vtype) { 1480 fst_type = vt2fst[i].fst_vtype; 1481 break; 1482 } 1483 } 1484 return (fst_type); 1485 } 1486 1487 static char * 1488 getmnton(kvm_t *kd, struct mount *m) 1489 { 1490 struct mount mnt; 1491 static struct mtab { 1492 struct mtab *next; 1493 struct mount *m; 1494 char mntonname[MNAMELEN + 1]; 1495 } *mhead = NULL; 1496 struct mtab *mt; 1497 1498 for (mt = mhead; mt != NULL; mt = mt->next) 1499 if (m == mt->m) 1500 return (mt->mntonname); 1501 if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) { 1502 warnx("can't read mount table at %p", (void *)m); 1503 return (NULL); 1504 } 1505 if ((mt = malloc(sizeof (struct mtab))) == NULL) 1506 err(1, NULL); 1507 mt->m = m; 1508 bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); 1509 mt->mntonname[MNAMELEN] = '\0'; 1510 mt->next = mhead; 1511 mhead = mt; 1512 return (mt->mntonname); 1513 } 1514 1515 static struct kinfo_vmentry * 1516 kinfo_getvmmap_core(struct procstat_core *core, int *cntp) 1517 { 1518 int cnt; 1519 size_t len; 1520 char *buf, *bp, *eb; 1521 struct kinfo_vmentry *kiv, *kp, *kv; 1522 1523 buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len); 1524 if (buf == NULL) 1525 return (NULL); 1526 1527 /* 1528 * XXXMG: The code below is just copy&past from libutil. 1529 * The code duplication can be avoided if libutil 1530 * is extended to provide something like: 1531 * struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf, 1532 * size_t len, int *cntp); 1533 */ 1534 1535 /* Pass 1: count items */ 1536 cnt = 0; 1537 bp = buf; 1538 eb = buf + len; 1539 while (bp < eb) { 1540 kv = (struct kinfo_vmentry *)(uintptr_t)bp; 1541 bp += kv->kve_structsize; 1542 cnt++; 1543 } 1544 1545 kiv = calloc(cnt, sizeof(*kiv)); 1546 if (kiv == NULL) { 1547 free(buf); 1548 return (NULL); 1549 } 1550 bp = buf; 1551 eb = buf + len; 1552 kp = kiv; 1553 /* Pass 2: unpack */ 1554 while (bp < eb) { 1555 kv = (struct kinfo_vmentry *)(uintptr_t)bp; 1556 /* Copy/expand into pre-zeroed buffer */ 1557 memcpy(kp, kv, kv->kve_structsize); 1558 /* Advance to next packed record */ 1559 bp += kv->kve_structsize; 1560 /* Set field size to fixed length, advance */ 1561 kp->kve_structsize = sizeof(*kp); 1562 kp++; 1563 } 1564 free(buf); 1565 *cntp = cnt; 1566 return (kiv); /* Caller must free() return value */ 1567 } 1568 1569 struct kinfo_vmentry * 1570 procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp, 1571 unsigned int *cntp) 1572 { 1573 switch(procstat->type) { 1574 case PROCSTAT_KVM: 1575 warnx("kvm method is not supported"); 1576 return (NULL); 1577 case PROCSTAT_SYSCTL: 1578 return (kinfo_getvmmap(kp->ki_pid, cntp)); 1579 case PROCSTAT_CORE: 1580 return (kinfo_getvmmap_core(procstat->core, cntp)); 1581 default: 1582 warnx("unknown access method: %d", procstat->type); 1583 return (NULL); 1584 } 1585 } 1586 1587 void 1588 procstat_freevmmap(struct procstat *procstat __unused, 1589 struct kinfo_vmentry *vmmap) 1590 { 1591 1592 free(vmmap); 1593 } 1594 1595 static gid_t * 1596 procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp) 1597 { 1598 int mib[4]; 1599 size_t len; 1600 gid_t *groups; 1601 1602 mib[0] = CTL_KERN; 1603 mib[1] = KERN_PROC; 1604 mib[2] = KERN_PROC_GROUPS; 1605 mib[3] = pid; 1606 len = (sysconf(_SC_NGROUPS_MAX) + 1) * sizeof(gid_t); 1607 groups = malloc(len); 1608 if (groups == NULL) { 1609 warn("malloc(%zu)", len); 1610 return (NULL); 1611 } 1612 if (sysctl(mib, 4, groups, &len, NULL, 0) == -1) { 1613 warn("sysctl: kern.proc.groups: %d", pid); 1614 free(groups); 1615 return (NULL); 1616 } 1617 *cntp = len / sizeof(gid_t); 1618 return (groups); 1619 } 1620 1621 static gid_t * 1622 procstat_getgroups_core(struct procstat_core *core, unsigned int *cntp) 1623 { 1624 size_t len; 1625 gid_t *groups; 1626 1627 groups = procstat_core_get(core, PSC_TYPE_GROUPS, NULL, &len); 1628 if (groups == NULL) 1629 return (NULL); 1630 *cntp = len / sizeof(gid_t); 1631 return (groups); 1632 } 1633 1634 gid_t * 1635 procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp, 1636 unsigned int *cntp) 1637 { 1638 switch(procstat->type) { 1639 case PROCSTAT_KVM: 1640 warnx("kvm method is not supported"); 1641 return (NULL); 1642 case PROCSTAT_SYSCTL: 1643 return (procstat_getgroups_sysctl(kp->ki_pid, cntp)); 1644 case PROCSTAT_CORE: 1645 return (procstat_getgroups_core(procstat->core, cntp)); 1646 default: 1647 warnx("unknown access method: %d", procstat->type); 1648 return (NULL); 1649 } 1650 } 1651 1652 void 1653 procstat_freegroups(struct procstat *procstat __unused, gid_t *groups) 1654 { 1655 1656 free(groups); 1657 } 1658