1 /* $OpenBSD: kvm_proc.c,v 1.64 2024/05/10 06:46:14 asou Exp $ */
2 /* $NetBSD: kvm_proc.c,v 1.30 1999/03/24 05:50:50 mrg Exp $ */
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*-
32 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
33 * Copyright (c) 1989, 1992, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * This code is derived from software developed by the Computer Systems
37 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
38 * BG 91-66 and contributed to Berkeley.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64
65 /*
66 * Proc traversal interface for kvm. ps and w are (probably) the exclusive
67 * users of this code, so we've factored it out into a separate module.
68 * Thus, we keep this grunge out of the other kvm applications (i.e.,
69 * most other applications are interested only in open/close/read/nlist).
70 */
71
72 #define __need_process
73 #include <sys/param.h> /* VM_MIN_ADDRESS PAGE_SIZE */
74 #include <sys/types.h>
75 #include <sys/signal.h>
76 #include <sys/proc.h>
77 #include <sys/exec.h>
78 #include <sys/stat.h>
79 #include <sys/ioctl.h>
80 #include <sys/tty.h>
81 #include <stddef.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <unistd.h>
85 #include <nlist.h>
86 #include <kvm.h>
87 #include <errno.h>
88
89 #include <uvm/uvm_extern.h>
90 #include <uvm/uvm_amap.h>
91 #include <machine/vmparam.h>
92 #include <machine/pmap.h>
93
94 #include <sys/sysctl.h>
95
96 #include <limits.h>
97 #include <db.h>
98 #include <paths.h>
99
100 #include "kvm_private.h"
101
102 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
103 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
104
105 static char *_kvm_ureadm(kvm_t *, const struct kinfo_proc *, u_long, u_long *);
106 static ssize_t kvm_ureadm(kvm_t *, const struct kinfo_proc *, u_long, char *, size_t);
107
108 static char **kvm_argv(kvm_t *, const struct kinfo_proc *, u_long, int, int, int);
109
110 static char **kvm_doargv(kvm_t *, const struct kinfo_proc *, int, int,
111 void (*)(struct ps_strings *, u_long *, int *));
112 static int proc_verify(kvm_t *, const struct kinfo_proc *);
113 static void ps_str_a(struct ps_strings *, u_long *, int *);
114 static void ps_str_e(struct ps_strings *, u_long *, int *);
115
116 static struct vm_anon *
_kvm_findanon(kvm_t * kd,struct vm_amap * amapp,int slot)117 _kvm_findanon(kvm_t *kd, struct vm_amap *amapp, int slot)
118 {
119 u_long addr;
120 int bucket;
121 struct vm_amap amap;
122 struct vm_amap_chunk chunk, *chunkp;
123 struct vm_anon *anonp;
124
125 addr = (u_long)amapp;
126 if (KREAD(kd, addr, &amap))
127 return (NULL);
128
129 /* sanity-check slot number */
130 if (slot > amap.am_nslot)
131 return (NULL);
132
133 if (UVM_AMAP_SMALL(&amap))
134 chunkp = &amapp->am_small;
135 else {
136 bucket = UVM_AMAP_BUCKET(&amap, slot);
137 addr = (u_long)(amap.am_buckets + bucket);
138 if (KREAD(kd, addr, &chunkp))
139 return (NULL);
140
141 while (chunkp != NULL) {
142 addr = (u_long)chunkp;
143 if (KREAD(kd, addr, &chunk))
144 return (NULL);
145
146 if (UVM_AMAP_BUCKET(&amap, chunk.ac_baseslot) !=
147 bucket)
148 return (NULL);
149 if (slot >= chunk.ac_baseslot &&
150 slot < chunk.ac_baseslot + chunk.ac_nslot)
151 break;
152
153 chunkp = TAILQ_NEXT(&chunk, ac_list);
154 }
155 if (chunkp == NULL)
156 return (NULL);
157 }
158
159 addr = (u_long)&chunkp->ac_anon[UVM_AMAP_SLOTIDX(slot)];
160 if (KREAD(kd, addr, &anonp))
161 return (NULL);
162
163 return (anonp);
164 }
165
166 static char *
_kvm_ureadm(kvm_t * kd,const struct kinfo_proc * p,u_long va,u_long * cnt)167 _kvm_ureadm(kvm_t *kd, const struct kinfo_proc *p, u_long va, u_long *cnt)
168 {
169 u_long addr, offset, slot;
170 struct vmspace vm;
171 struct vm_anon *anonp, anon;
172 struct vm_map_entry vme;
173 struct vm_page pg;
174 unsigned long rboff;
175
176 if (kd->swapspc == 0) {
177 kd->swapspc = _kvm_malloc(kd, kd->nbpg);
178 if (kd->swapspc == 0)
179 return (NULL);
180 }
181
182 rboff = (unsigned long)&vme.daddrs.addr_entry - (unsigned long)&vme;
183
184 /*
185 * Look through the address map for the memory object
186 * that corresponds to the given virtual address.
187 */
188 if (KREAD(kd, (u_long)p->p_vmspace, &vm))
189 return (NULL);
190 addr = (u_long)vm.vm_map.addr.rbh_root.rbt_root;
191 while (1) {
192 if (addr == 0)
193 return (NULL);
194 addr -= rboff;
195 if (KREAD(kd, addr, &vme))
196 return (NULL);
197
198 if (va < vme.start)
199 addr = (u_long)vme.daddrs.addr_entry.rbt_left;
200 else if (va >= vme.end + vme.guard + vme.fspace)
201 addr = (u_long)vme.daddrs.addr_entry.rbt_right;
202 else if (va >= vme.end)
203 return (NULL);
204 else
205 break;
206 }
207
208 /*
209 * we found the map entry, now to find the object...
210 */
211 if (vme.aref.ar_amap == NULL)
212 return (NULL);
213
214 offset = va - vme.start;
215 slot = offset / kd->nbpg + vme.aref.ar_pageoff;
216
217 anonp = _kvm_findanon(kd, vme.aref.ar_amap, slot);
218 if (anonp == NULL)
219 return (NULL);
220
221 addr = (u_long)anonp;
222 if (KREAD(kd, addr, &anon))
223 return (NULL);
224
225 addr = (u_long)anon.an_page;
226 if (addr) {
227 if (KREAD(kd, addr, &pg))
228 return (NULL);
229
230 if (_kvm_pread(kd, kd->pmfd, (void *)kd->swapspc,
231 (size_t)kd->nbpg, _kvm_pa2off(kd, pg.phys_addr)) != kd->nbpg)
232 return (NULL);
233 } else {
234 if (kd->swfd == -1 ||
235 _kvm_pread(kd, kd->swfd, (void *)kd->swapspc,
236 (size_t)kd->nbpg,
237 (off_t)(anon.an_swslot * kd->nbpg)) != kd->nbpg)
238 return (NULL);
239 }
240
241 /* Found the page. */
242 offset %= kd->nbpg;
243 *cnt = kd->nbpg - offset;
244 return (&kd->swapspc[offset]);
245 }
246
247 void *
_kvm_reallocarray(kvm_t * kd,void * p,size_t i,size_t n)248 _kvm_reallocarray(kvm_t *kd, void *p, size_t i, size_t n)
249 {
250 void *np = reallocarray(p, i, n);
251
252 if (np == 0)
253 _kvm_err(kd, kd->program, "out of memory");
254 return (np);
255 }
256
257 /*
258 * Read in an argument vector from the user address space of process p.
259 * addr if the user-space base address of narg null-terminated contiguous
260 * strings. This is used to read in both the command arguments and
261 * environment strings. Read at most maxcnt characters of strings.
262 */
263 static char **
kvm_argv(kvm_t * kd,const struct kinfo_proc * p,u_long addr,int narg,int maxcnt,int isenv)264 kvm_argv(kvm_t *kd, const struct kinfo_proc *p, u_long addr, int narg,
265 int maxcnt, int isenv)
266 {
267 char *np, *cp, *ep, *ap, **argv, ***pargv, **pargspc, **pargbuf;
268 u_long oaddr = -1;
269 int len, cc, *parglen, *pargc;
270 size_t argc;
271
272 /*
273 * Check that there aren't an unreasonable number of arguments,
274 * and that the address is in user space.
275 */
276 if (narg > ARG_MAX || addr < VM_MIN_ADDRESS || addr >= VM_MAXUSER_ADDRESS)
277 return (0);
278
279 if (isenv) {
280 pargspc = &kd->envspc;
281 pargbuf = &kd->envbuf;
282 parglen = &kd->envlen;
283 pargv = &kd->envp;
284 pargc = &kd->envc;
285 } else {
286 pargspc = &kd->argspc;
287 pargbuf = &kd->argbuf;
288 parglen = &kd->arglen;
289 pargv = &kd->argv;
290 pargc = &kd->argc;
291 }
292
293 if (*pargv == 0)
294 argc = MAXIMUM(narg + 1, 32);
295 else if (narg + 1 > *pargc)
296 argc = MAXIMUM(2 * (*pargc), narg + 1);
297 else
298 goto argv_allocated;
299 argv = _kvm_reallocarray(kd, *pargv, argc, sizeof(**pargv));
300 if (argv == 0)
301 return (0);
302 *pargv = argv;
303 *pargc = argc;
304
305 argv_allocated:
306 if (*pargspc == 0) {
307 *pargspc = _kvm_malloc(kd, kd->nbpg);
308 if (*pargspc == 0)
309 return (0);
310 *parglen = kd->nbpg;
311 }
312 if (*pargbuf == 0) {
313 *pargbuf = _kvm_malloc(kd, kd->nbpg);
314 if (*pargbuf == 0)
315 return (0);
316 }
317 cc = sizeof(char *) * narg;
318 if (kvm_ureadm(kd, p, addr, (char *)*pargv, cc) != cc)
319 return (0);
320 ap = np = *pargspc;
321 argv = *pargv;
322 len = 0;
323
324 /*
325 * Loop over pages, filling in the argument vector.
326 */
327 while (argv < *pargv + narg && *argv != 0) {
328 addr = (u_long)*argv & ~(kd->nbpg - 1);
329 if (addr != oaddr) {
330 if (kvm_ureadm(kd, p, addr, *pargbuf, kd->nbpg) !=
331 kd->nbpg)
332 return (0);
333 oaddr = addr;
334 }
335 addr = (u_long)*argv & (kd->nbpg - 1);
336 cp = *pargbuf + addr;
337 cc = kd->nbpg - addr;
338 if (maxcnt > 0 && cc > maxcnt - len)
339 cc = maxcnt - len;
340 ep = memchr(cp, '\0', cc);
341 if (ep != 0)
342 cc = ep - cp + 1;
343 if (len + cc > *parglen) {
344 ptrdiff_t off;
345 char **pp;
346 char *op = *pargspc;
347 char *newp;
348
349 newp = _kvm_reallocarray(kd, *pargspc,
350 *parglen, 2);
351 if (newp == 0)
352 return (0);
353 *pargspc = newp;
354 *parglen *= 2;
355 /*
356 * Adjust argv pointers in case realloc moved
357 * the string space.
358 */
359 off = *pargspc - op;
360 for (pp = *pargv; pp < argv; pp++)
361 *pp += off;
362 ap += off;
363 np += off;
364 }
365 memcpy(np, cp, cc);
366 np += cc;
367 len += cc;
368 if (ep != 0) {
369 *argv++ = ap;
370 ap = np;
371 } else
372 *argv += cc;
373 if (maxcnt > 0 && len >= maxcnt) {
374 /*
375 * We're stopping prematurely. Terminate the
376 * current string.
377 */
378 if (ep == 0) {
379 *np = '\0';
380 *argv++ = ap;
381 }
382 break;
383 }
384 }
385 /* Make sure argv is terminated. */
386 *argv = 0;
387 return (*pargv);
388 }
389
390 static void
ps_str_a(struct ps_strings * p,u_long * addr,int * n)391 ps_str_a(struct ps_strings *p, u_long *addr, int *n)
392 {
393 *addr = (u_long)p->ps_argvstr;
394 *n = p->ps_nargvstr;
395 }
396
397 static void
ps_str_e(struct ps_strings * p,u_long * addr,int * n)398 ps_str_e(struct ps_strings *p, u_long *addr, int *n)
399 {
400 *addr = (u_long)p->ps_envstr;
401 *n = p->ps_nenvstr;
402 }
403
404 /*
405 * Determine if the proc indicated by p is still active.
406 * This test is not 100% foolproof in theory, but chances of
407 * being wrong are very low.
408 */
409 static int
proc_verify(kvm_t * kd,const struct kinfo_proc * p)410 proc_verify(kvm_t *kd, const struct kinfo_proc *p)
411 {
412 struct proc kernproc;
413 struct process kernprocess;
414
415 if (p->p_psflags & (PS_EMBRYO | PS_ZOMBIE))
416 return (0);
417
418 /*
419 * Just read in the whole proc. It's not that big relative
420 * to the cost of the read system call.
421 */
422 if (KREAD(kd, (u_long)p->p_paddr, &kernproc))
423 return (0);
424 if (KREAD(kd, (u_long)kernproc.p_p, &kernprocess))
425 return (0);
426 if (p->p_pid != kernprocess.ps_pid)
427 return (0);
428 return ((kernprocess.ps_flags & (PS_EMBRYO | PS_ZOMBIE)) == 0);
429 }
430
431 static char **
kvm_doargv(kvm_t * kd,const struct kinfo_proc * p,int nchr,int isenv,void (* info)(struct ps_strings *,u_long *,int *))432 kvm_doargv(kvm_t *kd, const struct kinfo_proc *p, int nchr, int isenv,
433 void (*info)(struct ps_strings *, u_long *, int *))
434 {
435 struct proc pp;
436 struct process pr;
437 struct ps_strings *ps;
438 struct ps_strings arginfo;
439 u_long addr;
440 char **ap;
441 int cnt;
442
443 /* get ps_strings address */
444 if (KREAD(kd, (u_long)p->p_paddr, &pp))
445 return (0);
446 if (KREAD(kd, (u_long)pp.p_p, &pr))
447 return (0);
448 ps = (struct ps_strings *)pr.ps_strings;
449
450 /*
451 * Pointers are stored at the top of the user stack.
452 */
453 if (p->p_psflags & (PS_EMBRYO | PS_ZOMBIE) ||
454 kvm_ureadm(kd, p, (u_long)ps, (char *)&arginfo,
455 sizeof(arginfo)) != sizeof(arginfo))
456 return (0);
457
458 (*info)(&arginfo, &addr, &cnt);
459 if (cnt == 0)
460 return (0);
461 ap = kvm_argv(kd, p, addr, cnt, nchr, isenv);
462 /*
463 * For live kernels, make sure this process didn't go away.
464 */
465 if (ap != 0 && ISALIVE(kd) && !proc_verify(kd, p))
466 ap = 0;
467 return (ap);
468 }
469
470 static char **
kvm_arg_sysctl(kvm_t * kd,pid_t pid,int nchr,int isenv)471 kvm_arg_sysctl(kvm_t *kd, pid_t pid, int nchr, int isenv)
472 {
473 size_t len, orglen;
474 int mib[4], ret;
475 char *buf, **pargbuf;
476
477 if (isenv) {
478 pargbuf = &kd->envbuf;
479 orglen = kd->nbpg;
480 } else {
481 pargbuf = &kd->argbuf;
482 orglen = 8 * kd->nbpg; /* XXX - should be ARG_MAX */
483 }
484 if (*pargbuf == NULL &&
485 (*pargbuf = _kvm_malloc(kd, orglen)) == NULL)
486 return (NULL);
487
488 again:
489 mib[0] = CTL_KERN;
490 mib[1] = KERN_PROC_ARGS;
491 mib[2] = (int)pid;
492 mib[3] = isenv ? KERN_PROC_ENV : KERN_PROC_ARGV;
493
494 len = orglen;
495 ret = (sysctl(mib, 4, *pargbuf, &len, NULL, 0) == -1);
496 if (ret && errno == ENOMEM) {
497 buf = _kvm_reallocarray(kd, *pargbuf, orglen, 2);
498 if (buf == NULL)
499 return (NULL);
500 orglen *= 2;
501 *pargbuf = buf;
502 goto again;
503 }
504
505 if (ret) {
506 free(*pargbuf);
507 *pargbuf = NULL;
508 _kvm_syserr(kd, kd->program, "kvm_arg_sysctl");
509 return (NULL);
510 }
511 #if 0
512 for (argv = (char **)*pargbuf; *argv != NULL; argv++)
513 if (strlen(*argv) > nchr)
514 *argv[nchr] = '\0';
515 #endif
516
517 return (char **)(*pargbuf);
518 }
519
520 /*
521 * Get the command args. This code is now machine independent.
522 */
523 char **
kvm_getargv(kvm_t * kd,const struct kinfo_proc * kp,int nchr)524 kvm_getargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
525 {
526 if (ISALIVE(kd))
527 return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 0));
528 return (kvm_doargv(kd, kp, nchr, 0, ps_str_a));
529 }
530
531 char **
kvm_getenvv(kvm_t * kd,const struct kinfo_proc * kp,int nchr)532 kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
533 {
534 if (ISALIVE(kd))
535 return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 1));
536 return (kvm_doargv(kd, kp, nchr, 1, ps_str_e));
537 }
538
539 /*
540 * Read from user space. The user context is given by p.
541 */
542 static ssize_t
kvm_ureadm(kvm_t * kd,const struct kinfo_proc * p,u_long uva,char * buf,size_t len)543 kvm_ureadm(kvm_t *kd, const struct kinfo_proc *p, u_long uva, char *buf,
544 size_t len)
545 {
546 char *cp = buf;
547
548 while (len > 0) {
549 u_long cnt;
550 size_t cc;
551 char *dp;
552
553 dp = _kvm_ureadm(kd, p, uva, &cnt);
554 if (dp == 0) {
555 _kvm_err(kd, 0, "invalid address (%lx)", uva);
556 return (0);
557 }
558 cc = (size_t)MINIMUM(cnt, len);
559 memcpy(cp, dp, cc);
560 cp += cc;
561 uva += cc;
562 len -= cc;
563 }
564 return (ssize_t)(cp - buf);
565 }
566