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