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 * 3. 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 * @(#)kvm.c 8.2 (Berkeley) 2/13/94 34 * $FreeBSD: src/lib/libkvm/kvm.c,v 1.12.2.3 2002/09/13 14:53:43 nectar Exp $ 35 */ 36 37 #include <sys/user.h> /* MUST BE FIRST */ 38 #include <sys/param.h> 39 #include <sys/proc.h> 40 #include <sys/ioctl.h> 41 #include <sys/stat.h> 42 #include <sys/sysctl.h> 43 #include <sys/linker.h> 44 45 #include <vm/vm.h> 46 #include <vm/vm_param.h> 47 #include <vm/swap_pager.h> 48 49 #include <machine/vmparam.h> 50 51 #include <ctype.h> 52 #include <fcntl.h> 53 #include <kvm.h> 54 #include <limits.h> 55 #include <nlist.h> 56 #include <paths.h> 57 #include <stdio.h> 58 #include <stdlib.h> 59 #include <string.h> 60 #include <stdarg.h> 61 #include <unistd.h> 62 63 #include "kvm_private.h" 64 65 /* from src/lib/libc/gen/nlist.c */ 66 int __fdnlist (int, struct nlist *); 67 68 char * 69 kvm_geterr(kvm_t *kd) 70 { 71 return (kd->errbuf); 72 } 73 74 /* 75 * Report an error using printf style arguments. "program" is kd->program 76 * on hard errors, and 0 on soft errors, so that under sun error emulation, 77 * only hard errors are printed out (otherwise, programs like gdb will 78 * generate tons of error messages when trying to access bogus pointers). 79 */ 80 void 81 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 82 { 83 va_list ap; 84 85 va_start(ap, fmt); 86 if (program != NULL) { 87 (void)fprintf(stderr, "%s: ", program); 88 (void)vfprintf(stderr, fmt, ap); 89 (void)fputc('\n', stderr); 90 } else 91 (void)vsnprintf(kd->errbuf, 92 sizeof(kd->errbuf), (char *)fmt, ap); 93 94 va_end(ap); 95 } 96 97 void 98 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 99 { 100 va_list ap; 101 int n; 102 103 va_start(ap, fmt); 104 if (program != NULL) { 105 (void)fprintf(stderr, "%s: ", program); 106 (void)vfprintf(stderr, fmt, ap); 107 (void)fprintf(stderr, ": %s\n", strerror(errno)); 108 } else { 109 char *cp = kd->errbuf; 110 111 (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 112 n = strlen(cp); 113 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 114 strerror(errno)); 115 } 116 va_end(ap); 117 } 118 119 void * 120 _kvm_malloc(kvm_t *kd, size_t n) 121 { 122 void *p; 123 124 if ((p = calloc(n, sizeof(char))) == NULL) 125 _kvm_err(kd, kd->program, "can't allocate %zd bytes: %s", 126 n, strerror(errno)); 127 return (p); 128 } 129 130 static int 131 is_proc_mem(const char *p) 132 { 133 static char proc[] = "/proc/"; 134 static char mem[] = "/mem"; 135 if (strncmp(proc, p, sizeof(proc) - 1)) 136 return 0; 137 p += sizeof(proc) - 1; 138 for (; p != '\0'; ++p) 139 if (!isdigit(*p)) 140 break; 141 if (!isdigit(*(p - 1))) 142 return 0; 143 return !strncmp(p, mem, sizeof(mem) - 1); 144 } 145 146 static kvm_t * 147 _kvm_open(kvm_t *kd, const char *uf, const char *mf, int flag, char *errout) 148 { 149 struct stat st; 150 151 kd->vmfd = -1; 152 kd->pmfd = -1; 153 kd->nlfd = -1; 154 kd->vmst = 0; 155 kd->procbase = NULL; 156 kd->procend = NULL; 157 kd->argspc = 0; 158 kd->argv = 0; 159 kd->flags = 0; 160 161 if (uf == NULL) 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 == NULL) 172 mf = _PATH_MEM; 173 174 if ((kd->pmfd = open(mf, flag, 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 (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) { 183 _kvm_syserr(kd, kd->program, "%s", mf); 184 goto failed; 185 } 186 if (S_ISCHR(st.st_mode)) { 187 /* 188 * If this is a character special device, then check that 189 * it's /dev/mem. If so, open kmem too. (Maybe we should 190 * make it work for either /dev/mem or /dev/kmem -- in either 191 * case you're working with a live kernel.) 192 */ 193 if (strcmp(mf, _PATH_DEVNULL) == 0) { 194 kd->vmfd = open(_PATH_DEVNULL, O_RDONLY); 195 } else { 196 if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 197 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 198 goto failed; 199 } 200 if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) { 201 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 202 goto failed; 203 } 204 } 205 kd->flags |= KVMF_HOST; 206 } else { 207 /* 208 * Crash dump or vkernel /proc/$pid/mem file: 209 * can't use kldsym, we are going to need ->nlfd 210 */ 211 if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 212 _kvm_syserr(kd, kd->program, "%s", uf); 213 goto failed; 214 } 215 if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) { 216 _kvm_syserr(kd, kd->program, "%s", uf); 217 goto failed; 218 } 219 if(is_proc_mem(mf)) { 220 /* 221 * It's /proc/$pid/mem, so we rely on the host 222 * kernel to do address translation for us. 223 */ 224 kd->vmfd = kd->pmfd; 225 kd->pmfd = -1; 226 kd->flags |= KVMF_VKERN; 227 } else { 228 if (st.st_size <= 0) { 229 errno = EINVAL; 230 _kvm_syserr(kd, kd->program, "empty file"); 231 goto failed; 232 } 233 234 /* 235 * This is a crash dump. 236 * Initialize the virtual address translation machinery, 237 * but first setup the namelist fd. 238 */ 239 if (_kvm_initvtop(kd) < 0) 240 goto failed; 241 } 242 } 243 return (kd); 244 failed: 245 /* 246 * Copy out the error if doing sane error semantics. 247 */ 248 if (errout != NULL) 249 strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 250 (void)kvm_close(kd); 251 return (0); 252 } 253 254 kvm_t * 255 kvm_openfiles(const char *uf, const char *mf, const char *sf, int flag, 256 char *errout) 257 { 258 kvm_t *kd; 259 260 if ((kd = malloc(sizeof(*kd))) == NULL) { 261 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 262 return (0); 263 } 264 memset(kd, 0, sizeof(*kd)); 265 kd->program = 0; 266 return (_kvm_open(kd, uf, mf, flag, errout)); 267 } 268 269 kvm_t * 270 kvm_open(const char *uf, const char *mf, const char *sf, int flag, 271 const char *errstr) 272 { 273 kvm_t *kd; 274 275 if ((kd = malloc(sizeof(*kd))) == NULL) { 276 if (errstr != NULL) 277 (void)fprintf(stderr, "%s: %s\n", 278 errstr, strerror(errno)); 279 return (0); 280 } 281 memset(kd, 0, sizeof(*kd)); 282 kd->program = errstr; 283 return (_kvm_open(kd, uf, mf, flag, NULL)); 284 } 285 286 int 287 kvm_close(kvm_t *kd) 288 { 289 int error = 0; 290 291 if (kd->pmfd >= 0) 292 error |= close(kd->pmfd); 293 if (kd->vmfd >= 0) 294 error |= close(kd->vmfd); 295 if (kd->nlfd >= 0) 296 error |= close(kd->nlfd); 297 if (kd->vmst) 298 _kvm_freevtop(kd); 299 if (kd->procbase != NULL) 300 free(kd->procbase); 301 if (kd->argv != 0) 302 free((void *)kd->argv); 303 free((void *)kd); 304 305 return (0); 306 } 307 308 int 309 kvm_nlist(kvm_t *kd, struct nlist *nl) 310 { 311 struct nlist *p; 312 int nvalid; 313 struct kld_sym_lookup lookup; 314 int error; 315 316 /* 317 * If we can't use the kld symbol lookup, revert to the 318 * slow library call. 319 */ 320 if (!kvm_ishost(kd)) 321 return (__fdnlist(kd->nlfd, nl)); 322 323 /* 324 * We can use the kld lookup syscall. Go through each nlist entry 325 * and look it up with a kldsym(2) syscall. 326 */ 327 nvalid = 0; 328 for (p = nl; p->n_name && p->n_name[0]; ++p) { 329 lookup.version = sizeof(lookup); 330 lookup.symname = p->n_name; 331 lookup.symvalue = 0; 332 lookup.symsize = 0; 333 334 if (lookup.symname[0] == '_') 335 lookup.symname++; 336 337 if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { 338 p->n_type = N_TEXT; 339 p->n_other = 0; 340 p->n_desc = 0; 341 p->n_value = lookup.symvalue; 342 ++nvalid; 343 /* lookup.symsize */ 344 } 345 } 346 /* 347 * Return the number of entries that weren't found. If they exist, 348 * also fill internal error buffer. 349 */ 350 error = ((p - nl) - nvalid); 351 if (error) 352 _kvm_syserr(kd, kd->program, "kvm_nlist"); 353 return (error); 354 } 355 356 ssize_t 357 kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len) 358 { 359 int cc; 360 void *cp; 361 362 if (kvm_notrans(kd)) { 363 /* 364 * We're using /dev/kmem. Just read straight from the 365 * device and let the active kernel do the address translation. 366 */ 367 errno = 0; 368 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 369 _kvm_err(kd, 0, "invalid address (%lx)", kva); 370 return (-1); 371 } 372 373 /* 374 * Try to pre-fault the user memory to reduce instances of 375 * races within the kernel. XXX workaround for kernel bug 376 * where kernel does a sanity check, but user faults during 377 * the copy can block and race against another kernel entity 378 * unmapping the memory in question. 379 */ 380 bzero(buf, len); 381 cc = read(kd->vmfd, buf, len); 382 if (cc < 0) { 383 _kvm_syserr(kd, 0, "kvm_read"); 384 return (-1); 385 } else if (cc < len) 386 _kvm_err(kd, kd->program, "short read"); 387 return (cc); 388 } else { 389 cp = buf; 390 while (len > 0) { 391 off_t pa; 392 393 cc = _kvm_kvatop(kd, kva, &pa); 394 if (cc == 0) 395 return (-1); 396 if (cc > len) 397 cc = len; 398 errno = 0; 399 if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) { 400 _kvm_syserr(kd, 0, _PATH_MEM); 401 break; 402 } 403 bzero(cp, cc); 404 cc = read(kd->pmfd, cp, cc); 405 if (cc < 0) { 406 _kvm_syserr(kd, kd->program, "kvm_read"); 407 break; 408 } 409 /* 410 * If kvm_kvatop returns a bogus value or our core 411 * file is truncated, we might wind up seeking beyond 412 * the end of the core file in which case the read will 413 * return 0 (EOF). 414 */ 415 if (cc == 0) 416 break; 417 cp = (char *)cp + cc; 418 kva += cc; 419 len -= cc; 420 } 421 return ((char *)cp - (char *)buf); 422 } 423 /* NOTREACHED */ 424 } 425 426 char * 427 kvm_readstr(kvm_t *kd, u_long kva, char *buf, size_t *lenp) 428 { 429 size_t len, cc, pos; 430 char ch; 431 int asize = -1; 432 433 if (buf == NULL) { 434 asize = len = 16; 435 buf = malloc(len); 436 if (buf == NULL) { 437 _kvm_syserr(kd, kd->program, "kvm_readstr"); 438 return NULL; 439 } 440 } else { 441 len = *lenp; 442 } 443 444 if (kvm_notrans(kd)) { 445 /* 446 * We're using /dev/kmem. Just read straight from the 447 * device and let the active kernel do the address translation. 448 */ 449 errno = 0; 450 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 451 _kvm_err(kd, 0, "invalid address (%lx)", kva); 452 return NULL; 453 } 454 455 for (pos = 0, ch = -1; ch != 0; pos++) { 456 cc = read(kd->vmfd, &ch, 1); 457 if ((ssize_t)cc < 0) { 458 _kvm_syserr(kd, 0, "kvm_readstr"); 459 return NULL; 460 } else if (cc < 1) 461 _kvm_err(kd, kd->program, "short read"); 462 if (pos == asize) { 463 buf = realloc(buf, asize *= 2); 464 if (buf == NULL) { 465 _kvm_syserr(kd, kd->program, "kvm_readstr"); 466 return NULL; 467 } 468 len = asize; 469 } 470 if (pos < len) 471 buf[pos] = ch; 472 } 473 474 if (lenp != NULL) 475 *lenp = pos; 476 if (pos > len) 477 return NULL; 478 else 479 return buf; 480 } else { 481 size_t left = 0; 482 for (pos = 0, ch = -1; ch != 0; pos++, left--, kva++) { 483 if (left == 0) { 484 off_t pa; 485 486 left = _kvm_kvatop(kd, kva, &pa); 487 if (left == 0) 488 return NULL; 489 errno = 0; 490 if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { 491 _kvm_syserr(kd, 0, _PATH_MEM); 492 return NULL; 493 } 494 } 495 cc = read(kd->pmfd, &ch, 1); 496 if ((ssize_t)cc < 0) { 497 _kvm_syserr(kd, 0, "kvm_readstr"); 498 return NULL; 499 } else if (cc < 1) 500 _kvm_err(kd, kd->program, "short read"); 501 if (pos == asize) { 502 buf = realloc(buf, asize *= 2); 503 if (buf == NULL) { 504 _kvm_syserr(kd, kd->program, "kvm_readstr"); 505 return NULL; 506 } 507 len = asize; 508 } 509 if (pos < len) 510 buf[pos] = ch; 511 } 512 513 if (lenp != NULL) 514 *lenp = pos; 515 if (pos > len) 516 return NULL; 517 else 518 return buf; 519 } 520 /* NOTREACHED */ 521 } 522 523 ssize_t 524 kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len) 525 { 526 int cc; 527 528 if (kvm_notrans(kd)) { 529 /* 530 * Just like kvm_read, only we write. 531 */ 532 errno = 0; 533 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 534 _kvm_err(kd, 0, "invalid address (%lx)", kva); 535 return (-1); 536 } 537 cc = write(kd->vmfd, buf, len); 538 if (cc < 0) { 539 _kvm_syserr(kd, 0, "kvm_write"); 540 return (-1); 541 } else if (cc < len) 542 _kvm_err(kd, kd->program, "short write"); 543 return (cc); 544 } else { 545 _kvm_err(kd, kd->program, 546 "kvm_write not implemented for dead kernels"); 547 return (-1); 548 } 549 /* NOTREACHED */ 550 } 551