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