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