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