# HG changeset patch # User Bryan Cantrill # Date 1364935939 25200 # Node ID c1f1ea4feeb150bf897d5dde922c4e4fcc3c29c4 # Parent 779e63d911a51259e6e3918b47e510a0450f7f4d 3673 core dumping is abysmally slow 3671 left behind enemy lines, agent LWP can go rogue 3670 add visibility into agent LWP's spymaster Reviewed by: Keith M Wesolowski Reviewed by: Joshua M. Clulow Reviewed by: Robert Mustacchi Reviewed by: Richard Lowe Reviewed by: Garrett D'Amore Reviewed by: Eric Schrock Approved by: Richard Lowe diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/ptools/pflags/pflags.c --- a/usr/src/cmd/ptools/pflags/pflags.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/ptools/pflags/pflags.c Tue Apr 02 13:52:19 2013 -0700 @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #include #include #include @@ -258,6 +262,7 @@ int flags; uint32_t sighold, sighold1, sighold2; uint32_t sigpend, sigpend1, sigpend2; + psinfo_t ps; int cursig; char buf[32]; @@ -331,6 +336,17 @@ (void) printf("\tcursig = %s\n", proc_signame(cursig, buf, sizeof (buf))); + if ((flags & PR_AGENT) && + Plwp_getspymaster(Pr, pip->pr_lwpid, &ps) == 0) { + time_t time = ps.pr_time.tv_sec; + char t[64]; + + (void) strftime(t, sizeof (t), "%F:%H.%M.%S", localtime(&time)); + + (void) printf("\tspymaster = pid %d, \"%s\" at %s\n", + (int)ps.pr_pid, ps.pr_psargs, t); + } + if (rflag) { if (Pstate(Pr) == PS_DEAD || (arg->pflags & PR_STOPPED)) { #if defined(__sparc) && defined(_ILP32) diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/sgs/elfdump/common/corenote.c --- a/usr/src/cmd/sgs/elfdump/common/corenote.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/sgs/elfdump/common/corenote.c Tue Apr 02 13:52:19 2013 -0700 @@ -25,6 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include @@ -1437,7 +1438,6 @@ indent_exit(state); } - /* * Output information from prpsinfo_t structure. */ @@ -1849,6 +1849,13 @@ state.ns_v2col = 54; dump_prfdinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PRFDINFO_T)); return (CORENOTE_R_OK); + + case NT_SPYMASTER: + state.ns_vcol = 25; + state.ns_t2col = 45; + state.ns_v2col = 58; + dump_psinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PSINFO_T)); + return (CORENOTE_R_OK); } return (CORENOTE_R_BADTYPE); diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/sgs/include/conv.h --- a/usr/src/cmd/sgs/include/conv.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/sgs/include/conv.h Tue Apr 02 13:52:19 2013 -0700 @@ -277,7 +277,7 @@ } Conv_bnd_obj_buf_t; /* conv_phdr_flags() */ -#define CONV_PHDR_FLAGS_BUFSIZE 57 +#define CONV_PHDR_FLAGS_BUFSIZE 88 typedef union { Conv_inv_buf_t inv_buf; char buf[CONV_PHDR_FLAGS_BUFSIZE]; diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/sgs/libconv/common/corenote.c --- a/usr/src/cmd/sgs/libconv/common/corenote.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/sgs/libconv/common/corenote.c Tue Apr 02 13:52:19 2013 -0700 @@ -25,6 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -55,9 +56,10 @@ MSG_NT_UTSNAME, MSG_NT_LWPSTATUS, MSG_NT_LWPSINFO, MSG_NT_PRPRIV, MSG_NT_PRPRIVINFO, MSG_NT_CONTENT, - MSG_NT_ZONENAME, MSG_NT_FDINFO + MSG_NT_ZONENAME, MSG_NT_FDINFO, + MSG_NT_SPYMASTER }; -#if NT_NUM != NT_FDINFO +#if NT_NUM != NT_SPYMASTER #error "NT_NUM has grown. Update core note types[]" #endif static const conv_ds_msg_t ds_types = { diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/sgs/libconv/common/corenote.msg --- a/usr/src/cmd/sgs/libconv/common/corenote.msg Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/sgs/libconv/common/corenote.msg Tue Apr 02 13:52:19 2013 -0700 @@ -24,6 +24,7 @@ # Use is subject to license terms. # # Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # @ MSG_NT_PRSTATUS "[ NT_PRSTATUS ]" @@ -46,6 +47,7 @@ @ MSG_NT_CONTENT "[ NT_CONTENT ]" @ MSG_NT_ZONENAME "[ NT_ZONENAME ]" @ MSG_NT_FDINFO "[ NT_FDINFO ]" +@ MSG_NT_SPYMASTER "[ NT_SPYMASTER ]" @ MSG_AUXV_AF_SUN_SETUGID "AF_SUN_SETUGID" diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/sgs/libconv/common/phdr.c --- a/usr/src/cmd/sgs/libconv/common/phdr.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/sgs/libconv/common/phdr.c Tue Apr 02 13:52:19 2013 -0700 @@ -215,6 +215,8 @@ MSG_PF_W_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ MSG_PF_R_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ MSG_PF_SUNW_FAILURE_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_PF_SUNW_KILLED_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_PF_SUNW_SIGINFO_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE /* @@ -241,6 +243,8 @@ { PF_W, ALL, MSG_PF_W_CF }, { PF_R, ALL, MSG_PF_R_CF }, { PF_SUNW_FAILURE, SOL, MSG_PF_SUNW_FAILURE_CF }, + { PF_SUNW_KILLED, SOL, MSG_PF_SUNW_KILLED_CF }, + { PF_SUNW_SIGINFO, SOL, MSG_PF_SUNW_SIGINFO_CF }, { 0 } }; static const Val_desc2 vda_nf[] = { @@ -248,6 +252,8 @@ { PF_W, ALL, MSG_PF_W_NF }, { PF_R, ALL, MSG_PF_R_NF }, { PF_SUNW_FAILURE, SOL, MSG_PF_SUNW_FAILURE_NF }, + { PF_SUNW_KILLED, SOL, MSG_PF_SUNW_KILLED_NF }, + { PF_SUNW_SIGINFO, SOL, MSG_PF_SUNW_SIGINFO_NF }, { 0 } }; diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/cmd/sgs/libconv/common/phdr.msg --- a/usr/src/cmd/sgs/libconv/common/phdr.msg Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/cmd/sgs/libconv/common/phdr.msg Tue Apr 02 13:52:19 2013 -0700 @@ -105,5 +105,9 @@ @ MSG_PF_R_NF "r" @ MSG_PF_SUNW_FAILURE_CF "PF_SUNW_FAILURE" # 0x00100000 @ MSG_PF_SUNW_FAILURE_NF "sunw_failure" +@ MSG_PF_SUNW_KILLED_CF "PF_SUNW_KILLED" # 0x00200000 +@ MSG_PF_SUNW_KILLED_NF "sunw_killed" +@ MSG_PF_SUNW_SIGINFO_CF "PF_SUNW_SIGINFO" # 0x00400000 +@ MSG_PF_SUNW_SIGINFO_NF "sunw_siginfo" @ MSG_GBL_ZERO "0" diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/Pcontrol.h --- a/usr/src/lib/libproc/common/Pcontrol.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/Pcontrol.h Tue Apr 02 13:52:19 2013 -0700 @@ -24,6 +24,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #ifndef _PCONTROL_H @@ -233,6 +234,9 @@ char *zoneroot; /* cached path to zone root */ plist_t fd_head; /* head of file desc info list */ int num_fd; /* number of file descs in list */ + uintptr_t map_missing; /* first missing mapping in core due to sig */ + siginfo_t killinfo; /* signal that interrupted core dump */ + psinfo_t spymaster; /* agent LWP's spymaster, if any */ }; /* flags */ diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/Pcore.c --- a/usr/src/lib/libproc/common/Pcore.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/Pcore.c Tue Apr 02 13:52:19 2013 -0700 @@ -24,11 +24,13 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include #include #include +#include #include #include @@ -40,6 +42,7 @@ #include #include #include +#include #include "libproc.h" #include "Pcontrol.h" @@ -672,6 +675,35 @@ #endif /* __sparcv9 */ #endif /* __sparc */ +static int +note_spymaster(struct ps_prochandle *P, size_t nbytes) +{ +#ifdef _LP64 + if (P->core->core_dmodel == PR_MODEL_ILP32) { + psinfo32_t ps32; + + if (nbytes < sizeof (psinfo32_t) || + read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32)) + goto err; + + psinfo_32_to_n(&ps32, &P->spymaster); + } else +#endif + if (nbytes < sizeof (psinfo_t) || read(P->asfd, + &P->spymaster, sizeof (psinfo_t)) != sizeof (psinfo_t)) + goto err; + + dprintf("spymaster pr_fname = <%s>\n", P->psinfo.pr_fname); + dprintf("spymaster pr_psargs = <%s>\n", P->psinfo.pr_psargs); + dprintf("spymaster pr_wstat = 0x%x\n", P->psinfo.pr_wstat); + + return (0); + +err: + dprintf("Pgrab_core: failed to read NT_SPYMASTER\n"); + return (-1); +} + /*ARGSUSED*/ static int note_notsup(struct ps_prochandle *P, size_t nbytes) @@ -725,8 +757,72 @@ note_content, /* 20 NT_CONTENT */ note_zonename, /* 21 NT_ZONENAME */ note_fdinfo, /* 22 NT_FDINFO */ + note_spymaster, /* 23 NT_SPYMASTER */ }; +static void +core_report_mapping(struct ps_prochandle *P, GElf_Phdr *php) +{ + prkillinfo_t killinfo; + siginfo_t *si = &killinfo.prk_info; + char signame[SIG2STR_MAX], sig[64], info[64]; + void *addr = (void *)(uintptr_t)php->p_vaddr; + + const char *errfmt = "core file data for mapping at %p not saved: %s\n"; + const char *incfmt = "core file incomplete due to %s%s\n"; + const char *msgfmt = "mappings at and above %p are missing\n"; + + if (!(php->p_flags & PF_SUNW_KILLED)) { + int err = 0; + + (void) pread64(P->asfd, &err, + sizeof (err), (off64_t)php->p_offset); + + Perror_printf(P, errfmt, addr, strerror(err)); + dprintf(errfmt, addr, strerror(err)); + return; + } + + if (!(php->p_flags & PF_SUNW_SIGINFO)) + return; + + (void) memset(&killinfo, 0, sizeof (killinfo)); + + (void) pread64(P->asfd, &killinfo, + sizeof (killinfo), (off64_t)php->p_offset); + + /* + * While there is (or at least should be) only one segment that has + * PF_SUNW_SIGINFO set, the signal information there is globally + * useful (even if only to those debugging libproc consumers); we hang + * the signal information gleaned here off of the ps_prochandle. + */ + P->map_missing = php->p_vaddr; + P->killinfo = killinfo.prk_info; + + if (sig2str(si->si_signo, signame) == -1) { + (void) snprintf(sig, sizeof (sig), + ", ", si->si_signo); + } else { + (void) snprintf(sig, sizeof (sig), "SIG%s, ", signame); + } + + if (si->si_code == SI_USER || si->si_code == SI_QUEUE) { + (void) snprintf(info, sizeof (info), + "pid=%d uid=%d zone=%d ctid=%d", + si->si_pid, si->si_uid, si->si_zoneid, si->si_ctid); + } else { + (void) snprintf(info, sizeof (info), + "code=%d", si->si_code); + } + + Perror_printf(P, incfmt, sig, info); + Perror_printf(P, msgfmt, addr); + + dprintf(incfmt, sig, info); + dprintf(msgfmt, addr); +} + /* * Add information on the address space mapping described by the given * PT_LOAD program header. We fill in more information on the mapping later. @@ -734,7 +830,6 @@ static int core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php) { - int err = 0; prmap_t pmap; dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n", @@ -749,14 +844,7 @@ * PF_SUNW_FAILURE in the Phdr and try to stash away the errno for us. */ if (php->p_flags & PF_SUNW_FAILURE) { - (void) pread64(P->asfd, &err, - sizeof (err), (off64_t)php->p_offset); - - Perror_printf(P, "core file data for mapping at %p not saved: " - "%s\n", (void *)(uintptr_t)php->p_vaddr, strerror(err)); - dprintf("core file data for mapping at %p not saved: %s\n", - (void *)(uintptr_t)php->p_vaddr, strerror(err)); - + core_report_mapping(P, php); } else if (php->p_filesz != 0 && php->p_offset >= P->core->core_size) { Perror_printf(P, "core file may be corrupt -- data for mapping " "at %p is missing\n", (void *)(uintptr_t)php->p_vaddr); diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/Pgcore.c --- a/usr/src/lib/libproc/common/Pgcore.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/Pgcore.c Tue Apr 02 13:52:19 2013 -0700 @@ -25,6 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #define _STRUCTURED_PROC 1 @@ -481,6 +482,7 @@ { pgcore_t *pgc = data; struct ps_prochandle *P = pgc->P; + psinfo_t ps; /* * If lsp is NULL this indicates that this is a zombie LWP in @@ -548,6 +550,27 @@ #endif /* __sparcv9 */ #endif /* sparc */ + if (!(lsp->pr_flags & PR_AGENT)) + return (0); + + if (Plwp_getspymaster(P, lsp->pr_lwpid, &ps) != 0) + return (0); + + if (P->status.pr_dmodel == PR_MODEL_NATIVE) { + if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps, + sizeof (psinfo_t), pgc->pgc_doff) != 0) + return (1); +#ifdef _LP64 + } else { + psinfo32_t ps32; + psinfo_n_to_32(&ps, &ps32); + if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps32, + sizeof (psinfo32_t), pgc->pgc_doff) != 0) + return (1); +#endif /* _LP64 */ + } + + return (0); } diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/Plwpregs.c --- a/usr/src/lib/libproc/common/Plwpregs.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/Plwpregs.c Tue Apr 02 13:52:19 2013 -0700 @@ -23,7 +23,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #include #include @@ -349,6 +351,39 @@ } int +Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps) +{ + lwpstatus_t lps; + + if (P->state == PS_IDLE) { + errno = ENODATA; + return (-1); + } + + if (getlwpstatus(P, lwpid, &lps) != 0) + return (-1); + + if (!(lps.pr_flags & PR_AGENT)) { + errno = EINVAL; + return (-1); + } + + if (P->state != PS_DEAD) { + return (getlwpfile(P, lwpid, "spymaster", + ps, sizeof (psinfo_t))); + } + + if (P->spymaster.pr_nlwp != 0) { + (void) memcpy(ps, &P->spymaster, sizeof (psinfo_t)); + return (0); + } + + errno = ENODATA; + + return (-1); +} + +int Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp) { uintptr_t addr; diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/Psyscall.c --- a/usr/src/lib/libproc/common/Psyscall.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/Psyscall.c Tue Apr 02 13:52:19 2013 -0700 @@ -22,8 +22,9 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + /* - * Copyright (c) 2013, Joyent Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include @@ -61,7 +62,7 @@ int sysnum = P->status.pr_lwp.pr_syscall; int stop; - dprintf("agent LWP is asleep in syscall %d\n", sysnum); + dprintf("agent LWP is stopped or asleep in syscall %d\n", sysnum); (void) Pstop(P, 0); stop = Psysexit(P, sysnum, TRUE); @@ -147,11 +148,16 @@ P->agentctlfd = fd; /* - * If the agent is currently asleep in a system call, attempt - * to abort the system call so it's ready to serve. + * If the agent is currently asleep in a system call or stopped on + * system call entry, attempt to abort the system call so it's ready to + * serve. */ - if (P->status.pr_lwp.pr_flags & PR_ASLEEP) { - dprintf("Pcreate_agent: aborting agent syscall\n"); + if ((P->status.pr_lwp.pr_flags & PR_ASLEEP) || + ((P->status.pr_lwp.pr_flags & PR_STOPPED) && + P->status.pr_lwp.pr_why == PR_SYSENTRY)) { + dprintf("Pcreate_agent: aborting agent syscall; lwp is %s\n", + (P->status.pr_lwp.pr_flags & PR_ASLEEP) ? + "asleep" : "stopped"); Pabort_agent(P); } diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/libproc.h --- a/usr/src/lib/libproc/common/libproc.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/libproc.h Tue Apr 02 13:52:19 2013 -0700 @@ -25,6 +25,7 @@ * * Portions Copyright 2007 Chad Mynhier * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -389,6 +390,7 @@ #endif /* __i386 || __amd64 */ extern int Plwp_getpsinfo(struct ps_prochandle *, lwpid_t, lwpsinfo_t *); +extern int Plwp_getspymaster(struct ps_prochandle *, lwpid_t, psinfo_t *); extern int Plwp_stack(struct ps_prochandle *, lwpid_t, stack_t *); extern int Plwp_main_stack(struct ps_prochandle *, lwpid_t, stack_t *); diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/lib/libproc/common/mapfile-vers --- a/usr/src/lib/libproc/common/mapfile-vers Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/lib/libproc/common/mapfile-vers Tue Apr 02 13:52:19 2013 -0700 @@ -21,6 +21,7 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # # @@ -133,6 +134,7 @@ Plwp_getfpregs; Plwp_getpsinfo; Plwp_getregs; + Plwp_getspymaster; Plwp_iter; Plwp_iter_all; Plwp_main_stack; diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/man/man4/core.4 --- a/usr/src/man/man4/core.4 Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/man/man4/core.4 Tue Apr 02 13:52:19 2013 -0700 @@ -1,11 +1,12 @@ '\" te .\" Copyright (C) 2008, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +.\" Copyright (c) 2013, Joyent, Inc. All rights reserved. .\" Copyright 1989 AT&T .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CORE 4 "Oct 23, 2012" +.TH CORE 4 "Mar 31, 2013" .SH NAME core \- process core file .SH DESCRIPTION @@ -130,9 +131,13 @@ .sp .LP A mapping's data can be excluded due to the core file content settings (see -\fBcoreadm\fR(1M)), or due to some failure. If the data is excluded because of -a failure, the program header entry will have the \fBPF_SUNW_FAILURE\fR flag -set in its \fBp_flags\fR field. +\fBcoreadm\fR(1M)), due to a failure, or due to a signal received after +core dump initiation but before its completion. If the data is excluded +because of a failure, the program header entry will have the +\fBPF_SUNW_FAILURE\fR flag +set in its \fBp_flags\fR field; if the data is excluded because of a signal, +the segment's \fBp_flags\fR field will have the \fBPF_SUNW_KILLED\fR +flag set. .sp .LP The program headers of an \fBELF\fR core file also contain entries for two @@ -434,6 +439,18 @@ .RE .sp +.ne 2 +.na +\fB\fBpsinfo_t\fR\fR +.ad +.RS 15n +\fBn_type\fR: \fBNT_SPYMASTER\fR. This entry is present only for an agent +LWP and contains the \fBpsinfo_t\fR of the process that created the agent +LWP. See the \fBproc\fR(4) description of the \fBspymaster\fR entry for +more details. +.RE + +.sp .LP Depending on the \fBcoreadm\fR(1M) settings, the section header of an ELF core file can contain entries for CTF, symbol table, and string table sections. The diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/man/man4/proc.4 --- a/usr/src/man/man4/proc.4 Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/man/man4/proc.4 Tue Apr 02 13:52:19 2013 -0700 @@ -1,10 +1,11 @@ '\" te .\" Copyright 1989 AT&T .\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved. +.\" Copyright (c) 2013, Joyent, Inc. All rights reserved. .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH PROC 4 "Nov 29, 2006" +.TH PROC 4 "Mar 31, 2013" .SH NAME proc \- /proc, the process file system .SH DESCRIPTION @@ -1481,7 +1482,7 @@ within the process. These entries are themselves directories containing additional files as described below. Only the \fBlwpsinfo\fR file exists in the directory of a zombie lwp. -.SH STRUCTURE OF \fB/proc/\fR\fIpid\fR\fB/lwp/\fR \fIlwpid\fR +.SH STRUCTURE OF \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR .sp .LP A given directory \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR contains the @@ -1538,6 +1539,15 @@ values of the lwp's platform-dependent ancillary state registers. If the lwp is not stopped, all register values are undefined. See also the \fBPCSASRS\fR control operation, below. +.SS "spymaster" +.sp +.LP +For an agent lwp (see \fBPCAGENT\fR), this file contains a \fBpsinfo_t\fR +structure that corresponds to the process that created the agent lwp at the +time the agent was created. This structure is identical to that retrieved via +the \fBpsinfo\fR file, with one modification: the \fBpr_time\fR field does not +correspond to the CPU time for the process, but rather to the creation time of +the agent lwp. .SS "templates" .sp .LP @@ -2263,6 +2273,16 @@ of the representative lwp, so that the agent lwp can use its stack. .sp .LP +If the controlling process neglects to force the agent lwp to execute the +\fBSYS_lwp_exit\fR system call (due to either logic error or fatal failure on +the part of the controlling process), the agent lwp will remain in the target +process. For purposes of being able to debug these otherwise rogue agents, +information as to the creator of the agent lwp is reflected in that lwp's +\fBspymaster\fR file in \fB/proc\fR. Should the target process generate a core +dump with the agent lwp in place, this information will be available via the +\fBNT_SPYMASTER\fR note in the core file (see \fBcore\fR(4)). +.sp +.LP The agent lwp is not allowed to execute any variation of the \fBSYS_fork\fR or \fBSYS_exec\fR system call traps. Attempts to do so yield \fBENOTSUP\fR to the agent lwp. @@ -2789,6 +2809,16 @@ ancillary state registers (SPARC V9 only) .RE +.sp +.ne 2 +.na +\fB\fB/proc/\fIpid\fR/lwp/\fIlwpid\fR/spymaster\fR\fR +.ad +.sp .6 +.RS 4n +For an agent LWP, the controlling process +.RE + .SH SEE ALSO .sp .LP @@ -2803,8 +2833,8 @@ \fBreaddir\fR(3C), \fBpthread_create\fR(3C), \fBpthread_join\fR(3C), \fBsiginfo.h\fR(3HEAD), \fBsignal.h\fR(3HEAD), \fBthr_create\fR(3C), \fBthr_join\fR(3C), \fBtypes32.h\fR(3HEAD), \fBucontext.h\fR(3HEAD), -\fBwait\fR(3C), \fBcontract\fR(4), \fBprocess\fR(4), \fBlfcompile\fR(5), -\fBprivileges\fR(5) +\fBwait\fR(3C), \fBcontract\fR(4), \fBcore\fR(4), \fBprocess\fR(4), +\fBlfcompile\fR(5), \fBprivileges\fR(5) .SH DIAGNOSTICS .sp .LP diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/exec/elf/elf.c --- a/usr/src/uts/common/exec/elf/elf.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/exec/elf/elf.c Tue Apr 02 13:52:19 2013 -0700 @@ -64,6 +64,7 @@ #include #include "elf_impl.h" #include +#include extern int at_flags; @@ -1726,6 +1727,7 @@ caddr_t stkbase; size_t stksize; int ntries = 0; + klwp_t *lwp = ttolwp(curthread); top: /* @@ -1989,6 +1991,10 @@ goto done; for (i = 2; i < nphdrs; i++) { + prkillinfo_t killinfo; + sigqueue_t *sq; + int sig, j; + if (v[i].p_filesz == 0) continue; @@ -2002,9 +2008,13 @@ */ if ((error = core_seg(p, vp, v[i].p_offset, (caddr_t)(uintptr_t)v[i].p_vaddr, v[i].p_filesz, - rlimit, credp)) != 0) { + rlimit, credp)) == 0) { + continue; + } + if ((sig = lwp->lwp_cursig) == 0) { /* + * We failed due to something other than a signal. * Since the space reserved for the segment is now * unused, we stash the errno in the first four * bytes. This undocumented interface will let us @@ -2019,7 +2029,75 @@ poffset + sizeof (v[i]) * i, &v[i], sizeof (v[i]), rlimit, credp)) != 0) goto done; + + continue; } + + /* + * We took a signal. We want to abort the dump entirely, but + * we also want to indicate what failed and why. We therefore + * use the space reserved for the first failing segment to + * write our error (which, for purposes of compatability with + * older core dump readers, we set to EINTR) followed by any + * siginfo associated with the signal. + */ + bzero(&killinfo, sizeof (killinfo)); + killinfo.prk_error = EINTR; + + sq = sig == SIGKILL ? curproc->p_killsqp : lwp->lwp_curinfo; + + if (sq != NULL) { + bcopy(&sq->sq_info, &killinfo.prk_info, + sizeof (killinfo.prk_info)); + } else { + killinfo.prk_info.si_signo = lwp->lwp_cursig; + killinfo.prk_info.si_code = SI_NOINFO; + } + +#if (defined(_SYSCALL32_IMPL) || defined(_LP64)) + /* + * If this is a 32-bit process, we need to translate from the + * native siginfo to the 32-bit variant. (Core readers must + * always have the same data model as their target or must + * be aware of -- and compensate for -- data model differences.) + */ + if (curproc->p_model == DATAMODEL_ILP32) { + siginfo32_t si32; + + siginfo_kto32((k_siginfo_t *)&killinfo.prk_info, &si32); + bcopy(&si32, &killinfo.prk_info, sizeof (si32)); + } +#endif + + (void) core_write(vp, UIO_SYSSPACE, v[i].p_offset, + &killinfo, sizeof (killinfo), rlimit, credp); + + /* + * For the segment on which we took the signal, indicate that + * its data now refers to a siginfo. + */ + v[i].p_filesz = 0; + v[i].p_flags |= PF_SUNW_FAILURE | PF_SUNW_KILLED | + PF_SUNW_SIGINFO; + + /* + * And for every other segment, indicate that its absence + * is due to a signal. + */ + for (j = i + 1; j < nphdrs; j++) { + v[j].p_filesz = 0; + v[j].p_flags |= PF_SUNW_FAILURE | PF_SUNW_KILLED; + } + + /* + * Finally, write out our modified program headers. + */ + if ((error = core_write(vp, UIO_SYSSPACE, + poffset + sizeof (v[i]) * i, &v[i], + sizeof (v[i]) * (nphdrs - i), rlimit, credp)) != 0) + goto done; + + break; } if (nshdrs > 0) { diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/exec/elf/elf_notes.c --- a/usr/src/uts/common/exec/elf/elf_notes.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/exec/elf/elf_notes.c Tue Apr 02 13:52:19 2013 -0700 @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include @@ -107,6 +108,11 @@ + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word)); + if (curproc->p_agenttp != NULL) { + v[0].p_filesz += sizeof (Note) + + roundup(sizeof (psinfo_t), sizeof (Word)); + } + size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); pcrp = kmem_alloc(size, KM_SLEEP); prgetcred(p, pcrp); @@ -519,6 +525,31 @@ if (error) goto done; } + + if (t->t_lwp->lwp_spymaster != NULL) { + void *psaddr = t->t_lwp->lwp_spymaster; +#ifdef _ELF32_COMPAT + /* + * On a 64-bit kernel with 32-bit ELF compatibility, + * this file is compiled into two different objects: + * one is compiled normally, and the other is compiled + * with _ELF32_COMPAT set -- and therefore with a + * psinfo_t defined to be a psinfo32_t. However, the + * psinfo_t denoting our spymaster is always of the + * native type; if we are in the _ELF32_COMPAT case, + * we need to explicitly convert it. + */ + if (p->p_model == DATAMODEL_ILP32) { + psinfo_kto32(psaddr, &bigwad->psinfo); + psaddr = &bigwad->psinfo; + } +#endif + + error = elfnote(vp, &offset, NT_SPYMASTER, + sizeof (psinfo_t), psaddr, rlimit, credp); + if (error) + goto done; + } } ASSERT(nlwp == 0); diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/fs/proc/prcontrol.c --- a/usr/src/uts/common/fs/proc/prcontrol.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/fs/proc/prcontrol.c Tue Apr 02 13:52:19 2013 -0700 @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #include #include #include @@ -2008,6 +2012,23 @@ return (ENOMEM); } prsetprregs(clwp, prgregset, 1); + + /* + * Because abandoning the agent inside the target process leads to + * a state that is essentially undebuggable, we record the psinfo of + * the process creating the agent and hang that off of the lwp. + */ + clwp->lwp_spymaster = kmem_zalloc(sizeof (psinfo_t), KM_SLEEP); + mutex_enter(&curproc->p_lock); + prgetpsinfo(curproc, clwp->lwp_spymaster); + mutex_exit(&curproc->p_lock); + + /* + * We overload pr_time in the spymaster to denote the time at which the + * agent was created. + */ + gethrestime(&clwp->lwp_spymaster->pr_time); + retry: cid = t->t_cid; (void) CL_ALLOC(&bufp, cid, KM_SLEEP); diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/fs/proc/prdata.h --- a/usr/src/uts/common/fs/proc/prdata.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/fs/proc/prdata.h Tue Apr 02 13:52:19 2013 -0700 @@ -26,12 +26,13 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #ifndef _SYS_PROC_PRDATA_H #define _SYS_PROC_PRDATA_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -141,6 +142,7 @@ PR_XREGS, /* /proc//lwp//xregs */ PR_TMPLDIR, /* /proc//lwp//templates */ PR_TMPL, /* /proc//lwp//templates/ */ + PR_SPYMASTER, /* /proc//lwp//spymaster */ #if defined(__sparc) PR_GWINDOWS, /* /proc//lwp//gwindows */ PR_ASRS, /* /proc//lwp//asrs */ diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/fs/proc/prsubr.c --- a/usr/src/uts/common/fs/proc/prsubr.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/fs/proc/prsubr.c Tue Apr 02 13:52:19 2013 -0700 @@ -21,6 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -2490,6 +2491,7 @@ psp->pr_envp = 0; } } + #endif /* _SYSCALL32_IMPL */ void @@ -2628,6 +2630,100 @@ } #endif /* _SYSCALL32_IMPL */ +#ifdef _SYSCALL32_IMPL + +#define PR_COPY_FIELD(s, d, field) d->field = s->field + +#define PR_COPY_FIELD_ILP32(s, d, field) \ + if (s->pr_dmodel == PR_MODEL_ILP32) { \ + d->field = s->field; \ + } + +#define PR_COPY_TIMESPEC(s, d, field) \ + TIMESPEC_TO_TIMESPEC32(&d->field, &s->field); + +#define PR_COPY_BUF(s, d, field) \ + bcopy(s->field, d->field, sizeof (d->field)); + +#define PR_IGNORE_FIELD(s, d, field) + +void +lwpsinfo_kto32(const struct lwpsinfo *src, struct lwpsinfo32 *dest) +{ + bzero(dest, sizeof (*dest)); + + PR_COPY_FIELD(src, dest, pr_flag); + PR_COPY_FIELD(src, dest, pr_lwpid); + PR_IGNORE_FIELD(src, dest, pr_addr); + PR_IGNORE_FIELD(src, dest, pr_wchan); + PR_COPY_FIELD(src, dest, pr_stype); + PR_COPY_FIELD(src, dest, pr_state); + PR_COPY_FIELD(src, dest, pr_sname); + PR_COPY_FIELD(src, dest, pr_nice); + PR_COPY_FIELD(src, dest, pr_syscall); + PR_COPY_FIELD(src, dest, pr_oldpri); + PR_COPY_FIELD(src, dest, pr_cpu); + PR_COPY_FIELD(src, dest, pr_pri); + PR_COPY_FIELD(src, dest, pr_pctcpu); + PR_COPY_TIMESPEC(src, dest, pr_start); + PR_COPY_BUF(src, dest, pr_clname); + PR_COPY_BUF(src, dest, pr_name); + PR_COPY_FIELD(src, dest, pr_onpro); + PR_COPY_FIELD(src, dest, pr_bindpro); + PR_COPY_FIELD(src, dest, pr_bindpset); + PR_COPY_FIELD(src, dest, pr_lgrp); +} + +void +psinfo_kto32(const struct psinfo *src, struct psinfo32 *dest) +{ + bzero(dest, sizeof (*dest)); + + PR_COPY_FIELD(src, dest, pr_flag); + PR_COPY_FIELD(src, dest, pr_nlwp); + PR_COPY_FIELD(src, dest, pr_pid); + PR_COPY_FIELD(src, dest, pr_ppid); + PR_COPY_FIELD(src, dest, pr_pgid); + PR_COPY_FIELD(src, dest, pr_sid); + PR_COPY_FIELD(src, dest, pr_uid); + PR_COPY_FIELD(src, dest, pr_euid); + PR_COPY_FIELD(src, dest, pr_gid); + PR_COPY_FIELD(src, dest, pr_egid); + PR_IGNORE_FIELD(src, dest, pr_addr); + PR_COPY_FIELD_ILP32(src, dest, pr_size); + PR_COPY_FIELD_ILP32(src, dest, pr_rssize); + PR_COPY_FIELD(src, dest, pr_ttydev); + PR_COPY_FIELD(src, dest, pr_pctcpu); + PR_COPY_FIELD(src, dest, pr_pctmem); + PR_COPY_TIMESPEC(src, dest, pr_start); + PR_COPY_TIMESPEC(src, dest, pr_time); + PR_COPY_TIMESPEC(src, dest, pr_ctime); + PR_COPY_BUF(src, dest, pr_fname); + PR_COPY_BUF(src, dest, pr_psargs); + PR_COPY_FIELD(src, dest, pr_wstat); + PR_COPY_FIELD(src, dest, pr_argc); + PR_COPY_FIELD_ILP32(src, dest, pr_argv); + PR_COPY_FIELD_ILP32(src, dest, pr_envp); + PR_COPY_FIELD(src, dest, pr_dmodel); + PR_COPY_FIELD(src, dest, pr_taskid); + PR_COPY_FIELD(src, dest, pr_projid); + PR_COPY_FIELD(src, dest, pr_nzomb); + PR_COPY_FIELD(src, dest, pr_poolid); + PR_COPY_FIELD(src, dest, pr_contract); + PR_COPY_FIELD(src, dest, pr_poolid); + PR_COPY_FIELD(src, dest, pr_poolid); + + lwpsinfo_kto32(&src->pr_lwp, &dest->pr_lwp); +} + +#undef PR_COPY_FIELD +#undef PR_COPY_FIELD_ILP32 +#undef PR_COPY_TIMESPEC +#undef PR_COPY_BUF +#undef PR_IGNORE_FIELD + +#endif /* _SYSCALL32_IMPL */ + /* * This used to get called when microstate accounting was disabled but * microstate information was requested. Since Microstate accounting is on diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/fs/proc/prvnops.c --- a/usr/src/uts/common/fs/proc/prvnops.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/fs/proc/prvnops.c Tue Apr 02 13:52:19 2013 -0700 @@ -21,6 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -189,10 +190,12 @@ "xregs" }, { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t), "templates" }, + { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t), + "spymaster" }, #if defined(__sparc) - { PR_GWINDOWS, 9 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_GWINDOWS, 10 * sizeof (prdirent_t), sizeof (prdirent_t), "gwindows" }, - { PR_ASRS, 10 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_ASRS, 11 * sizeof (prdirent_t), sizeof (prdirent_t), "asrs" }, #endif }; @@ -573,6 +576,7 @@ pr_read_usage(), pr_read_lusage(), pr_read_pagedata(), pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(), pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(), + pr_read_spymaster(), #if defined(__sparc) pr_read_gwindows(), pr_read_asrs(), #endif @@ -616,6 +620,7 @@ pr_read_xregs, /* /proc//lwp//xregs */ pr_read_inval, /* /proc//lwp//templates */ pr_read_inval, /* /proc//lwp//templates/ */ + pr_read_spymaster, /* /proc//lwp//spymaster */ #if defined(__sparc) pr_read_gwindows, /* /proc//lwp//gwindows */ pr_read_asrs, /* /proc//lwp//asrs */ @@ -1562,6 +1567,31 @@ #endif } +static int +pr_read_spymaster(prnode_t *pnp, uio_t *uiop) +{ + psinfo_t psinfo; + int error; + klwp_t *lwp; + + ASSERT(pnp->pr_type == PR_SPYMASTER); + + if ((error = prlock(pnp, ZNO)) != 0) + return (error); + + lwp = pnp->pr_common->prc_thread->t_lwp; + + if (lwp->lwp_spymaster == NULL) { + prunlock(pnp); + return (0); + } + + bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t)); + prunlock(pnp); + + return (pr_uioread(&psinfo, sizeof (psinfo), uiop)); +} + #if defined(__sparc) static int @@ -1703,7 +1733,7 @@ pr_read_sigact_32(), pr_read_auxv_32(), pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(), pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(), - pr_read_lwpusage_32(), + pr_read_lwpusage_32(), pr_read_spymaster_32(), #if defined(__sparc) pr_read_gwindows_32(), #endif @@ -1747,6 +1777,7 @@ pr_read_xregs, /* /proc//lwp//xregs */ pr_read_inval, /* /proc//lwp//templates */ pr_read_inval, /* /proc//lwp//templates/ */ + pr_read_spymaster_32, /* /proc//lwp//spymaster */ #if defined(__sparc) pr_read_gwindows_32, /* /proc//lwp//gwindows */ pr_read_asrs, /* /proc//lwp//asrs */ @@ -2545,6 +2576,31 @@ return (error); } +static int +pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop) +{ + psinfo32_t psinfo; + int error; + klwp_t *lwp; + + ASSERT(pnp->pr_type == PR_SPYMASTER); + + if ((error = prlock(pnp, ZNO)) != 0) + return (error); + + lwp = pnp->pr_common->prc_thread->t_lwp; + + if (lwp->lwp_spymaster == NULL) { + prunlock(pnp); + return (0); + } + + psinfo_kto32(lwp->lwp_spymaster, &psinfo); + prunlock(pnp); + + return (pr_uioread(&psinfo, sizeof (psinfo), uiop)); +} + #if defined(__sparc) static int pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop) @@ -3054,6 +3110,13 @@ else vap->va_size = 0; break; + case PR_SPYMASTER: + if (pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) { + vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t); + } else { + vap->va_size = 0; + } + break; #if defined(__sparc) case PR_GWINDOWS: { @@ -3254,6 +3317,7 @@ pr_lookup_notdir, /* /proc//lwp//xregs */ pr_lookup_tmpldir, /* /proc//lwp//templates */ pr_lookup_notdir, /* /proc//lwp//templates/ */ + pr_lookup_notdir, /* /proc//lwp//spymaster */ #if defined(__sparc) pr_lookup_notdir, /* /proc//lwp//gwindows */ pr_lookup_notdir, /* /proc//lwp//asrs */ @@ -4602,6 +4666,7 @@ pr_readdir_notdir, /* /proc//lwp//xregs */ pr_readdir_tmpldir, /* /proc//lwp//templates */ pr_readdir_notdir, /* /proc//lwp//templates/ */ + pr_readdir_notdir, /* /proc//lwp//spymaster */ #if defined(__sparc) pr_readdir_notdir, /* /proc//lwp//gwindows */ pr_readdir_notdir, /* /proc//lwp//asrs */ diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/os/core.c --- a/usr/src/uts/common/os/core.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/os/core.c Tue Apr 02 13:52:19 2013 -0700 @@ -651,11 +651,11 @@ } /* - * Block all signals except SIGHUP, SIGINT, SIGKILL, and SIGTERM. - * These signals are allowed to interrupt the core dump. - * SIGQUIT is not allowed because it is supposed to make a core. - * Additionally, get current limit on core file size for handling later - * error reporting. + * Block all signals except SIGHUP, SIGINT, SIGKILL, and SIGTERM; no + * other signal may interrupt a core dump. For each signal, we + * explicitly unblock it and set it in p_siginfo to allow for some + * minimal error reporting. Additionally, we get the current limit on + * core file size for handling later error reporting. */ mutex_enter(&p->p_lock); @@ -671,6 +671,12 @@ sigdelset(&sighold, SIGKILL); if (!sigismember(&sigmask, SIGTERM)) sigdelset(&sighold, SIGTERM); + + sigaddset(&p->p_siginfo, SIGHUP); + sigaddset(&p->p_siginfo, SIGINT); + sigaddset(&p->p_siginfo, SIGKILL); + sigaddset(&p->p_siginfo, SIGTERM); + curthread->t_hold = sighold; rlimit = rctl_enforced_value(rctlproc_legacy[RLIMIT_CORE], p->p_rctls, @@ -789,6 +795,7 @@ len = eaddr - base; if (as_memory(p->p_as, &base, &len) != 0) return (0); + /* * Reduce len to a reasonable value so that we don't * overwhelm the VM system with a monstrously large @@ -800,16 +807,17 @@ err = core_write(vp, UIO_USERSPACE, offset + (size_t)(base - addr), base, len, rlimit, credp); - if (err == 0) { - /* - * Give pageout a chance to run. - * Also allow core dumping to be interruptible. - */ - err = delay_sig(drv_usectohz(core_delay_usec)); - } if (err) return (err); + + /* + * If we have taken a signal, return EINTR to allow the dump + * to be aborted. + */ + if (issig(JUSTLOOKING) && issig(FORREAL)) + return (EINTR); } + return (0); } diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/os/lwp.c --- a/usr/src/uts/common/os/lwp.c Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/os/lwp.c Tue Apr 02 13:52:19 2013 -0700 @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #include #include #include @@ -995,6 +999,15 @@ lwp->lwp_curinfo = NULL; } + /* + * If we have spymaster information (that is, if we're an agent LWP), + * free that now. + */ + if (lwp->lwp_spymaster != NULL) { + kmem_free(lwp->lwp_spymaster, sizeof (psinfo_t)); + lwp->lwp_spymaster = NULL; + } + thread_rele(t); /* diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/sys/elf.h --- a/usr/src/uts/common/sys/elf.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/sys/elf.h Tue Apr 02 13:52:19 2013 -0700 @@ -20,6 +20,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. @@ -366,6 +367,8 @@ #define PF_MASKPROC 0xf0000000 /* processor specific values */ #define PF_SUNW_FAILURE 0x00100000 /* mapping absent due to failure */ +#define PF_SUNW_KILLED 0x00200000 /* signal received during dump */ +#define PF_SUNW_SIGINFO 0x00400000 /* segment has killing sig's siginfo */ #define PN_XNUM 0xffff /* extended program header index */ @@ -816,7 +819,8 @@ #define NT_CONTENT 20 /* core_content_t */ #define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */ #define NT_FDINFO 22 /* open fd info */ -#define NT_NUM 22 +#define NT_SPYMASTER 23 /* psinfo_t for agent LWP spymaster */ +#define NT_NUM 23 #ifdef _KERNEL diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/sys/klwp.h --- a/usr/src/uts/common/sys/klwp.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/sys/klwp.h Tue Apr 02 13:52:19 2013 -0700 @@ -23,11 +23,13 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #ifndef _SYS_KLWP_H #define _SYS_KLWP_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -190,6 +192,7 @@ struct contract *lwp_ct_latest[CTT_MAXTYPE]; /* last created contract */ void *lwp_brand; /* per-lwp brand data */ + struct psinfo *lwp_spymaster; /* if an agent LWP, our spymaster */ } klwp_t; /* lwp states */ diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/sys/proc.h --- a/usr/src/uts/common/sys/proc.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/sys/proc.h Tue Apr 02 13:52:19 2013 -0700 @@ -574,6 +574,12 @@ LWP_STAT_MSGSND } lwp_stat_id_t; +typedef struct prkillinfo { + int32_t prk_error; /* errno */ + int32_t prk_pad; /* pad */ + siginfo_t prk_info; /* siginfo of killing signal */ +} prkillinfo_t; + #ifdef _KERNEL /* user profiling functions */ diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/common/sys/prsystm.h --- a/usr/src/uts/common/sys/prsystm.h Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/common/sys/prsystm.h Tue Apr 02 13:52:19 2013 -0700 @@ -27,6 +27,9 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #ifndef _SYS_PRSYSTM_H #define _SYS_PRSYSTM_H @@ -129,6 +132,8 @@ extern void prgetlwpstatus32(kthread_t *, struct lwpstatus32 *, zone_t *); extern void prgetpsinfo32(proc_t *, struct psinfo32 *); extern void prgetlwpsinfo32(kthread_t *, struct lwpsinfo32 *); +extern void lwpsinfo_kto32(const struct lwpsinfo *src, struct lwpsinfo32 *dest); +extern void psinfo_kto32(const struct psinfo *src, struct psinfo32 *dest); extern void prgetprfpregs32(klwp_t *, struct prfpregset32 *); #if defined(__sparc) struct gwindows32; diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/intel/ia32/ml/modstubs.s --- a/usr/src/uts/intel/ia32/ml/modstubs.s Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/intel/ia32/ml/modstubs.s Tue Apr 02 13:52:19 2013 -0700 @@ -21,6 +21,7 @@ /* * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include @@ -695,6 +696,8 @@ NO_UNLOAD_STUB(procfs, prgetlwpsinfo32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetstatus32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetpsinfo32, nomod_zero); + NO_UNLOAD_STUB(procfs, psinfo_kto32, nomod_zero); + NO_UNLOAD_STUB(procfs, lwpsinfo_kto32, nomod_zero); #endif /* _SYSCALL32_IMPL */ NO_UNLOAD_STUB(procfs, prnotify, nomod_zero); NO_UNLOAD_STUB(procfs, prexecstart, nomod_zero); diff -r 779e63d911a5 -r c1f1ea4feeb1 usr/src/uts/sparc/ml/modstubs.s --- a/usr/src/uts/sparc/ml/modstubs.s Tue Apr 02 17:25:01 2013 -0700 +++ b/usr/src/uts/sparc/ml/modstubs.s Tue Apr 02 13:52:19 2013 -0700 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #if !defined(lint) @@ -582,6 +583,8 @@ NO_UNLOAD_STUB(procfs, prgetlwpsinfo32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetstatus32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetpsinfo32, nomod_zero); + NO_UNLOAD_STUB(procfs, psinfo_kto32, nomod_zero); + NO_UNLOAD_STUB(procfs, lwpsinfo_kto32, nomod_zero); #endif /* _SYSCALL32_IMPL */ NO_UNLOAD_STUB(procfs, prnotify, nomod_zero); NO_UNLOAD_STUB(procfs, prexecstart, nomod_zero);