1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2011, Joyent Inc. All rights reserved. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/time.h> 33 #include <sys/sysmacros.h> 34 #include <sys/proc.h> 35 #include <sys/systm.h> 36 #include <sys/cred.h> 37 #include <sys/user.h> 38 #include <sys/utsname.h> 39 #include <sys/errno.h> 40 #include <sys/signal.h> 41 #include <sys/siginfo.h> 42 #include <sys/fault.h> 43 #include <sys/syscall.h> 44 #include <sys/ucontext.h> 45 #include <sys/prsystm.h> 46 #include <sys/vnode.h> 47 #include <sys/var.h> 48 #include <sys/file.h> 49 #include <sys/pathname.h> 50 #include <sys/vfs.h> 51 #include <sys/exec.h> 52 #include <sys/debug.h> 53 #include <sys/stack.h> 54 #include <sys/kmem.h> 55 #include <sys/schedctl.h> 56 #include <sys/core.h> 57 #include <sys/corectl.h> 58 #include <sys/cmn_err.h> 59 #include <vm/as.h> 60 #include <sys/rctl.h> 61 #include <sys/nbmlock.h> 62 #include <sys/stat.h> 63 #include <sys/zone.h> 64 #include <sys/contract/process_impl.h> 65 #include <sys/ddi.h> 66 67 /* 68 * Processes running within a zone potentially dump core in 3 locations, 69 * based on the per-process, per-zone, and the global zone's core settings. 70 * 71 * Per-zone and global zone settings are often referred to as "global" 72 * settings since they apply to the system (or zone) as a whole, as 73 * opposed to a particular process. 74 */ 75 enum core_types { 76 CORE_PROC, /* Use per-process settings */ 77 CORE_ZONE, /* Use per-zone settings */ 78 CORE_GLOBAL /* Use global zone settings */ 79 }; 80 81 /* 82 * Log information about "global" core dumps to syslog. 83 */ 84 static void 85 core_log(struct core_globals *cg, int error, const char *why, const char *path, 86 zoneid_t zoneid) 87 { 88 proc_t *p = curproc; 89 pid_t pid = p->p_pid; 90 char *fn = PTOU(p)->u_comm; 91 92 if (!(cg->core_options & CC_GLOBAL_LOG)) 93 return; 94 95 if (path == NULL) 96 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s", fn, pid, why); 97 else if (error == 0) 98 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s: %s", fn, pid, 99 why, path); 100 else 101 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s, errno=%d: %s", 102 fn, pid, why, error, path); 103 } 104 105 /* 106 * Private version of vn_remove(). 107 * Refuse to unlink a directory or an unwritable file. 108 * Also allow the process to access files normally inaccessible due to 109 * chroot(2) or Zone limitations. 110 */ 111 static int 112 remove_core_file(char *fp, enum core_types core_type) 113 { 114 vnode_t *vp = NULL; /* entry vnode */ 115 vnode_t *dvp; /* ptr to parent dir vnode */ 116 vfs_t *dvfsp; 117 int error; 118 int in_crit = 0; 119 pathname_t pn; /* name of entry */ 120 vnode_t *startvp, *rootvp; 121 122 if ((error = pn_get(fp, UIO_SYSSPACE, &pn)) != 0) 123 return (error); 124 /* 125 * Determine what rootvp to use. 126 */ 127 if (core_type == CORE_PROC) { 128 rootvp = (PTOU(curproc)->u_rdir == NULL ? 129 curproc->p_zone->zone_rootvp : PTOU(curproc)->u_rdir); 130 startvp = (fp[0] == '/' ? rootvp : PTOU(curproc)->u_cdir); 131 } else if (core_type == CORE_ZONE) { 132 startvp = curproc->p_zone->zone_rootvp; 133 rootvp = curproc->p_zone->zone_rootvp; 134 } else { 135 ASSERT(core_type == CORE_GLOBAL); 136 startvp = rootdir; 137 rootvp = rootdir; 138 } 139 VN_HOLD(startvp); 140 if (rootvp != rootdir) 141 VN_HOLD(rootvp); 142 if ((error = lookuppnvp(&pn, NULL, NO_FOLLOW, &dvp, &vp, rootvp, 143 startvp, CRED())) != 0) { 144 pn_free(&pn); 145 return (error); 146 } 147 /* 148 * Succeed if there is no file. 149 * Fail if the file is not a regular file. 150 * Fail if the filesystem is mounted read-only. 151 * Fail if the file is not writeable. 152 * Fail if the file has NBMAND share reservations. 153 */ 154 if (vp == NULL) 155 error = 0; 156 else if (vp->v_type != VREG) 157 error = EACCES; 158 else if ((dvfsp = dvp->v_vfsp) != NULL && 159 (dvfsp->vfs_flag & VFS_RDONLY)) 160 error = EROFS; 161 else if ((error = VOP_ACCESS(vp, VWRITE, 0, CRED(), NULL)) == 0) { 162 if (nbl_need_check(vp)) { 163 nbl_start_crit(vp, RW_READER); 164 in_crit = 1; 165 if (nbl_share_conflict(vp, NBL_REMOVE, NULL)) { 166 error = EACCES; 167 } 168 } 169 if (!error) { 170 error = VOP_REMOVE(dvp, pn.pn_path, CRED(), NULL, 0); 171 } 172 } 173 174 pn_free(&pn); 175 if (vp != NULL) { 176 if (in_crit) 177 nbl_end_crit(vp); 178 VN_RELE(vp); 179 } 180 VN_RELE(dvp); 181 return (error); 182 } 183 184 /* 185 * Create the core file in a location that may be normally inaccessible due 186 * to chroot(2) or Zone limitations. 187 */ 188 static int 189 create_core_file(char *fp, enum core_types core_type, vnode_t **vpp) 190 { 191 int error; 192 mode_t perms = (S_IRUSR | S_IWUSR); 193 pathname_t pn; 194 char *file; 195 vnode_t *vp; 196 vnode_t *dvp; 197 vattr_t vattr; 198 cred_t *credp = CRED(); 199 200 if (core_type == CORE_PROC) { 201 file = fp; 202 dvp = NULL; /* regular lookup */ 203 } else { 204 vnode_t *startvp, *rootvp; 205 206 ASSERT(core_type == CORE_ZONE || core_type == CORE_GLOBAL); 207 /* 208 * This is tricky because we want to dump the core in 209 * a location which may normally be inaccessible 210 * to us (due to chroot(2) limitations, or zone 211 * membership), and hence need to overcome u_rdir 212 * restrictions. The basic idea is to separate 213 * the path from the filename, lookup the 214 * pathname separately (starting from the global 215 * zone's root directory), and then open the 216 * file starting at the directory vnode. 217 */ 218 if (error = pn_get(fp, UIO_SYSSPACE, &pn)) 219 return (error); 220 221 if (core_type == CORE_ZONE) { 222 startvp = rootvp = curproc->p_zone->zone_rootvp; 223 } else { 224 startvp = rootvp = rootdir; 225 } 226 /* 227 * rootvp and startvp will be VN_RELE()'d by lookuppnvp() if 228 * necessary. 229 */ 230 VN_HOLD(startvp); 231 if (rootvp != rootdir) 232 VN_HOLD(rootvp); 233 /* 234 * Do a lookup on the full path, ignoring the actual file, but 235 * finding the vnode for the directory. It's OK if the file 236 * doesn't exist -- it most likely won't since we just removed 237 * it. 238 */ 239 error = lookuppnvp(&pn, NULL, FOLLOW, &dvp, NULLVPP, 240 rootvp, startvp, credp); 241 pn_free(&pn); 242 if (error != 0) 243 return (error); 244 ASSERT(dvp != NULL); 245 /* 246 * Now find the final component in the path (ie, the name of 247 * the core file). 248 */ 249 if (error = pn_get(fp, UIO_SYSSPACE, &pn)) { 250 VN_RELE(dvp); 251 return (error); 252 } 253 pn_setlast(&pn); 254 file = pn.pn_path; 255 } 256 error = vn_openat(file, UIO_SYSSPACE, 257 FWRITE | FTRUNC | FEXCL | FCREAT | FOFFMAX, 258 perms, &vp, CRCREAT, PTOU(curproc)->u_cmask, dvp, -1); 259 if (core_type != CORE_PROC) { 260 VN_RELE(dvp); 261 pn_free(&pn); 262 } 263 /* 264 * Don't dump a core file owned by "nobody". 265 */ 266 vattr.va_mask = AT_UID; 267 if (error == 0 && 268 (VOP_GETATTR(vp, &vattr, 0, credp, NULL) != 0 || 269 vattr.va_uid != crgetuid(credp))) { 270 (void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, 271 credp, NULL); 272 VN_RELE(vp); 273 (void) remove_core_file(fp, core_type); 274 error = EACCES; 275 } 276 *vpp = vp; 277 return (error); 278 } 279 280 /* 281 * Install the specified held cred into the process, and return a pointer to 282 * the held cred which was previously the value of p->p_cred. 283 */ 284 static cred_t * 285 set_cred(proc_t *p, cred_t *newcr) 286 { 287 cred_t *oldcr; 288 uid_t olduid, newuid; 289 290 /* 291 * Place a hold on the existing cred, and then install the new 292 * cred into the proc structure. 293 */ 294 mutex_enter(&p->p_crlock); 295 oldcr = p->p_cred; 296 crhold(oldcr); 297 p->p_cred = newcr; 298 mutex_exit(&p->p_crlock); 299 300 ASSERT(crgetzoneid(oldcr) == crgetzoneid(newcr)); 301 302 /* 303 * If the real uid is changing, keep the per-user process 304 * counts accurate. 305 */ 306 olduid = crgetruid(oldcr); 307 newuid = crgetruid(newcr); 308 if (olduid != newuid) { 309 zoneid_t zoneid = crgetzoneid(newcr); 310 311 mutex_enter(&pidlock); 312 upcount_dec(olduid, zoneid); 313 upcount_inc(newuid, zoneid); 314 mutex_exit(&pidlock); 315 } 316 317 /* 318 * Broadcast the new cred to all the other threads. The old 319 * cred can be safely returned because we have a hold on it. 320 */ 321 crset(p, newcr); 322 return (oldcr); 323 } 324 325 static int 326 do_core(char *fp, int sig, enum core_types core_type, struct core_globals *cg) 327 { 328 proc_t *p = curproc; 329 cred_t *credp = CRED(); 330 rlim64_t rlimit; 331 vnode_t *vp; 332 int error = 0; 333 struct execsw *eswp; 334 cred_t *ocredp = NULL; 335 int is_setid = 0; 336 core_content_t content; 337 uid_t uid; 338 gid_t gid; 339 340 if (core_type == CORE_GLOBAL || core_type == CORE_ZONE) { 341 mutex_enter(&cg->core_lock); 342 content = cg->core_content; 343 mutex_exit(&cg->core_lock); 344 rlimit = cg->core_rlimit; 345 } else { 346 mutex_enter(&p->p_lock); 347 rlimit = rctl_enforced_value(rctlproc_legacy[RLIMIT_CORE], 348 p->p_rctls, p); 349 content = corectl_content_value(p->p_content); 350 mutex_exit(&p->p_lock); 351 } 352 353 if (rlimit == 0) 354 return (EFBIG); 355 356 /* 357 * If SNOCD is set, or if the effective, real, and saved ids do 358 * not match up, no one but a privileged user is allowed to view 359 * this core file. Set the credentials and the owner to root. 360 */ 361 if ((p->p_flag & SNOCD) || 362 (uid = crgetuid(credp)) != crgetruid(credp) || 363 uid != crgetsuid(credp) || 364 (gid = crgetgid(credp)) != crgetrgid(credp) || 365 gid != crgetsgid(credp)) { 366 /* 367 * Because this is insecure against certain forms of file 368 * system attack, do it only if set-id core files have been 369 * enabled via corectl(CC_GLOBAL_SETID | CC_PROCESS_SETID). 370 */ 371 if (((core_type == CORE_GLOBAL || core_type == CORE_ZONE) && 372 !(cg->core_options & CC_GLOBAL_SETID)) || 373 (core_type == CORE_PROC && 374 !(cg->core_options & CC_PROCESS_SETID))) 375 return (ENOTSUP); 376 377 is_setid = 1; 378 } 379 380 /* 381 * If we are doing a "global" core dump or a set-id core dump, 382 * use kcred to do the dumping. 383 */ 384 if (core_type == CORE_GLOBAL || core_type == CORE_ZONE || is_setid) { 385 /* 386 * Use the zone's "kcred" to prevent privilege 387 * escalation. 388 */ 389 credp = zone_get_kcred(getzoneid()); 390 ASSERT(credp != NULL); 391 ocredp = set_cred(p, credp); 392 } 393 394 /* 395 * First remove any existing core file, then 396 * open the new core file with (O_EXCL|O_CREAT). 397 * 398 * The reasons for doing this are manifold: 399 * 400 * For security reasons, we don't want root processes 401 * to dump core through a symlink because that would 402 * allow a malicious user to clobber any file on 403 * the system if s/he could convince a root process, 404 * perhaps a set-uid root process that s/he started, 405 * to dump core in a directory writable by that user. 406 * Similar security reasons apply to hard links. 407 * For symmetry we do this unconditionally, not 408 * just for root processes. 409 * 410 * If the process has the core file mmap()d into the 411 * address space, we would be modifying the address 412 * space that we are trying to dump if we did not first 413 * remove the core file. (The command "file core" 414 * is the canonical example of this possibility.) 415 * 416 * Opening the core file with O_EXCL|O_CREAT ensures than 417 * two concurrent core dumps don't clobber each other. 418 * One is bound to lose; we don't want to make both lose. 419 */ 420 if ((error = remove_core_file(fp, core_type)) == 0) { 421 error = create_core_file(fp, core_type, &vp); 422 } 423 424 /* 425 * Now that vn_open is complete, reset the process's credentials if 426 * we changed them, and make 'credp' point to kcred used 427 * above. We use 'credp' to do i/o on the core file below, but leave 428 * p->p_cred set to the original credential to allow the core file 429 * to record this information. 430 */ 431 if (ocredp != NULL) 432 credp = set_cred(p, ocredp); 433 434 if (error == 0) { 435 int closerr; 436 #if defined(__sparc) 437 (void) flush_user_windows_to_stack(NULL); 438 #endif 439 if ((eswp = PTOU(curproc)->u_execsw) == NULL || 440 (eswp = findexec_by_magic(eswp->exec_magic)) == NULL) { 441 error = ENOSYS; 442 } else { 443 error = eswp->exec_core(vp, p, credp, rlimit, sig, 444 content); 445 rw_exit(eswp->exec_lock); 446 } 447 448 closerr = VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, credp, NULL); 449 VN_RELE(vp); 450 if (error == 0) 451 error = closerr; 452 } 453 454 if (ocredp != NULL) 455 crfree(credp); 456 457 return (error); 458 } 459 460 /* 461 * Convert a core name pattern to a pathname. 462 */ 463 static int 464 expand_string(const char *pat, char *fp, int size, cred_t *cr) 465 { 466 proc_t *p = curproc; 467 char buf[24]; 468 int len, i; 469 char *s; 470 char c; 471 472 while ((c = *pat++) != '\0') { 473 if (size < 2) 474 return (ENAMETOOLONG); 475 if (c != '%') { 476 size--; 477 *fp++ = c; 478 continue; 479 } 480 if ((c = *pat++) == '\0') { 481 size--; 482 *fp++ = '%'; 483 break; 484 } 485 switch (c) { 486 case 'p': /* pid */ 487 (void) sprintf((s = buf), "%d", p->p_pid); 488 break; 489 case 'u': /* effective uid */ 490 (void) sprintf((s = buf), "%u", crgetuid(p->p_cred)); 491 break; 492 case 'g': /* effective gid */ 493 (void) sprintf((s = buf), "%u", crgetgid(p->p_cred)); 494 break; 495 case 'f': /* exec'd filename */ 496 s = PTOU(p)->u_comm; 497 break; 498 case 'd': /* exec'd dirname */ 499 /* 500 * Even if pathname caching is disabled, we should 501 * be able to lookup the pathname for a directory. 502 */ 503 if (p->p_execdir != NULL && vnodetopath(NULL, 504 p->p_execdir, fp, size, cr) == 0) { 505 len = (int)strlen(fp); 506 ASSERT(len < size); 507 ASSERT(len >= 1); 508 ASSERT(fp[0] == '/'); 509 510 /* 511 * Strip off the leading slash. 512 */ 513 for (i = 0; i < len; i++) { 514 fp[i] = fp[i + 1]; 515 } 516 517 len--; 518 519 size -= len; 520 fp += len; 521 } else { 522 *fp = '\0'; 523 } 524 525 continue; 526 case 'n': /* system nodename */ 527 s = uts_nodename(); 528 break; 529 case 'm': /* machine (sun4u, etc) */ 530 s = utsname.machine; 531 break; 532 case 't': /* decimal value of time(2) */ 533 (void) sprintf((s = buf), "%ld", gethrestime_sec()); 534 break; 535 case 'z': 536 s = p->p_zone->zone_name; 537 break; 538 case 'Z': 539 /* This is zonepath + "/root/", except for GZ */ 540 s = p->p_zone->zone_rootpath; 541 break; 542 case '%': 543 (void) strcpy((s = buf), "%"); 544 break; 545 default: 546 s = buf; 547 buf[0] = '%'; 548 buf[1] = c; 549 buf[2] = '\0'; 550 break; 551 } 552 len = (int)strlen(s); 553 if ((size -= len) <= 0) 554 return (ENAMETOOLONG); 555 (void) strcpy(fp, s); 556 /* strip trailing "/root/" from non-GZ zonepath string */ 557 if (c == 'Z' && len > 6) { 558 len -= 6; 559 ASSERT(strncmp(fp + len, "/root/", 6) == 0); 560 } 561 fp += len; 562 } 563 564 *fp = '\0'; 565 return (0); 566 } 567 568 static int 569 dump_one_core(int sig, rlim64_t rlimit, enum core_types core_type, 570 struct core_globals *cg, char **name) 571 { 572 refstr_t *rp; 573 proc_t *p = curproc; 574 zoneid_t zoneid; 575 int error; 576 char *fp; 577 cred_t *cr; 578 579 ASSERT(core_type == CORE_ZONE || core_type == CORE_GLOBAL); 580 zoneid = (core_type == CORE_ZONE ? getzoneid() : GLOBAL_ZONEID); 581 582 mutex_enter(&cg->core_lock); 583 if ((rp = cg->core_file) != NULL) 584 refstr_hold(rp); 585 mutex_exit(&cg->core_lock); 586 if (rp == NULL) { 587 core_log(cg, 0, "no global core file pattern exists", NULL, 588 zoneid); 589 return (1); /* core file not generated */ 590 } 591 fp = kmem_alloc(MAXPATHLEN, KM_SLEEP); 592 cr = zone_get_kcred(getzoneid()); 593 error = expand_string(refstr_value(rp), fp, MAXPATHLEN, cr); 594 crfree(cr); 595 if (error != 0) { 596 core_log(cg, 0, "global core file pattern too long", 597 refstr_value(rp), zoneid); 598 } else if ((error = do_core(fp, sig, core_type, cg)) == 0) { 599 core_log(cg, 0, "core dumped", fp, zoneid); 600 } else if (error == ENOTSUP) { 601 core_log(cg, 0, "setid process, core not dumped", fp, zoneid); 602 } else if (error == ENOSPC) { 603 core_log(cg, 0, "no space left on device, core truncated", 604 fp, zoneid); 605 } else if (error == EFBIG) { 606 if (rlimit == 0) 607 core_log(cg, 0, "core rlimit is zero, core not dumped", 608 fp, zoneid); 609 else 610 core_log(cg, 0, "core rlimit exceeded, core truncated", 611 fp, zoneid); 612 /* 613 * In addition to the core result logging, we 614 * may also have explicit actions defined on 615 * core file size violations via the resource 616 * control framework. 617 */ 618 mutex_enter(&p->p_lock); 619 (void) rctl_action(rctlproc_legacy[RLIMIT_CORE], 620 p->p_rctls, p, RCA_SAFE); 621 mutex_exit(&p->p_lock); 622 } else { 623 core_log(cg, error, "core dump failed", fp, zoneid); 624 } 625 refstr_rele(rp); 626 if (name != NULL) 627 *name = fp; 628 else 629 kmem_free(fp, MAXPATHLEN); 630 return (error); 631 } 632 633 int 634 core(int sig, int ext) 635 { 636 proc_t *p = curproc; 637 klwp_t *lwp = ttolwp(curthread); 638 refstr_t *rp; 639 char *fp_process = NULL, *fp_global = NULL, *fp_zone = NULL; 640 int error1 = 1; 641 int error2 = 1; 642 int error3 = 1; 643 k_sigset_t sigmask; 644 k_sigset_t sighold; 645 rlim64_t rlimit; 646 struct core_globals *my_cg, *global_cg; 647 648 global_cg = zone_getspecific(core_zone_key, global_zone); 649 ASSERT(global_cg != NULL); 650 651 my_cg = zone_getspecific(core_zone_key, curproc->p_zone); 652 ASSERT(my_cg != NULL); 653 654 /* core files suppressed? */ 655 if (!(my_cg->core_options & (CC_PROCESS_PATH|CC_GLOBAL_PATH)) && 656 !(global_cg->core_options & CC_GLOBAL_PATH)) { 657 if (!ext && p->p_ct_process != NULL) 658 contract_process_core(p->p_ct_process, p, sig, 659 NULL, NULL, NULL); 660 return (1); 661 } 662 663 /* 664 * Block all signals except SIGHUP, SIGINT, SIGKILL, and SIGTERM; no 665 * other signal may interrupt a core dump. For each signal, we 666 * explicitly unblock it and set it in p_siginfo to allow for some 667 * minimal error reporting. Additionally, we get the current limit on 668 * core file size for handling later error reporting. 669 */ 670 mutex_enter(&p->p_lock); 671 672 p->p_flag |= SDOCORE; 673 schedctl_finish_sigblock(curthread); 674 sigmask = curthread->t_hold; /* remember for later */ 675 sigfillset(&sighold); 676 if (!sigismember(&sigmask, SIGHUP)) 677 sigdelset(&sighold, SIGHUP); 678 if (!sigismember(&sigmask, SIGINT)) 679 sigdelset(&sighold, SIGINT); 680 if (!sigismember(&sigmask, SIGKILL)) 681 sigdelset(&sighold, SIGKILL); 682 if (!sigismember(&sigmask, SIGTERM)) 683 sigdelset(&sighold, SIGTERM); 684 685 sigaddset(&p->p_siginfo, SIGHUP); 686 sigaddset(&p->p_siginfo, SIGINT); 687 sigaddset(&p->p_siginfo, SIGKILL); 688 sigaddset(&p->p_siginfo, SIGTERM); 689 690 curthread->t_hold = sighold; 691 692 rlimit = rctl_enforced_value(rctlproc_legacy[RLIMIT_CORE], p->p_rctls, 693 p); 694 695 mutex_exit(&p->p_lock); 696 697 /* 698 * Undo any watchpoints. 699 */ 700 pr_free_watched_pages(p); 701 702 /* 703 * The presence of a current signal prevents file i/o 704 * from succeeding over a network. We copy the current 705 * signal information to the side and cancel the current 706 * signal so that the core dump will succeed. 707 */ 708 ASSERT(lwp->lwp_cursig == sig); 709 lwp->lwp_cursig = 0; 710 lwp->lwp_extsig = 0; 711 if (lwp->lwp_curinfo == NULL) { 712 bzero(&lwp->lwp_siginfo, sizeof (k_siginfo_t)); 713 lwp->lwp_siginfo.si_signo = sig; 714 lwp->lwp_siginfo.si_code = SI_NOINFO; 715 } else { 716 bcopy(&lwp->lwp_curinfo->sq_info, 717 &lwp->lwp_siginfo, sizeof (k_siginfo_t)); 718 siginfofree(lwp->lwp_curinfo); 719 lwp->lwp_curinfo = NULL; 720 } 721 722 /* 723 * Convert the core file name patterns into path names 724 * and call do_core() to write the core files. 725 */ 726 727 if (my_cg->core_options & CC_PROCESS_PATH) { 728 mutex_enter(&p->p_lock); 729 if (p->p_corefile != NULL) 730 rp = corectl_path_value(p->p_corefile); 731 else 732 rp = NULL; 733 mutex_exit(&p->p_lock); 734 if (rp != NULL) { 735 fp_process = kmem_alloc(MAXPATHLEN, KM_SLEEP); 736 error1 = expand_string(refstr_value(rp), 737 fp_process, MAXPATHLEN, p->p_cred); 738 if (error1 == 0) 739 error1 = do_core(fp_process, sig, CORE_PROC, 740 my_cg); 741 refstr_rele(rp); 742 } 743 } 744 745 if (my_cg->core_options & CC_GLOBAL_PATH) 746 error2 = dump_one_core(sig, rlimit, CORE_ZONE, my_cg, 747 &fp_global); 748 if (global_cg != my_cg && (global_cg->core_options & CC_GLOBAL_PATH)) 749 error3 = dump_one_core(sig, rlimit, CORE_GLOBAL, global_cg, 750 &fp_zone); 751 752 /* 753 * Restore the signal hold mask. 754 */ 755 mutex_enter(&p->p_lock); 756 curthread->t_hold = sigmask; 757 mutex_exit(&p->p_lock); 758 759 if (!ext && p->p_ct_process != NULL) 760 contract_process_core(p->p_ct_process, p, sig, 761 error1 == 0 ? fp_process : NULL, 762 error2 == 0 ? fp_global : NULL, 763 error3 == 0 ? fp_zone : NULL); 764 765 if (fp_process != NULL) 766 kmem_free(fp_process, MAXPATHLEN); 767 if (fp_global != NULL) 768 kmem_free(fp_global, MAXPATHLEN); 769 if (fp_zone != NULL) 770 kmem_free(fp_zone, MAXPATHLEN); 771 772 /* 773 * Return non-zero if no core file was created. 774 */ 775 return (error1 != 0 && error2 != 0 && error3 != 0); 776 } 777 778 /* 779 * Maximum chunk size for dumping core files, 780 * size in pages, patchable in /etc/system 781 */ 782 uint_t core_chunk = 32; 783 784 /* 785 * The delay between core_write() calls, in microseconds. The default 786 * matches one "normal" clock tick, or 10 milliseconds. 787 */ 788 clock_t core_delay_usec = 10000; 789 790 /* 791 * Common code to core dump process memory. The core_seg routine does i/o 792 * using core_write() below, and so it has the same failure semantics. 793 */ 794 int 795 core_seg(proc_t *p, vnode_t *vp, offset_t offset, caddr_t addr, size_t size, 796 rlim64_t rlimit, cred_t *credp) 797 { 798 caddr_t eaddr; 799 caddr_t base; 800 size_t len; 801 int err = 0; 802 803 eaddr = addr + size; 804 for (base = addr; base < eaddr; base += len) { 805 len = eaddr - base; 806 if (as_memory(p->p_as, &base, &len) != 0) 807 return (0); 808 809 /* 810 * Reduce len to a reasonable value so that we don't 811 * overwhelm the VM system with a monstrously large 812 * single write and cause pageout to stop running. 813 */ 814 if (len > (size_t)core_chunk * PAGESIZE) 815 len = (size_t)core_chunk * PAGESIZE; 816 817 err = core_write(vp, UIO_USERSPACE, 818 offset + (size_t)(base - addr), base, len, rlimit, credp); 819 820 if (err) 821 return (err); 822 823 /* 824 * If we have taken a signal, return EINTR to allow the dump 825 * to be aborted. 826 */ 827 if (issig(JUSTLOOKING) && issig(FORREAL)) 828 return (EINTR); 829 } 830 831 return (0); 832 } 833 834 /* 835 * Wrapper around vn_rdwr to perform writes to a core file. For core files, 836 * we always want to write as much as we possibly can, and then make sure to 837 * return either 0 to the caller (for success), or the actual errno value. 838 * By using this function, the caller can omit additional code for handling 839 * retries and errors for partial writes returned by vn_rdwr. If vn_rdwr 840 * unexpectedly returns zero but no progress has been made, we return ENOSPC. 841 */ 842 int 843 core_write(vnode_t *vp, enum uio_seg segflg, offset_t offset, 844 const void *buf, size_t len, rlim64_t rlimit, cred_t *credp) 845 { 846 ssize_t resid = len; 847 int error = 0; 848 849 while (len != 0) { 850 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)buf, len, offset, 851 segflg, 0, rlimit, credp, &resid); 852 853 if (error != 0) 854 break; 855 856 if (resid >= len) 857 return (ENOSPC); 858 859 buf = (const char *)buf + len - resid; 860 offset += len - resid; 861 len = resid; 862 } 863 864 return (error); 865 } 866