1/*-
2 * Copyright (c) 1989, 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software developed by the Computer Systems
6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7 * BG 91-66 and contributed to Berkeley.
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 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/10/lib/libkvm/kvm.c 316072 2017-03-28 06:05:26Z ngie $");
36
37#if defined(LIBC_SCCS) && !defined(lint)
38#if 0
39static char sccsid[] = "@(#)kvm.c	8.2 (Berkeley) 2/13/94";
40#endif
41#endif /* LIBC_SCCS and not lint */
42
43#include <sys/param.h>
44
45#define	_WANT_VNET
46
47#include <sys/user.h>
48#include <sys/proc.h>
49#include <sys/ioctl.h>
50#include <sys/stat.h>
51#include <sys/sysctl.h>
52#include <sys/linker.h>
53#include <sys/pcpu.h>
54
55#include <net/vnet.h>
56
57#include <vm/vm.h>
58#include <vm/vm_param.h>
59
60#include <machine/vmparam.h>
61
62#include <ctype.h>
63#include <fcntl.h>
64#include <kvm.h>
65#include <limits.h>
66#include <nlist.h>
67#include <paths.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71#include <strings.h>
72#include <unistd.h>
73
74#include "kvm_private.h"
75
76/* from src/lib/libc/gen/nlist.c */
77int __fdnlist(int, struct nlist *);
78
79static char _kd_is_null[] = "";
80
81char *
82kvm_geterr(kvm_t *kd)
83{
84
85	if (kd == NULL)
86		return (_kd_is_null);
87	return (kd->errbuf);
88}
89
90#include <stdarg.h>
91
92/*
93 * Report an error using printf style arguments.  "program" is kd->program
94 * on hard errors, and 0 on soft errors, so that under sun error emulation,
95 * only hard errors are printed out (otherwise, programs like gdb will
96 * generate tons of error messages when trying to access bogus pointers).
97 */
98void
99_kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
100{
101	va_list ap;
102
103	va_start(ap, fmt);
104	if (program != NULL) {
105		(void)fprintf(stderr, "%s: ", program);
106		(void)vfprintf(stderr, fmt, ap);
107		(void)fputc('\n', stderr);
108	} else
109		(void)vsnprintf(kd->errbuf,
110		    sizeof(kd->errbuf), fmt, ap);
111
112	va_end(ap);
113}
114
115void
116_kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
117{
118	va_list ap;
119	int n;
120
121	va_start(ap, fmt);
122	if (program != NULL) {
123		(void)fprintf(stderr, "%s: ", program);
124		(void)vfprintf(stderr, fmt, ap);
125		(void)fprintf(stderr, ": %s\n", strerror(errno));
126	} else {
127		char *cp = kd->errbuf;
128
129		(void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap);
130		n = strlen(cp);
131		(void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
132		    strerror(errno));
133	}
134	va_end(ap);
135}
136
137void *
138_kvm_malloc(kvm_t *kd, size_t n)
139{
140	void *p;
141
142	if ((p = calloc(n, sizeof(char))) == NULL)
143		_kvm_err(kd, kd->program, "can't allocate %zu bytes: %s",
144			 n, strerror(errno));
145	return (p);
146}
147
148static kvm_t *
149_kvm_open(kvm_t *kd, const char *uf, const char *mf, int flag, char *errout)
150{
151	struct stat st;
152
153	kd->vmfd = -1;
154	kd->pmfd = -1;
155	kd->nlfd = -1;
156	kd->vmst = 0;
157	kd->procbase = 0;
158	kd->argspc = 0;
159	kd->argv = 0;
160
161	if (uf == 0)
162		uf = getbootfile();
163	else if (strlen(uf) >= MAXPATHLEN) {
164		_kvm_err(kd, kd->program, "exec file name too long");
165		goto failed;
166	}
167	if (flag & ~O_RDWR) {
168		_kvm_err(kd, kd->program, "bad flags arg");
169		goto failed;
170	}
171	if (mf == 0)
172		mf = _PATH_MEM;
173
174	if ((kd->pmfd = open(mf, flag | O_CLOEXEC, 0)) < 0) {
175		_kvm_syserr(kd, kd->program, "%s", mf);
176		goto failed;
177	}
178	if (fstat(kd->pmfd, &st) < 0) {
179		_kvm_syserr(kd, kd->program, "%s", mf);
180		goto failed;
181	}
182	if (S_ISREG(st.st_mode) && st.st_size <= 0) {
183		errno = EINVAL;
184		_kvm_syserr(kd, kd->program, "empty file");
185		goto failed;
186	}
187	if (S_ISCHR(st.st_mode)) {
188		/*
189		 * If this is a character special device, then check that
190		 * it's /dev/mem.  If so, open kmem too.  (Maybe we should
191		 * make it work for either /dev/mem or /dev/kmem -- in either
192		 * case you're working with a live kernel.)
193		 */
194		if (strcmp(mf, _PATH_DEVNULL) == 0) {
195			kd->vmfd = open(_PATH_DEVNULL, O_RDONLY | O_CLOEXEC);
196			return (kd);
197		} else if (strcmp(mf, _PATH_MEM) == 0) {
198			if ((kd->vmfd = open(_PATH_KMEM, flag | O_CLOEXEC)) <
199			    0) {
200				_kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
201				goto failed;
202			}
203			return (kd);
204		}
205	}
206
207	/*
208	 * This is either a crash dump or a remote live system with its physical
209	 * memory fully accessible via a special device.
210	 * Initialize the virtual address translation machinery,
211	 * but first setup the namelist fd.
212	 */
213	if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) {
214		_kvm_syserr(kd, kd->program, "%s", uf);
215		goto failed;
216	}
217	if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0 ||
218	    strncmp(mf, _PATH_DEVVMM, strlen(_PATH_DEVVMM)) == 0) {
219		kd->rawdump = 1;
220		kd->writable = 1;
221	}
222	if (_kvm_initvtop(kd) < 0)
223		goto failed;
224	return (kd);
225failed:
226	/*
227	 * Copy out the error if doing sane error semantics.
228	 */
229	if (errout != 0)
230		strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
231	(void)kvm_close(kd);
232	return (NULL);
233}
234
235kvm_t *
236kvm_openfiles(const char *uf, const char *mf, const char *sf __unused, int flag,
237    char *errout)
238{
239	kvm_t *kd;
240
241	if ((kd = calloc(1, sizeof(*kd))) == NULL) {
242		(void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
243		return (NULL);
244	}
245	kd->program = 0;
246	return (_kvm_open(kd, uf, mf, flag, errout));
247}
248
249kvm_t *
250kvm_open(const char *uf, const char *mf, const char *sf __unused, int flag,
251    const char *errstr)
252{
253	kvm_t *kd;
254
255	if ((kd = calloc(1, sizeof(*kd))) == NULL) {
256		if (errstr != NULL)
257			(void)fprintf(stderr, "%s: %s\n",
258				      errstr, strerror(errno));
259		return (NULL);
260	}
261	kd->program = errstr;
262	return (_kvm_open(kd, uf, mf, flag, NULL));
263}
264
265int
266kvm_close(kvm_t *kd)
267{
268	int error = 0;
269
270	if (kd == NULL) {
271		errno = EINVAL;
272		return (-1);
273	}
274	if (kd->pmfd >= 0)
275		error |= close(kd->pmfd);
276	if (kd->vmfd >= 0)
277		error |= close(kd->vmfd);
278	if (kd->nlfd >= 0)
279		error |= close(kd->nlfd);
280	if (kd->vmst)
281		_kvm_freevtop(kd);
282	if (kd->procbase != 0)
283		free((void *)kd->procbase);
284	if (kd->argbuf != 0)
285		free((void *) kd->argbuf);
286	if (kd->argspc != 0)
287		free((void *) kd->argspc);
288	if (kd->argv != 0)
289		free((void *)kd->argv);
290	free((void *)kd);
291
292	return (error);
293}
294
295/*
296 * Walk the list of unresolved symbols, generate a new list and prefix the
297 * symbol names, try again, and merge back what we could resolve.
298 */
299static int
300kvm_fdnlist_prefix(kvm_t *kd, struct nlist *nl, int missing, const char *prefix,
301    uintptr_t (*validate_fn)(kvm_t *, uintptr_t))
302{
303	struct nlist *n, *np, *p;
304	char *cp, *ce;
305	const char *ccp;
306	size_t len;
307	int slen, unresolved;
308
309	/*
310	 * Calculate the space we need to malloc for nlist and names.
311	 * We are going to store the name twice for later lookups: once
312	 * with the prefix and once the unmodified name delmited by \0.
313	 */
314	len = 0;
315	unresolved = 0;
316	for (p = nl; p->n_name && p->n_name[0]; ++p) {
317		if (p->n_type != N_UNDF)
318			continue;
319		len += sizeof(struct nlist) + strlen(prefix) +
320		    2 * (strlen(p->n_name) + 1);
321		unresolved++;
322	}
323	if (unresolved == 0)
324		return (unresolved);
325	/* Add space for the terminating nlist entry. */
326	len += sizeof(struct nlist);
327	unresolved++;
328
329	/* Alloc one chunk for (nlist, [names]) and setup pointers. */
330	n = np = malloc(len);
331	bzero(n, len);
332	if (n == NULL)
333		return (missing);
334	cp = ce = (char *)np;
335	cp += unresolved * sizeof(struct nlist);
336	ce += len;
337
338	/* Generate shortened nlist with special prefix. */
339	unresolved = 0;
340	for (p = nl; p->n_name && p->n_name[0]; ++p) {
341		if (p->n_type != N_UNDF)
342			continue;
343		bcopy(p, np, sizeof(struct nlist));
344		/* Save the new\0orig. name so we can later match it again. */
345		slen = snprintf(cp, ce - cp, "%s%s%c%s", prefix,
346		    (prefix[0] != '\0' && p->n_name[0] == '_') ?
347			(p->n_name + 1) : p->n_name, '\0', p->n_name);
348		if (slen < 0 || slen >= ce - cp)
349			continue;
350		np->n_name = cp;
351		cp += slen + 1;
352		np++;
353		unresolved++;
354	}
355
356	/* Do lookup on the reduced list. */
357	np = n;
358	unresolved = __fdnlist(kd->nlfd, np);
359
360	/* Check if we could resolve further symbols and update the list. */
361	if (unresolved >= 0 && unresolved < missing) {
362		/* Find the first freshly resolved entry. */
363		for (; np->n_name && np->n_name[0]; np++)
364			if (np->n_type != N_UNDF)
365				break;
366		/*
367		 * The lists are both in the same order,
368		 * so we can walk them in parallel.
369		 */
370		for (p = nl; np->n_name && np->n_name[0] &&
371		    p->n_name && p->n_name[0]; ++p) {
372			if (p->n_type != N_UNDF)
373				continue;
374			/* Skip expanded name and compare to orig. one. */
375			ccp = np->n_name + strlen(np->n_name) + 1;
376			if (strcmp(ccp, p->n_name) != 0)
377				continue;
378			/* Update nlist with new, translated results. */
379			p->n_type = np->n_type;
380			p->n_other = np->n_other;
381			p->n_desc = np->n_desc;
382			if (validate_fn)
383				p->n_value = (*validate_fn)(kd, np->n_value);
384			else
385				p->n_value = np->n_value;
386			missing--;
387			/* Find next freshly resolved entry. */
388			for (np++; np->n_name && np->n_name[0]; np++)
389				if (np->n_type != N_UNDF)
390					break;
391		}
392	}
393	/* We could assert missing = unresolved here. */
394
395	free(n);
396	return (unresolved);
397}
398
399int
400_kvm_nlist(kvm_t *kd, struct nlist *nl, int initialize)
401{
402	struct nlist *p;
403	int nvalid;
404	struct kld_sym_lookup lookup;
405	int error;
406	const char *prefix = "";
407	char symname[1024]; /* XXX-BZ symbol name length limit? */
408	int tried_vnet, tried_dpcpu;
409
410	/*
411	 * If we can't use the kld symbol lookup, revert to the
412	 * slow library call.
413	 */
414	if (!ISALIVE(kd)) {
415		error = __fdnlist(kd->nlfd, nl);
416		if (error <= 0)			/* Hard error or success. */
417			return (error);
418
419		if (_kvm_vnet_initialized(kd, initialize))
420			error = kvm_fdnlist_prefix(kd, nl, error,
421			    VNET_SYMPREFIX, _kvm_vnet_validaddr);
422
423		if (error > 0 && _kvm_dpcpu_initialized(kd, initialize))
424			error = kvm_fdnlist_prefix(kd, nl, error,
425			    DPCPU_SYMPREFIX, _kvm_dpcpu_validaddr);
426
427		return (error);
428	}
429
430	/*
431	 * We can use the kld lookup syscall.  Go through each nlist entry
432	 * and look it up with a kldsym(2) syscall.
433	 */
434	nvalid = 0;
435	tried_vnet = 0;
436	tried_dpcpu = 0;
437again:
438	for (p = nl; p->n_name && p->n_name[0]; ++p) {
439		if (p->n_type != N_UNDF)
440			continue;
441
442		lookup.version = sizeof(lookup);
443		lookup.symvalue = 0;
444		lookup.symsize = 0;
445
446		error = snprintf(symname, sizeof(symname), "%s%s", prefix,
447		    (prefix[0] != '\0' && p->n_name[0] == '_') ?
448			(p->n_name + 1) : p->n_name);
449		if (error < 0 || error >= (int)sizeof(symname))
450			continue;
451		lookup.symname = symname;
452		if (lookup.symname[0] == '_')
453			lookup.symname++;
454
455		if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) {
456			p->n_type = N_TEXT;
457			p->n_other = 0;
458			p->n_desc = 0;
459			if (_kvm_vnet_initialized(kd, initialize) &&
460			    strcmp(prefix, VNET_SYMPREFIX) == 0)
461				p->n_value =
462				    _kvm_vnet_validaddr(kd, lookup.symvalue);
463			else if (_kvm_dpcpu_initialized(kd, initialize) &&
464			    strcmp(prefix, DPCPU_SYMPREFIX) == 0)
465				p->n_value =
466				    _kvm_dpcpu_validaddr(kd, lookup.symvalue);
467			else
468				p->n_value = lookup.symvalue;
469			++nvalid;
470			/* lookup.symsize */
471		}
472	}
473
474	/*
475	 * Check the number of entries that weren't found. If they exist,
476	 * try again with a prefix for virtualized or DPCPU symbol names.
477	 */
478	error = ((p - nl) - nvalid);
479	if (error && _kvm_vnet_initialized(kd, initialize) && !tried_vnet) {
480		tried_vnet = 1;
481		prefix = VNET_SYMPREFIX;
482		goto again;
483	}
484	if (error && _kvm_dpcpu_initialized(kd, initialize) && !tried_dpcpu) {
485		tried_dpcpu = 1;
486		prefix = DPCPU_SYMPREFIX;
487		goto again;
488	}
489
490	/*
491	 * Return the number of entries that weren't found. If they exist,
492	 * also fill internal error buffer.
493	 */
494	error = ((p - nl) - nvalid);
495	if (error)
496		_kvm_syserr(kd, kd->program, "kvm_nlist");
497	return (error);
498}
499
500int
501kvm_nlist(kvm_t *kd, struct nlist *nl)
502{
503
504	/*
505	 * If called via the public interface, permit intialization of
506	 * further virtualized modules on demand.
507	 */
508	return (_kvm_nlist(kd, nl, 1));
509}
510
511ssize_t
512kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len)
513{
514	int cc;
515	ssize_t cr;
516	off_t pa;
517	char *cp;
518
519	if (ISALIVE(kd)) {
520		/*
521		 * We're using /dev/kmem.  Just read straight from the
522		 * device and let the active kernel do the address translation.
523		 */
524		errno = 0;
525		if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
526			_kvm_err(kd, 0, "invalid address (%lx)", kva);
527			return (-1);
528		}
529		cr = read(kd->vmfd, buf, len);
530		if (cr < 0) {
531			_kvm_syserr(kd, 0, "kvm_read");
532			return (-1);
533		} else if (cr < (ssize_t)len)
534			_kvm_err(kd, kd->program, "short read");
535		return (cr);
536	}
537
538	cp = buf;
539	while (len > 0) {
540		cc = _kvm_kvatop(kd, kva, &pa);
541		if (cc == 0)
542			return (-1);
543		if (cc > (ssize_t)len)
544			cc = len;
545		errno = 0;
546		if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
547			_kvm_syserr(kd, 0, _PATH_MEM);
548			break;
549		}
550		cr = read(kd->pmfd, cp, cc);
551		if (cr < 0) {
552			_kvm_syserr(kd, kd->program, "kvm_read");
553			break;
554		}
555		/*
556		 * If kvm_kvatop returns a bogus value or our core file is
557		 * truncated, we might wind up seeking beyond the end of the
558		 * core file in which case the read will return 0 (EOF).
559		 */
560		if (cr == 0)
561			break;
562		cp += cr;
563		kva += cr;
564		len -= cr;
565	}
566
567	return (cp - (char *)buf);
568}
569
570ssize_t
571kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
572{
573	int cc;
574	ssize_t cw;
575	off_t pa;
576	const char *cp;
577
578	if (!ISALIVE(kd) && !kd->writable) {
579		_kvm_err(kd, kd->program,
580		    "kvm_write not implemented for dead kernels");
581		return (-1);
582	}
583
584	if (ISALIVE(kd)) {
585		/*
586		 * Just like kvm_read, only we write.
587		 */
588		errno = 0;
589		if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
590			_kvm_err(kd, 0, "invalid address (%lx)", kva);
591			return (-1);
592		}
593		cc = write(kd->vmfd, buf, len);
594		if (cc < 0) {
595			_kvm_syserr(kd, 0, "kvm_write");
596			return (-1);
597		} else if ((size_t)cc < len)
598			_kvm_err(kd, kd->program, "short write");
599		return (cc);
600	}
601
602	cp = buf;
603	while (len > 0) {
604		cc = _kvm_kvatop(kd, kva, &pa);
605		if (cc == 0)
606			return (-1);
607		if (cc > (ssize_t)len)
608			cc = len;
609		errno = 0;
610		if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
611			_kvm_syserr(kd, 0, _PATH_MEM);
612			break;
613		}
614		cw = write(kd->pmfd, cp, cc);
615		if (cw < 0) {
616			_kvm_syserr(kd, kd->program, "kvm_write");
617			break;
618		}
619		/*
620		 * If ka_kvatop returns a bogus value or our core file is
621		 * truncated, we might wind up seeking beyond the end of the
622		 * core file in which case the read will return 0 (EOF).
623		 */
624		if (cw == 0)
625			break;
626		cp += cw;
627		kva += cw;
628		len -= cw;
629	}
630
631	return (cp - (const char *)buf);
632}
633