Print this page
OS-4119 lxbrand panic when running native perl inside lx zone
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/exec/aout/aout.c
+++ new/usr/src/uts/common/exec/aout/aout.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
25 + * Copyright 2015, Joyent, Inc.
25 26 */
26 27
27 28 #include <sys/types.h>
28 29 #include <sys/param.h>
29 30 #include <sys/systm.h>
30 31 #include <sys/fpu/fpusystm.h>
31 32 #include <sys/sysmacros.h>
32 33 #include <sys/signal.h>
33 34 #include <sys/cred.h>
34 35 #include <sys/user.h>
35 36 #include <sys/errno.h>
36 37 #include <sys/vnode.h>
37 38 #include <sys/mman.h>
38 39 #include <sys/kmem.h>
39 40 #include <sys/proc.h>
40 41 #include <sys/pathname.h>
41 42 #include <sys/cmn_err.h>
42 43 #include <sys/debug.h>
43 44 #include <sys/exec.h>
44 45 #include <sys/exechdr.h>
45 46 #include <sys/auxv.h>
46 47 #include <sys/core.h>
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
47 48 #include <sys/vmparam.h>
48 49 #include <sys/archsystm.h>
49 50 #include <sys/fs/swapnode.h>
50 51 #include <sys/modctl.h>
51 52 #include <vm/anon.h>
52 53 #include <vm/as.h>
53 54 #include <vm/seg.h>
54 55
55 56 static int aoutexec(vnode_t *vp, execa_t *uap, uarg_t *args,
56 57 intpdata_t *idatap, int level, long *execsz, int setid,
57 - caddr_t exec_file, cred_t *cred, int brand_action);
58 + caddr_t exec_file, cred_t *cred, int *brand_action);
58 59 static int get_aout_head(struct vnode **vpp, struct exdata *edp, long *execsz,
59 60 int *isdyn);
60 61 static int aoutcore(vnode_t *vp, proc_t *pp, cred_t *credp,
61 62 rlim64_t rlimit, int sig, core_content_t content);
62 63 extern int elf32exec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
63 64 long *, int, caddr_t, cred_t *, int);
64 65 extern int elf32core(vnode_t *, proc_t *, cred_t *, rlim64_t, int,
65 66 core_content_t);
66 67
67 68 static struct execsw nesw = {
68 69 aout_nmagicstr,
69 70 2,
70 71 2,
71 72 aoutexec,
72 73 aoutcore
73 74 };
74 75
75 76 static struct execsw zesw = {
76 77 aout_zmagicstr,
77 78 2,
78 79 2,
79 80 aoutexec,
80 81 aoutcore
81 82 };
82 83
83 84 static struct execsw oesw = {
84 85 aout_omagicstr,
85 86 2,
86 87 2,
87 88 aoutexec,
88 89 aoutcore
89 90 };
90 91
91 92 /*
92 93 * Module linkage information for the kernel.
93 94 */
94 95 static struct modlexec nexec = {
95 96 &mod_execops, "exec for NMAGIC", &nesw
96 97 };
97 98
98 99 static struct modlexec zexec = {
99 100 &mod_execops, "exec for ZMAGIC", &zesw
100 101 };
101 102
102 103 static struct modlexec oexec = {
103 104 &mod_execops, "exec for OMAGIC", &oesw
104 105 };
105 106
106 107 static struct modlinkage modlinkage = {
107 108 MODREV_1, &nexec, &zexec, &oexec, NULL
108 109 };
109 110
110 111 int
111 112 _init(void)
112 113 {
113 114 return (mod_install(&modlinkage));
114 115 }
115 116
116 117 int
117 118 _fini(void)
118 119 {
119 120 return (mod_remove(&modlinkage));
120 121 }
121 122
122 123 int
|
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
123 124 _info(struct modinfo *modinfop)
124 125 {
125 126 return (mod_info(&modlinkage, modinfop));
126 127 }
127 128
128 129
129 130 /*ARGSUSED*/
130 131 static int
131 132 aoutexec(vnode_t *vp, struct execa *uap, struct uarg *args,
132 133 struct intpdata *idatap, int level, long *execsz, int setid,
133 - caddr_t exec_file, cred_t *cred, int brand_action)
134 + caddr_t exec_file, cred_t *cred, int *brand_action)
134 135 {
135 136 auxv32_t auxflags_auxv32;
136 137 int error;
137 138 struct exdata edp, edpout;
138 139 struct execenv exenv;
139 140 proc_t *pp = ttoproc(curthread);
140 141 struct vnode *nvp;
141 142 int pagetext, pagedata;
142 143 int dataprot = PROT_ALL;
143 144 int textprot = PROT_ALL & ~PROT_WRITE;
144 145 int isdyn;
145 146
146 147
147 148 args->to_model = DATAMODEL_ILP32;
148 149 *execsz = btopr(SINCR) + btopr(SSIZE) + btopr(NCARGS32-1);
149 150
150 151 /*
151 152 * Read in and validate the file header.
152 153 */
153 154 if (error = get_aout_head(&vp, &edp, execsz, &isdyn))
154 155 return (error);
155 156
156 157 if (error = chkaout(&edp))
157 158 return (error);
158 159
159 160 /*
160 161 * Take a quick look to see if it looks like we will have
161 162 * enough swap space for the program to get started. This
162 163 * is not a guarantee that we will succeed, but it is definitely
163 164 * better than finding this out after we are committed to the
164 165 * new memory image. Maybe what is needed is a way to "prereserve"
165 166 * swap space for some segment mappings here.
166 167 *
167 168 * But with shared libraries the process can make it through
168 169 * the exec only to have ld.so fail to get the program going
169 170 * because its mmap's will not be able to succeed if the system
170 171 * is running low on swap space. In fact this is a far more
171 172 * common failure mode, but we cannot do much about this here
172 173 * other than add some slop to our anonymous memory resources
173 174 * requirements estimate based on some guess since we cannot know
174 175 * what else the program will really need to get to a useful state.
175 176 *
176 177 * XXX - The stack size (clrnd(SSIZE + btopr(nargc))) should also
177 178 * be used when checking for swap space. This requires some work
178 179 * since nargc is actually determined in exec_args() which is done
179 180 * after this check and hence we punt for now.
180 181 *
181 182 * nargc = SA(nc + (na + 4) * NBPW) + sizeof (struct rwindow);
182 183 */
183 184 if (CURRENT_TOTAL_AVAILABLE_SWAP < btopr(edp.ux_dsize) + btopr(SSIZE))
184 185 return (ENOMEM);
185 186
186 187 /*
187 188 * Load the trap 0 interpreter.
188 189 */
189 190 if (error = lookupname("/usr/4lib/sbcp", UIO_SYSSPACE, FOLLOW,
190 191 NULLVPP, &nvp)) {
191 192 goto done;
192 193 }
193 194 if (error = elf32exec(nvp, uap, args, idatap, level, execsz,
194 195 setid, exec_file, cred, brand_action)) {
195 196 VN_RELE(nvp);
196 197 return (error);
197 198 }
198 199 VN_RELE(nvp);
199 200
200 201 /*
201 202 * Determine the a.out's characteristics.
202 203 */
203 204 getexinfo(&edp, &edpout, &pagetext, &pagedata);
204 205
205 206 /*
206 207 * Load the a.out's text and data.
207 208 */
208 209 if (error = execmap(edp.vp, edp.ux_txtorg, edp.ux_tsize,
209 210 (size_t)0, edp.ux_toffset, textprot, pagetext, 0))
210 211 goto done;
211 212 if (error = execmap(edp.vp, edp.ux_datorg, edp.ux_dsize,
212 213 edp.ux_bsize, edp.ux_doffset, dataprot, pagedata, 0))
213 214 goto done;
214 215
215 216 exenv.ex_bssbase = (caddr_t)edp.ux_datorg;
216 217 exenv.ex_brkbase = (caddr_t)edp.ux_datorg;
217 218 exenv.ex_brksize = edp.ux_dsize + edp.ux_bsize;
218 219 exenv.ex_magic = edp.ux_mag;
219 220 exenv.ex_vp = edp.vp;
220 221 setexecenv(&exenv);
221 222
222 223 /*
223 224 * It's time to manipulate the process aux vectors.
224 225 * We need to update the AT_SUN_AUXFLAGS aux vector to set
225 226 * the AF_SUN_NOPLM flag.
226 227 */
227 228 if (copyin(args->auxp_auxflags, &auxflags_auxv32,
228 229 sizeof (auxflags_auxv32)) != 0)
229 230 return (EFAULT);
230 231
231 232 ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS);
232 233 auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM;
233 234 if (copyout(&auxflags_auxv32, args->auxp_auxflags,
234 235 sizeof (auxflags_auxv32)) != 0)
235 236 return (EFAULT);
236 237
237 238 done:
238 239 if (error != 0)
239 240 psignal(pp, SIGKILL);
240 241 else {
241 242 /*
242 243 * Ensure that the max fds do not exceed 256 (this is
243 244 * applicable to 4.x binaries, which is why we only
244 245 * do it on a.out files).
245 246 */
246 247 struct rlimit64 fdno_rlim;
247 248 rctl_alloc_gp_t *gp = rctl_rlimit_set_prealloc(1);
248 249
249 250 mutex_enter(&curproc->p_lock);
250 251 (void) rctl_rlimit_get(rctlproc_legacy[RLIMIT_NOFILE], curproc,
251 252 &fdno_rlim);
252 253 if (fdno_rlim.rlim_cur > 256) {
253 254 fdno_rlim.rlim_cur = fdno_rlim.rlim_max = 256;
254 255 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE],
255 256 curproc, &fdno_rlim, gp,
256 257 rctlproc_flags[RLIMIT_NOFILE],
257 258 rctlproc_signals[RLIMIT_NOFILE], CRED());
258 259 } else if (fdno_rlim.rlim_max > 256) {
259 260 fdno_rlim.rlim_max = 256;
260 261 (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE],
261 262 curproc, &fdno_rlim, gp,
262 263 rctlproc_flags[RLIMIT_NOFILE],
263 264 rctlproc_signals[RLIMIT_NOFILE], CRED());
264 265 }
265 266 mutex_exit(&curproc->p_lock);
266 267
267 268 rctl_prealloc_destroy(gp);
268 269 }
269 270
270 271 return (error);
271 272 }
272 273
273 274 /*
274 275 * Read in and validate the file header.
275 276 */
276 277 static int
277 278 get_aout_head(struct vnode **vpp, struct exdata *edp, long *execsz, int *isdyn)
278 279 {
279 280 struct vnode *vp = *vpp;
280 281 struct exec filhdr;
281 282 int error;
282 283 ssize_t resid;
283 284 rlim64_t limit;
284 285 rlim64_t roundlimit;
285 286
286 287 if (error = vn_rdwr(UIO_READ, vp, (caddr_t)&filhdr,
287 288 (ssize_t)sizeof (filhdr), (offset_t)0, UIO_SYSSPACE, 0,
288 289 (rlim64_t)0, CRED(), &resid))
289 290 return (error);
290 291
291 292 if (resid != 0)
292 293 return (ENOEXEC);
293 294
294 295 switch (filhdr.a_magic) {
295 296 case OMAGIC:
296 297 filhdr.a_data += filhdr.a_text;
297 298 filhdr.a_text = 0;
298 299 break;
299 300 case ZMAGIC:
300 301 case NMAGIC:
301 302 break;
302 303 default:
303 304 return (ENOEXEC);
304 305 }
305 306
306 307 /*
307 308 * Check total memory requirements (in pages) for a new process
308 309 * against the available memory or upper limit of memory allowed.
309 310 *
310 311 * For the 64-bit kernel, the limit can be set large enough so that
311 312 * rounding it up to a page can overflow, so we check for btopr()
312 313 * overflowing here by comparing it with the unrounded limit in pages.
313 314 */
314 315 *execsz += btopr(filhdr.a_text + filhdr.a_data);
315 316 limit = btop(curproc->p_vmem_ctl);
316 317 roundlimit = btopr(curproc->p_vmem_ctl);
317 318 if ((roundlimit > limit && *execsz > roundlimit) ||
318 319 (roundlimit < limit && *execsz > limit)) {
319 320 mutex_enter(&curproc->p_lock);
320 321 (void) rctl_action(rctlproc_legacy[RLIMIT_VMEM],
321 322 curproc->p_rctls, curproc, RCA_SAFE);
322 323 mutex_exit(&curproc->p_lock);
323 324 return (ENOMEM);
324 325 }
325 326
326 327 edp->ux_mach = filhdr.a_machtype;
327 328 edp->ux_tsize = filhdr.a_text;
328 329 edp->ux_dsize = filhdr.a_data;
329 330 edp->ux_bsize = filhdr.a_bss;
330 331 edp->ux_mag = filhdr.a_magic;
331 332 edp->ux_toffset = gettfile(&filhdr);
332 333 edp->ux_doffset = getdfile(&filhdr);
333 334 edp->ux_txtorg = gettmem(&filhdr);
334 335 edp->ux_datorg = getdmem(&filhdr);
335 336 edp->ux_entloc = (caddr_t)(uintptr_t)filhdr.a_entry;
336 337 edp->vp = vp;
337 338 *isdyn = filhdr.a_dynamic;
338 339
339 340 return (0);
340 341 }
341 342
342 343 static int
343 344 aoutcore(vnode_t *vp, proc_t *pp, struct cred *credp, rlim64_t rlimit, int sig,
344 345 core_content_t content)
345 346 {
346 347 return (elf32core(vp, pp, credp, rlimit, sig, content));
347 348 }
|
↓ open down ↓ |
204 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX