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