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 * Copyright (c) 2016 by Delphix. All rights reserved.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/time.h>
34 #include <sys/sysmacros.h>
35 #include <sys/proc.h>
36 #include <sys/systm.h>
37 #include <sys/cred.h>
38 #include <sys/user.h>
39 #include <sys/utsname.h>
40 #include <sys/errno.h>
41 #include <sys/signal.h>
42 #include <sys/siginfo.h>
43 #include <sys/fault.h>
44 #include <sys/syscall.h>
45 #include <sys/ucontext.h>
47 #include <sys/vnode.h>
48 #include <sys/var.h>
49 #include <sys/file.h>
50 #include <sys/pathname.h>
51 #include <sys/vfs.h>
52 #include <sys/exec.h>
53 #include <sys/debug.h>
54 #include <sys/stack.h>
55 #include <sys/kmem.h>
56 #include <sys/schedctl.h>
57 #include <sys/core.h>
58 #include <sys/corectl.h>
59 #include <sys/cmn_err.h>
60 #include <vm/as.h>
61 #include <sys/rctl.h>
62 #include <sys/nbmlock.h>
63 #include <sys/stat.h>
64 #include <sys/zone.h>
65 #include <sys/contract/process_impl.h>
66 #include <sys/ddi.h>
67
68 /*
69 * Processes running within a zone potentially dump core in 3 locations,
70 * based on the per-process, per-zone, and the global zone's core settings.
71 *
72 * Per-zone and global zone settings are often referred to as "global"
73 * settings since they apply to the system (or zone) as a whole, as
74 * opposed to a particular process.
75 */
76 enum core_types {
77 CORE_PROC, /* Use per-process settings */
78 CORE_ZONE, /* Use per-zone settings */
79 CORE_GLOBAL /* Use global zone settings */
80 };
81
82 /*
83 * Log information about "global" core dumps to syslog.
84 */
85 static void
86 core_log(struct core_globals *cg, int error, const char *why, const char *path,
87 zoneid_t zoneid)
88 {
89 proc_t *p = curproc;
90 pid_t pid = p->p_pid;
91 char *fn = PTOU(p)->u_comm;
92
93 if (!(cg->core_options & CC_GLOBAL_LOG))
94 return;
95
96 if (path == NULL)
97 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s", fn, pid, why);
98 else if (error == 0)
99 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s: %s", fn, pid,
100 why, path);
101 else
102 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s, errno=%d: %s",
103 fn, pid, why, error, path);
104 }
105
106 /*
107 * Private version of vn_remove().
108 * Refuse to unlink a directory or an unwritable file.
109 * Also allow the process to access files normally inaccessible due to
110 * chroot(2) or Zone limitations.
111 */
112 static int
113 remove_core_file(char *fp, enum core_types core_type)
114 {
115 vnode_t *vp = NULL; /* entry vnode */
116 vnode_t *dvp; /* ptr to parent dir vnode */
117 vfs_t *dvfsp;
118 int error;
119 int in_crit = 0;
120 pathname_t pn; /* name of entry */
121 vnode_t *startvp, *rootvp;
122
123 if ((error = pn_get(fp, UIO_SYSSPACE, &pn)) != 0)
124 return (error);
125 /*
126 * Determine what rootvp to use.
746 if (my_cg->core_options & CC_GLOBAL_PATH)
747 error2 = dump_one_core(sig, rlimit, CORE_ZONE, my_cg,
748 &fp_global);
749 if (global_cg != my_cg && (global_cg->core_options & CC_GLOBAL_PATH))
750 error3 = dump_one_core(sig, rlimit, CORE_GLOBAL, global_cg,
751 &fp_zone);
752
753 /*
754 * Restore the signal hold mask.
755 */
756 mutex_enter(&p->p_lock);
757 curthread->t_hold = sigmask;
758 mutex_exit(&p->p_lock);
759
760 if (!ext && p->p_ct_process != NULL)
761 contract_process_core(p->p_ct_process, p, sig,
762 error1 == 0 ? fp_process : NULL,
763 error2 == 0 ? fp_global : NULL,
764 error3 == 0 ? fp_zone : NULL);
765
766 if (fp_process != NULL)
767 kmem_free(fp_process, MAXPATHLEN);
768 if (fp_global != NULL)
769 kmem_free(fp_global, MAXPATHLEN);
770 if (fp_zone != NULL)
771 kmem_free(fp_zone, MAXPATHLEN);
772
773 /*
774 * Return non-zero if no core file was created.
775 */
776 return (error1 != 0 && error2 != 0 && error3 != 0);
777 }
778
779 /*
780 * Maximum chunk size for dumping core files,
781 * size in pages, patchable in /etc/system
782 */
783 uint_t core_chunk = 32;
784
785 /*
|
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 * Copyright (c) 2016 by Delphix. All rights reserved.
26 * Copyright 2017 Nexenta Systems, Inc.
27 */
28
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <sys/sysmacros.h>
36 #include <sys/proc.h>
37 #include <sys/systm.h>
38 #include <sys/cred.h>
39 #include <sys/user.h>
40 #include <sys/utsname.h>
41 #include <sys/errno.h>
42 #include <sys/signal.h>
43 #include <sys/siginfo.h>
44 #include <sys/fault.h>
45 #include <sys/syscall.h>
46 #include <sys/ucontext.h>
48 #include <sys/vnode.h>
49 #include <sys/var.h>
50 #include <sys/file.h>
51 #include <sys/pathname.h>
52 #include <sys/vfs.h>
53 #include <sys/exec.h>
54 #include <sys/debug.h>
55 #include <sys/stack.h>
56 #include <sys/kmem.h>
57 #include <sys/schedctl.h>
58 #include <sys/core.h>
59 #include <sys/corectl.h>
60 #include <sys/cmn_err.h>
61 #include <vm/as.h>
62 #include <sys/rctl.h>
63 #include <sys/nbmlock.h>
64 #include <sys/stat.h>
65 #include <sys/zone.h>
66 #include <sys/contract/process_impl.h>
67 #include <sys/ddi.h>
68 #include <sys/fm/protocol.h>
69 #include <sys/fm/util.h>
70 #include <sys/fm/sw/core.h>
71 #include <sys/sysevent.h>
72
73 /*
74 * Processes running within a zone potentially dump core in 3 locations,
75 * based on the per-process, per-zone, and the global zone's core settings.
76 *
77 * Per-zone and global zone settings are often referred to as "global"
78 * settings since they apply to the system (or zone) as a whole, as
79 * opposed to a particular process.
80 */
81 enum core_types {
82 CORE_PROC, /* Use per-process settings */
83 CORE_ZONE, /* Use per-zone settings */
84 CORE_GLOBAL /* Use global zone settings */
85 };
86
87 /*
88 * Log information about "global" core dumps to syslog.
89 */
90 static void
91 core_log(struct core_globals *cg, int error, const char *why, const char *path,
92 zoneid_t zoneid)
93 {
94 proc_t *p = curproc;
95 pid_t pid = p->p_pid;
96 char *fn = PTOU(p)->u_comm;
97
98 if (!(cg->core_options & CC_GLOBAL_LOG))
99 return;
100
101 if (path == NULL)
102 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s", fn, pid, why);
103 else if (error == 0)
104 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s: %s", fn, pid,
105 why, path);
106 else
107 zcmn_err(zoneid, CE_NOTE, "core_log: %s[%d] %s, errno=%d: %s",
108 fn, pid, why, error, path);
109 }
110
111 /*
112 * Generate FMA e-report for a core.
113 */
114 static void
115 gen_ereport(const char *path, int sig)
116 {
117 nvlist_t *ereport = NULL;
118 nvlist_t *fmri = NULL;
119 nvlist_t *sw_obj = NULL;
120 uint64_t ena;
121 proc_t *p = curproc;
122 int err = 0;
123
124 if ((ereport = fm_nvlist_create(NULL)) == NULL)
125 return;
126 if ((fmri = fm_nvlist_create(NULL)) == NULL)
127 goto out;
128 if ((sw_obj = fm_nvlist_create(NULL)) == NULL)
129 goto out;
130 ena = fm_ena_generate(0, FM_ENA_FMT1);
131
132 err |= nvlist_add_uint8(fmri, FM_VERSION, FM_SW_SCHEME_VERSION);
133 err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);
134 err |= nvlist_add_string(sw_obj, FM_FMRI_SW_OBJ_PATH, path);
135 err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_OBJ, sw_obj);
136
137 if (err != 0)
138 goto out;
139
140 fm_ereport_set(ereport, FM_EREPORT_VERSION, CORE_ERROR_CLASS,
141 ena, fmri, NULL);
142
143 fm_payload_set(ereport,
144 FM_EREPORT_PAYLOAD_CORE_COMMAND, DATA_TYPE_STRING,
145 p->p_exec->v_path ? p->p_exec->v_path : p->p_user.u_comm,
146 FM_EREPORT_PAYLOAD_CORE_PSARGS, DATA_TYPE_STRING,
147 p->p_user.u_psargs,
148 FM_EREPORT_PAYLOAD_CORE_SIGNAL, DATA_TYPE_INT32, sig,
149 FM_EREPORT_PAYLOAD_CORE_PATH, DATA_TYPE_STRING, path,
150 NULL);
151
152 fm_ereport_post(ereport, EVCH_SLEEP);
153
154 out:
155 fm_nvlist_destroy(sw_obj, FM_NVA_FREE);
156 fm_nvlist_destroy(ereport, FM_NVA_FREE);
157 fm_nvlist_destroy(fmri, FM_NVA_FREE);
158 }
159
160 /*
161 * Private version of vn_remove().
162 * Refuse to unlink a directory or an unwritable file.
163 * Also allow the process to access files normally inaccessible due to
164 * chroot(2) or Zone limitations.
165 */
166 static int
167 remove_core_file(char *fp, enum core_types core_type)
168 {
169 vnode_t *vp = NULL; /* entry vnode */
170 vnode_t *dvp; /* ptr to parent dir vnode */
171 vfs_t *dvfsp;
172 int error;
173 int in_crit = 0;
174 pathname_t pn; /* name of entry */
175 vnode_t *startvp, *rootvp;
176
177 if ((error = pn_get(fp, UIO_SYSSPACE, &pn)) != 0)
178 return (error);
179 /*
180 * Determine what rootvp to use.
800 if (my_cg->core_options & CC_GLOBAL_PATH)
801 error2 = dump_one_core(sig, rlimit, CORE_ZONE, my_cg,
802 &fp_global);
803 if (global_cg != my_cg && (global_cg->core_options & CC_GLOBAL_PATH))
804 error3 = dump_one_core(sig, rlimit, CORE_GLOBAL, global_cg,
805 &fp_zone);
806
807 /*
808 * Restore the signal hold mask.
809 */
810 mutex_enter(&p->p_lock);
811 curthread->t_hold = sigmask;
812 mutex_exit(&p->p_lock);
813
814 if (!ext && p->p_ct_process != NULL)
815 contract_process_core(p->p_ct_process, p, sig,
816 error1 == 0 ? fp_process : NULL,
817 error2 == 0 ? fp_global : NULL,
818 error3 == 0 ? fp_zone : NULL);
819
820 /*
821 * FMA ereport is currently generated only for global zone cores
822 * with global path.
823 */
824 if (error2 == 0 && global_cg == my_cg)
825 gen_ereport(fp_global, sig);
826
827 if (fp_process != NULL)
828 kmem_free(fp_process, MAXPATHLEN);
829 if (fp_global != NULL)
830 kmem_free(fp_global, MAXPATHLEN);
831 if (fp_zone != NULL)
832 kmem_free(fp_zone, MAXPATHLEN);
833
834 /*
835 * Return non-zero if no core file was created.
836 */
837 return (error1 != 0 && error2 != 0 && error3 != 0);
838 }
839
840 /*
841 * Maximum chunk size for dumping core files,
842 * size in pages, patchable in /etc/system
843 */
844 uint_t core_chunk = 32;
845
846 /*
|