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