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