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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 29 * Copyright 2018 Joyent, Inc. 30 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 31 * Copyright 2023 Oxide Computer Company 32 */ 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/thread.h> 37 #include <sys/sysmacros.h> 38 #include <sys/signal.h> 39 #include <sys/cred.h> 40 #include <sys/priv.h> 41 #include <sys/user.h> 42 #include <sys/file.h> 43 #include <sys/errno.h> 44 #include <sys/vnode.h> 45 #include <sys/mode.h> 46 #include <sys/vfs.h> 47 #include <sys/mman.h> 48 #include <sys/kmem.h> 49 #include <sys/proc.h> 50 #include <sys/pathname.h> 51 #include <sys/cmn_err.h> 52 #include <sys/systm.h> 53 #include <sys/elf.h> 54 #include <sys/vmsystm.h> 55 #include <sys/debug.h> 56 #include <sys/procfs.h> 57 #include <sys/regset.h> 58 #include <sys/auxv.h> 59 #include <sys/exec.h> 60 #include <sys/prsystm.h> 61 #include <sys/utsname.h> 62 #include <sys/zone.h> 63 #include <vm/as.h> 64 #include <vm/rm.h> 65 #include <sys/modctl.h> 66 #include <sys/systeminfo.h> 67 #include <sys/machelf.h> 68 #include <sys/sunddi.h> 69 #include "elf_impl.h" 70 #if defined(__i386_COMPAT) 71 #include <sys/sysi86.h> 72 #endif 73 74 void 75 setup_note_header(Phdr *v, proc_t *p) 76 { 77 int nlwp = p->p_lwpcnt; 78 int nzomb = p->p_zombcnt; 79 int nfd; 80 size_t size; 81 prcred_t *pcrp; 82 uf_info_t *fip; 83 uf_entry_t *ufp; 84 int fd; 85 86 fip = P_FINFO(p); 87 nfd = 0; 88 mutex_enter(&fip->fi_lock); 89 for (fd = 0; fd < fip->fi_nfiles; fd++) { 90 UF_ENTER(ufp, fip, fd); 91 if ((ufp->uf_file != NULL) && (ufp->uf_file->f_count > 0)) 92 nfd++; 93 UF_EXIT(ufp); 94 } 95 mutex_exit(&fip->fi_lock); 96 97 v[0].p_type = PT_NOTE; 98 v[0].p_flags = PF_R; 99 v[0].p_filesz = (sizeof (Note) * (10 + 3 * nlwp + nzomb + nfd)) 100 + roundup(sizeof (psinfo_t), sizeof (Word)) 101 + roundup(sizeof (pstatus_t), sizeof (Word)) 102 + roundup(prgetprivsize(), sizeof (Word)) 103 + roundup(priv_get_implinfo_size(), sizeof (Word)) 104 + roundup(strlen(platform) + 1, sizeof (Word)) 105 + roundup(strlen(p->p_zone->zone_name) + 1, sizeof (Word)) 106 + roundup(__KERN_NAUXV_IMPL * sizeof (aux_entry_t), sizeof (Word)) 107 + roundup(sizeof (utsname), sizeof (Word)) 108 + roundup(sizeof (core_content_t), sizeof (Word)) 109 + roundup(sizeof (prsecflags_t), sizeof (Word)) 110 + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word)) 111 + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) 112 + nlwp * roundup(sizeof (prlwpname_t), sizeof (Word)) 113 + nfd * roundup(sizeof (prfdinfo_core_t), sizeof (Word)); 114 115 if (curproc->p_agenttp != NULL) { 116 v[0].p_filesz += sizeof (Note) + 117 roundup(sizeof (psinfo_t), sizeof (Word)); 118 } 119 120 size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); 121 pcrp = kmem_zalloc(size, KM_SLEEP); 122 prgetcred(p, pcrp); 123 if (pcrp->pr_ngroups != 0) { 124 v[0].p_filesz += sizeof (Note) + roundup(sizeof (prcred_t) + 125 sizeof (gid_t) * (pcrp->pr_ngroups - 1), sizeof (Word)); 126 } else { 127 v[0].p_filesz += sizeof (Note) + 128 roundup(sizeof (prcred_t), sizeof (Word)); 129 } 130 kmem_free(pcrp, size); 131 132 133 #if defined(__i386_COMPAT) 134 mutex_enter(&p->p_ldtlock); 135 size = prnldt(p) * sizeof (struct ssd); 136 mutex_exit(&p->p_ldtlock); 137 if (size != 0) 138 v[0].p_filesz += sizeof (Note) + roundup(size, sizeof (Word)); 139 #endif /* __i386_COMPAT */ 140 141 if ((size = prhasx(p) ? prgetprxregsize(p) : 0) != 0) 142 v[0].p_filesz += nlwp * sizeof (Note) 143 + nlwp * roundup(size, sizeof (Word)); 144 145 #if defined(__sparc) 146 /* 147 * Figure out the number and sizes of register windows. 148 */ 149 { 150 kthread_t *t = p->p_tlist; 151 do { 152 if ((size = prnwindows(ttolwp(t))) != 0) { 153 size = sizeof (gwindows_t) - 154 (SPARC_MAXREGWINDOW - size) * 155 sizeof (struct rwindow); 156 v[0].p_filesz += sizeof (Note) + 157 roundup(size, sizeof (Word)); 158 } 159 } while ((t = t->t_forw) != p->p_tlist); 160 } 161 /* 162 * Space for the Ancillary State Registers. 163 */ 164 if (p->p_model == DATAMODEL_LP64) 165 v[0].p_filesz += nlwp * sizeof (Note) 166 + nlwp * roundup(sizeof (asrset_t), sizeof (Word)); 167 #endif /* __sparc */ 168 169 mutex_enter(&p->p_lock); 170 if ((p->p_upanicflag & P_UPF_PANICKED) != 0) { 171 v[0].p_filesz += sizeof (Note) + 172 roundup(sizeof (prupanic_t), sizeof (Word)); 173 } 174 mutex_exit(&p->p_lock); 175 } 176 177 int 178 write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, 179 rlim64_t rlimit, cred_t *credp, core_content_t content) 180 { 181 union { 182 psinfo_t psinfo; 183 pstatus_t pstatus; 184 lwpsinfo_t lwpsinfo; 185 lwpstatus_t lwpstatus; 186 #if defined(__sparc) 187 gwindows_t gwindows; 188 asrset_t asrset; 189 #endif /* __sparc */ 190 char xregs[1]; 191 aux_entry_t auxv[__KERN_NAUXV_IMPL]; 192 prcred_t pcred; 193 prpriv_t ppriv; 194 priv_impl_info_t prinfo; 195 struct utsname uts; 196 prsecflags_t psecflags; 197 prupanic_t upanic; 198 } *bigwad; 199 200 size_t xregsize = prhasx(p) ? prgetprxregsize(p) : 0; 201 size_t crsize = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); 202 size_t psize = prgetprivsize(); 203 size_t bigsize = MAX(psize, MAX(sizeof (*bigwad), 204 MAX(xregsize, crsize))); 205 206 priv_impl_info_t *prii; 207 208 lwpdir_t *ldp; 209 lwpent_t *lep; 210 kthread_t *t; 211 klwp_t *lwp; 212 user_t *up; 213 int i; 214 int nlwp; 215 int nzomb; 216 int error; 217 uchar_t oldsig; 218 uf_info_t *fip; 219 int fd; 220 vnode_t *vroot; 221 222 #if defined(__i386_COMPAT) 223 struct ssd *ssd; 224 size_t ssdsize; 225 #endif /* __i386_COMPAT */ 226 227 bigsize = MAX(bigsize, priv_get_implinfo_size()); 228 229 bigwad = kmem_alloc(bigsize, KM_SLEEP); 230 231 /* 232 * The order of the elfnote entries should be same here 233 * and in the gcore(1) command. Synchronization is 234 * needed between the kernel and gcore(1). 235 */ 236 237 /* 238 * Get the psinfo, and set the wait status to indicate that a core was 239 * dumped. We have to forge this since p->p_wcode is not set yet. 240 */ 241 mutex_enter(&p->p_lock); 242 prgetpsinfo(p, &bigwad->psinfo); 243 mutex_exit(&p->p_lock); 244 bigwad->psinfo.pr_wstat = wstat(CLD_DUMPED, sig); 245 246 error = elfnote(vp, &offset, NT_PSINFO, sizeof (bigwad->psinfo), 247 (caddr_t)&bigwad->psinfo, rlimit, credp); 248 if (error) 249 goto done; 250 251 /* 252 * Modify t_whystop and lwp_cursig so it appears that the current LWP 253 * is stopped after faulting on the signal that caused the core dump. 254 * As a result, prgetstatus() will record that signal, the saved 255 * lwp_siginfo, and its signal handler in the core file status. We 256 * restore lwp_cursig in case a subsequent signal was received while 257 * dumping core. 258 */ 259 mutex_enter(&p->p_lock); 260 lwp = ttolwp(curthread); 261 262 oldsig = lwp->lwp_cursig; 263 lwp->lwp_cursig = (uchar_t)sig; 264 curthread->t_whystop = PR_FAULTED; 265 266 prgetstatus(p, &bigwad->pstatus, p->p_zone); 267 bigwad->pstatus.pr_lwp.pr_why = 0; 268 269 curthread->t_whystop = 0; 270 lwp->lwp_cursig = oldsig; 271 mutex_exit(&p->p_lock); 272 273 error = elfnote(vp, &offset, NT_PSTATUS, sizeof (bigwad->pstatus), 274 (caddr_t)&bigwad->pstatus, rlimit, credp); 275 if (error) 276 goto done; 277 278 error = elfnote(vp, &offset, NT_PLATFORM, strlen(platform) + 1, 279 platform, rlimit, credp); 280 if (error) 281 goto done; 282 283 up = PTOU(p); 284 for (i = 0; i < __KERN_NAUXV_IMPL; i++) { 285 bigwad->auxv[i].a_type = up->u_auxv[i].a_type; 286 bigwad->auxv[i].a_un.a_val = up->u_auxv[i].a_un.a_val; 287 } 288 error = elfnote(vp, &offset, NT_AUXV, sizeof (bigwad->auxv), 289 (caddr_t)bigwad->auxv, rlimit, credp); 290 if (error) 291 goto done; 292 293 bcopy(&utsname, &bigwad->uts, sizeof (struct utsname)); 294 if (!INGLOBALZONE(p)) { 295 bcopy(p->p_zone->zone_nodename, &bigwad->uts.nodename, 296 _SYS_NMLN); 297 } 298 error = elfnote(vp, &offset, NT_UTSNAME, sizeof (struct utsname), 299 (caddr_t)&bigwad->uts, rlimit, credp); 300 if (error) 301 goto done; 302 303 prgetsecflags(p, &bigwad->psecflags); 304 error = elfnote(vp, &offset, NT_SECFLAGS, sizeof (prsecflags_t), 305 (caddr_t)&bigwad->psecflags, rlimit, credp); 306 if (error) 307 goto done; 308 309 bzero(bigwad, crsize); 310 prgetcred(p, &bigwad->pcred); 311 312 if (bigwad->pcred.pr_ngroups != 0) { 313 crsize = sizeof (prcred_t) + 314 sizeof (gid_t) * (bigwad->pcred.pr_ngroups - 1); 315 } else 316 crsize = sizeof (prcred_t); 317 318 error = elfnote(vp, &offset, NT_PRCRED, crsize, 319 (caddr_t)&bigwad->pcred, rlimit, credp); 320 if (error) 321 goto done; 322 323 error = elfnote(vp, &offset, NT_CONTENT, sizeof (core_content_t), 324 (caddr_t)&content, rlimit, credp); 325 if (error) 326 goto done; 327 328 prgetpriv(p, &bigwad->ppriv); 329 330 error = elfnote(vp, &offset, NT_PRPRIV, psize, 331 (caddr_t)&bigwad->ppriv, rlimit, credp); 332 if (error) 333 goto done; 334 335 prii = priv_hold_implinfo(); 336 error = elfnote(vp, &offset, NT_PRPRIVINFO, priv_get_implinfo_size(), 337 (caddr_t)prii, rlimit, credp); 338 priv_release_implinfo(); 339 if (error) 340 goto done; 341 342 /* zone can't go away as long as process exists */ 343 error = elfnote(vp, &offset, NT_ZONENAME, 344 strlen(p->p_zone->zone_name) + 1, p->p_zone->zone_name, 345 rlimit, credp); 346 if (error) 347 goto done; 348 349 350 /* open file table */ 351 vroot = PTOU(p)->u_rdir; 352 if (vroot == NULL) 353 vroot = rootdir; 354 355 VN_HOLD(vroot); 356 357 fip = P_FINFO(p); 358 359 for (fd = 0; fd < fip->fi_nfiles; fd++) { 360 uf_entry_t *ufp; 361 vnode_t *fvp; 362 struct file *fp; 363 vattr_t vattr; 364 prfdinfo_core_t fdinfo; 365 366 bzero(&fdinfo, sizeof (fdinfo)); 367 368 mutex_enter(&fip->fi_lock); 369 UF_ENTER(ufp, fip, fd); 370 if (((fp = ufp->uf_file) == NULL) || (fp->f_count < 1)) { 371 UF_EXIT(ufp); 372 mutex_exit(&fip->fi_lock); 373 continue; 374 } 375 376 fdinfo.pr_fd = fd; 377 fdinfo.pr_fdflags = ufp->uf_flag; 378 fdinfo.pr_fileflags = fp->f_flag2; 379 fdinfo.pr_fileflags <<= 16; 380 fdinfo.pr_fileflags |= fp->f_flag; 381 if ((fdinfo.pr_fileflags & (FSEARCH | FEXEC)) == 0) 382 fdinfo.pr_fileflags += FOPEN; 383 fdinfo.pr_offset = fp->f_offset; 384 385 386 fvp = fp->f_vnode; 387 VN_HOLD(fvp); 388 UF_EXIT(ufp); 389 mutex_exit(&fip->fi_lock); 390 391 /* 392 * There are some vnodes that have no corresponding 393 * path. Its reasonable for this to fail, in which 394 * case the path will remain an empty string. 395 */ 396 (void) vnodetopath(vroot, fvp, fdinfo.pr_path, 397 sizeof (fdinfo.pr_path), credp); 398 399 if (VOP_GETATTR(fvp, &vattr, 0, credp, NULL) != 0) { 400 /* 401 * Try to write at least a subset of information 402 */ 403 fdinfo.pr_major = 0; 404 fdinfo.pr_minor = 0; 405 fdinfo.pr_ino = 0; 406 fdinfo.pr_mode = 0; 407 fdinfo.pr_uid = (uid_t)-1; 408 fdinfo.pr_gid = (gid_t)-1; 409 fdinfo.pr_rmajor = 0; 410 fdinfo.pr_rminor = 0; 411 fdinfo.pr_size = -1; 412 413 error = elfnote(vp, &offset, NT_FDINFO, 414 sizeof (fdinfo), &fdinfo, rlimit, credp); 415 VN_RELE(fvp); 416 if (error) { 417 VN_RELE(vroot); 418 goto done; 419 } 420 continue; 421 } 422 423 if (fvp->v_type == VSOCK) 424 fdinfo.pr_fileflags |= sock_getfasync(fvp); 425 426 VN_RELE(fvp); 427 428 /* 429 * This logic mirrors fstat(), which we cannot use 430 * directly, as it calls copyout(). 431 */ 432 fdinfo.pr_major = getmajor(vattr.va_fsid); 433 fdinfo.pr_minor = getminor(vattr.va_fsid); 434 fdinfo.pr_ino = (ino64_t)vattr.va_nodeid; 435 fdinfo.pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode; 436 fdinfo.pr_uid = vattr.va_uid; 437 fdinfo.pr_gid = vattr.va_gid; 438 fdinfo.pr_rmajor = getmajor(vattr.va_rdev); 439 fdinfo.pr_rminor = getminor(vattr.va_rdev); 440 fdinfo.pr_size = (off64_t)vattr.va_size; 441 442 error = elfnote(vp, &offset, NT_FDINFO, 443 sizeof (fdinfo), &fdinfo, rlimit, credp); 444 if (error) { 445 VN_RELE(vroot); 446 goto done; 447 } 448 } 449 450 VN_RELE(vroot); 451 452 #if defined(__i386_COMPAT) 453 mutex_enter(&p->p_ldtlock); 454 ssdsize = prnldt(p) * sizeof (struct ssd); 455 if (ssdsize != 0) { 456 ssd = kmem_alloc(ssdsize, KM_SLEEP); 457 prgetldt(p, ssd); 458 error = elfnote(vp, &offset, NT_LDT, ssdsize, 459 (caddr_t)ssd, rlimit, credp); 460 kmem_free(ssd, ssdsize); 461 } 462 mutex_exit(&p->p_ldtlock); 463 if (error) 464 goto done; 465 #endif /* defined(__i386_COMPAT) */ 466 467 nlwp = p->p_lwpcnt; 468 nzomb = p->p_zombcnt; 469 /* for each entry in the lwp directory ... */ 470 for (ldp = p->p_lwpdir; nlwp + nzomb != 0; ldp++) { 471 prlwpname_t name = { 0, }; 472 473 if ((lep = ldp->ld_entry) == NULL) /* empty slot */ 474 continue; 475 476 if ((t = lep->le_thread) != NULL) { /* active lwp */ 477 ASSERT(nlwp != 0); 478 nlwp--; 479 lwp = ttolwp(t); 480 mutex_enter(&p->p_lock); 481 prgetlwpsinfo(t, &bigwad->lwpsinfo); 482 if (t->t_name != NULL) { 483 (void) strlcpy(name.pr_lwpname, t->t_name, 484 sizeof (name.pr_lwpname)); 485 } 486 mutex_exit(&p->p_lock); 487 } else { /* zombie lwp */ 488 ASSERT(nzomb != 0); 489 nzomb--; 490 bzero(&bigwad->lwpsinfo, sizeof (bigwad->lwpsinfo)); 491 bigwad->lwpsinfo.pr_lwpid = lep->le_lwpid; 492 bigwad->lwpsinfo.pr_state = SZOMB; 493 bigwad->lwpsinfo.pr_sname = 'Z'; 494 bigwad->lwpsinfo.pr_start.tv_sec = lep->le_start; 495 } 496 497 name.pr_lwpid = bigwad->lwpsinfo.pr_lwpid; 498 499 error = elfnote(vp, &offset, NT_LWPSINFO, 500 sizeof (bigwad->lwpsinfo), (caddr_t)&bigwad->lwpsinfo, 501 rlimit, credp); 502 if (error) 503 goto done; 504 505 if (t == NULL) /* nothing more to do for a zombie */ 506 continue; 507 508 mutex_enter(&p->p_lock); 509 if (t == curthread) { 510 /* 511 * Modify t_whystop and lwp_cursig so it appears that 512 * the current LWP is stopped after faulting on the 513 * signal that caused the core dump. As a result, 514 * prgetlwpstatus() will record that signal, the saved 515 * lwp_siginfo, and its signal handler in the core file 516 * status. We restore lwp_cursig in case a subsequent 517 * signal was received while dumping core. 518 */ 519 oldsig = lwp->lwp_cursig; 520 lwp->lwp_cursig = (uchar_t)sig; 521 t->t_whystop = PR_FAULTED; 522 523 prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone); 524 bigwad->lwpstatus.pr_why = 0; 525 526 t->t_whystop = 0; 527 lwp->lwp_cursig = oldsig; 528 } else { 529 prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone); 530 } 531 mutex_exit(&p->p_lock); 532 error = elfnote(vp, &offset, NT_LWPSTATUS, 533 sizeof (bigwad->lwpstatus), (caddr_t)&bigwad->lwpstatus, 534 rlimit, credp); 535 if (error) 536 goto done; 537 538 if ((error = elfnote(vp, &offset, NT_LWPNAME, sizeof (name), 539 (caddr_t)&name, rlimit, credp)) != 0) 540 goto done; 541 542 543 #if defined(__sparc) 544 /* 545 * Unspilled SPARC register windows. 546 */ 547 { 548 size_t size = prnwindows(lwp); 549 550 if (size != 0) { 551 size = sizeof (gwindows_t) - 552 (SPARC_MAXREGWINDOW - size) * 553 sizeof (struct rwindow); 554 prgetwindows(lwp, &bigwad->gwindows); 555 error = elfnote(vp, &offset, NT_GWINDOWS, 556 size, (caddr_t)&bigwad->gwindows, 557 rlimit, credp); 558 if (error) 559 goto done; 560 } 561 } 562 /* 563 * Ancillary State Registers. 564 */ 565 if (p->p_model == DATAMODEL_LP64) { 566 prgetasregs(lwp, bigwad->asrset); 567 error = elfnote(vp, &offset, NT_ASRS, 568 sizeof (asrset_t), (caddr_t)bigwad->asrset, 569 rlimit, credp); 570 if (error) 571 goto done; 572 } 573 #endif /* __sparc */ 574 575 if (xregsize) { 576 prgetprxregs(lwp, (prxregset_t *)bigwad->xregs); 577 error = elfnote(vp, &offset, NT_PRXREG, 578 xregsize, bigwad->xregs, rlimit, credp); 579 if (error) 580 goto done; 581 } 582 583 if (t->t_lwp->lwp_spymaster != NULL) { 584 void *psaddr = t->t_lwp->lwp_spymaster; 585 #ifdef _ELF32_COMPAT 586 /* 587 * On a 64-bit kernel with 32-bit ELF compatibility, 588 * this file is compiled into two different objects: 589 * one is compiled normally, and the other is compiled 590 * with _ELF32_COMPAT set -- and therefore with a 591 * psinfo_t defined to be a psinfo32_t. However, the 592 * psinfo_t denoting our spymaster is always of the 593 * native type; if we are in the _ELF32_COMPAT case, 594 * we need to explicitly convert it. 595 */ 596 if (p->p_model == DATAMODEL_ILP32) { 597 psinfo_kto32(psaddr, &bigwad->psinfo); 598 psaddr = &bigwad->psinfo; 599 } 600 #endif 601 602 error = elfnote(vp, &offset, NT_SPYMASTER, 603 sizeof (psinfo_t), psaddr, rlimit, credp); 604 if (error) 605 goto done; 606 } 607 } 608 ASSERT(nlwp == 0); 609 610 /* 611 * If a upanic occurred, add a note for it. 612 */ 613 mutex_enter(&p->p_lock); 614 if ((p->p_upanicflag & P_UPF_PANICKED) != 0) { 615 bzero(&bigwad->upanic, sizeof (prupanic_t)); 616 bigwad->upanic.pru_version = PRUPANIC_VERSION_1; 617 if ((p->p_upanicflag & P_UPF_INVALMSG) != 0) { 618 bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_ERROR; 619 } 620 621 if ((p->p_upanicflag & P_UPF_TRUNCMSG) != 0) { 622 bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_TRUNC; 623 } 624 625 if ((p->p_upanicflag & P_UPF_HAVEMSG) != 0) { 626 bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_VALID; 627 bcopy(p->p_upanic, bigwad->upanic.pru_data, 628 PRUPANIC_BUFLEN); 629 } 630 631 mutex_exit(&p->p_lock); 632 error = elfnote(vp, &offset, NT_UPANIC, sizeof (prupanic_t), 633 &bigwad->upanic, rlimit, credp); 634 if (error != 0) { 635 goto done; 636 } 637 } else { 638 mutex_exit(&p->p_lock); 639 } 640 641 done: 642 kmem_free(bigwad, bigsize); 643 return (error); 644 } 645