10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2712Snn35248 * Common Development and Distribution License (the "License"). 6*2712Snn35248 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2712Snn35248 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/param.h> 300Sstevel@tonic-gate #include <sys/systm.h> 310Sstevel@tonic-gate #include <sys/fpu/fpusystm.h> 320Sstevel@tonic-gate #include <sys/sysmacros.h> 330Sstevel@tonic-gate #include <sys/signal.h> 340Sstevel@tonic-gate #include <sys/cred.h> 350Sstevel@tonic-gate #include <sys/user.h> 360Sstevel@tonic-gate #include <sys/errno.h> 370Sstevel@tonic-gate #include <sys/vnode.h> 380Sstevel@tonic-gate #include <sys/mman.h> 390Sstevel@tonic-gate #include <sys/kmem.h> 400Sstevel@tonic-gate #include <sys/proc.h> 410Sstevel@tonic-gate #include <sys/pathname.h> 420Sstevel@tonic-gate #include <sys/cmn_err.h> 430Sstevel@tonic-gate #include <sys/debug.h> 440Sstevel@tonic-gate #include <sys/exec.h> 450Sstevel@tonic-gate #include <sys/exechdr.h> 460Sstevel@tonic-gate #include <sys/auxv.h> 470Sstevel@tonic-gate #include <sys/core.h> 480Sstevel@tonic-gate #include <sys/vmparam.h> 490Sstevel@tonic-gate #include <sys/archsystm.h> 500Sstevel@tonic-gate #include <sys/fs/swapnode.h> 510Sstevel@tonic-gate #include <sys/modctl.h> 520Sstevel@tonic-gate #include <vm/anon.h> 530Sstevel@tonic-gate #include <vm/as.h> 540Sstevel@tonic-gate #include <vm/seg.h> 550Sstevel@tonic-gate 560Sstevel@tonic-gate static int aoutexec(vnode_t *vp, execa_t *uap, uarg_t *args, 570Sstevel@tonic-gate intpdata_t *idatap, int level, long *execsz, int setid, 58*2712Snn35248 caddr_t exec_file, cred_t *cred, int brand_action); 590Sstevel@tonic-gate static int get_aout_head(struct vnode **vpp, struct exdata *edp, long *execsz, 600Sstevel@tonic-gate int *isdyn); 610Sstevel@tonic-gate static int aoutcore(vnode_t *vp, proc_t *pp, cred_t *credp, 620Sstevel@tonic-gate rlim64_t rlimit, int sig, core_content_t content); 630Sstevel@tonic-gate #ifdef _LP64 640Sstevel@tonic-gate extern int elf32exec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int, 65*2712Snn35248 long *, int, caddr_t, cred_t *, int); 660Sstevel@tonic-gate extern int elf32core(vnode_t *, proc_t *, cred_t *, rlim64_t, int, 670Sstevel@tonic-gate core_content_t); 680Sstevel@tonic-gate #else /* _LP64 */ 690Sstevel@tonic-gate extern int elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int, 70*2712Snn35248 long *, int, caddr_t, cred_t *, int); 710Sstevel@tonic-gate extern int elfcore(vnode_t *, proc_t *, cred_t *, rlim64_t, int, 720Sstevel@tonic-gate core_content_t); 730Sstevel@tonic-gate #endif /* _LP64 */ 740Sstevel@tonic-gate 750Sstevel@tonic-gate char _depends_on[] = "exec/elfexec"; 760Sstevel@tonic-gate 770Sstevel@tonic-gate static struct execsw nesw = { 780Sstevel@tonic-gate aout_nmagicstr, 790Sstevel@tonic-gate 2, 800Sstevel@tonic-gate 2, 810Sstevel@tonic-gate aoutexec, 820Sstevel@tonic-gate aoutcore 830Sstevel@tonic-gate }; 840Sstevel@tonic-gate 850Sstevel@tonic-gate static struct execsw zesw = { 860Sstevel@tonic-gate aout_zmagicstr, 870Sstevel@tonic-gate 2, 880Sstevel@tonic-gate 2, 890Sstevel@tonic-gate aoutexec, 900Sstevel@tonic-gate aoutcore 910Sstevel@tonic-gate }; 920Sstevel@tonic-gate 930Sstevel@tonic-gate static struct execsw oesw = { 940Sstevel@tonic-gate aout_omagicstr, 950Sstevel@tonic-gate 2, 960Sstevel@tonic-gate 2, 970Sstevel@tonic-gate aoutexec, 980Sstevel@tonic-gate aoutcore 990Sstevel@tonic-gate }; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /* 1020Sstevel@tonic-gate * Module linkage information for the kernel. 1030Sstevel@tonic-gate */ 1040Sstevel@tonic-gate static struct modlexec nexec = { 1050Sstevel@tonic-gate &mod_execops, "exec for NMAGIC", &nesw 1060Sstevel@tonic-gate }; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate static struct modlexec zexec = { 1090Sstevel@tonic-gate &mod_execops, "exec for ZMAGIC", &zesw 1100Sstevel@tonic-gate }; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate static struct modlexec oexec = { 1130Sstevel@tonic-gate &mod_execops, "exec for OMAGIC", &oesw 1140Sstevel@tonic-gate }; 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate static struct modlinkage modlinkage = { 1170Sstevel@tonic-gate MODREV_1, &nexec, &zexec, &oexec, NULL 1180Sstevel@tonic-gate }; 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate int 1210Sstevel@tonic-gate _init(void) 1220Sstevel@tonic-gate { 1230Sstevel@tonic-gate return (mod_install(&modlinkage)); 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate int 1270Sstevel@tonic-gate _fini(void) 1280Sstevel@tonic-gate { 1290Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate int 1330Sstevel@tonic-gate _info(struct modinfo *modinfop) 1340Sstevel@tonic-gate { 1350Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /*ARGSUSED*/ 1400Sstevel@tonic-gate static int 1410Sstevel@tonic-gate aoutexec(vnode_t *vp, struct execa *uap, struct uarg *args, 1420Sstevel@tonic-gate struct intpdata *idatap, int level, long *execsz, int setid, 143*2712Snn35248 caddr_t exec_file, cred_t *cred, int brand_action) 1440Sstevel@tonic-gate { 1450Sstevel@tonic-gate int error; 1460Sstevel@tonic-gate struct exdata edp, edpout; 1470Sstevel@tonic-gate struct execenv exenv; 1480Sstevel@tonic-gate proc_t *pp = ttoproc(curthread); 1490Sstevel@tonic-gate struct vnode *nvp; 1500Sstevel@tonic-gate int pagetext, pagedata; 1510Sstevel@tonic-gate int dataprot = PROT_ALL; 1520Sstevel@tonic-gate int textprot = PROT_ALL & ~PROT_WRITE; 1530Sstevel@tonic-gate int isdyn; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate args->to_model = DATAMODEL_ILP32; 1560Sstevel@tonic-gate *execsz = btopr(SINCR) + btopr(SSIZE) + btopr(NCARGS32-1); 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * Read in and validate the file header. 1600Sstevel@tonic-gate */ 1610Sstevel@tonic-gate if (error = get_aout_head(&vp, &edp, execsz, &isdyn)) 1620Sstevel@tonic-gate return (error); 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate if (error = chkaout(&edp)) 1650Sstevel@tonic-gate return (error); 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /* 1680Sstevel@tonic-gate * Take a quick look to see if it looks like we will have 1690Sstevel@tonic-gate * enough swap space for the program to get started. This 1700Sstevel@tonic-gate * is not a guarantee that we will succeed, but it is definitely 1710Sstevel@tonic-gate * better than finding this out after we are committed to the 1720Sstevel@tonic-gate * new memory image. Maybe what is needed is a way to "prereserve" 1730Sstevel@tonic-gate * swap space for some segment mappings here. 1740Sstevel@tonic-gate * 1750Sstevel@tonic-gate * But with shared libraries the process can make it through 1760Sstevel@tonic-gate * the exec only to have ld.so fail to get the program going 1770Sstevel@tonic-gate * because its mmap's will not be able to succeed if the system 1780Sstevel@tonic-gate * is running low on swap space. In fact this is a far more 1790Sstevel@tonic-gate * common failure mode, but we cannot do much about this here 1800Sstevel@tonic-gate * other than add some slop to our anonymous memory resources 1810Sstevel@tonic-gate * requirements estimate based on some guess since we cannot know 1820Sstevel@tonic-gate * what else the program will really need to get to a useful state. 1830Sstevel@tonic-gate * 1840Sstevel@tonic-gate * XXX - The stack size (clrnd(SSIZE + btopr(nargc))) should also 1850Sstevel@tonic-gate * be used when checking for swap space. This requires some work 1860Sstevel@tonic-gate * since nargc is actually determined in exec_args() which is done 1870Sstevel@tonic-gate * after this check and hence we punt for now. 1880Sstevel@tonic-gate * 1890Sstevel@tonic-gate * nargc = SA(nc + (na + 4) * NBPW) + sizeof (struct rwindow); 1900Sstevel@tonic-gate */ 1910Sstevel@tonic-gate if (CURRENT_TOTAL_AVAILABLE_SWAP < btopr(edp.ux_dsize) + btopr(SSIZE)) 1920Sstevel@tonic-gate return (ENOMEM); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* 1950Sstevel@tonic-gate * Load the trap 0 interpreter. 1960Sstevel@tonic-gate */ 1970Sstevel@tonic-gate if (error = lookupname("/usr/4lib/sbcp", UIO_SYSSPACE, FOLLOW, 1980Sstevel@tonic-gate NULLVPP, &nvp)) { 1990Sstevel@tonic-gate goto done; 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate #ifdef _LP64 2020Sstevel@tonic-gate if (error = elf32exec(nvp, uap, args, idatap, level, execsz, 203*2712Snn35248 setid, exec_file, cred, brand_action)) 2040Sstevel@tonic-gate #else /* _LP64 */ 2050Sstevel@tonic-gate if (error = elfexec(nvp, uap, args, idatap, level, execsz, 206*2712Snn35248 setid, exec_file, cred, brand_action)) 2070Sstevel@tonic-gate #endif /* _LP64 */ 2080Sstevel@tonic-gate { 2090Sstevel@tonic-gate VN_RELE(nvp); 2100Sstevel@tonic-gate return (error); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate VN_RELE(nvp); 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* 2150Sstevel@tonic-gate * Determine the a.out's characteristics. 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate getexinfo(&edp, &edpout, &pagetext, &pagedata); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * Load the a.out's text and data. 2210Sstevel@tonic-gate */ 2220Sstevel@tonic-gate if (error = execmap(edp.vp, edp.ux_txtorg, edp.ux_tsize, 2230Sstevel@tonic-gate (size_t)0, edp.ux_toffset, textprot, pagetext, 0)) 2240Sstevel@tonic-gate goto done; 2250Sstevel@tonic-gate if (error = execmap(edp.vp, edp.ux_datorg, edp.ux_dsize, 2260Sstevel@tonic-gate edp.ux_bsize, edp.ux_doffset, dataprot, pagedata, 0)) 2270Sstevel@tonic-gate goto done; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate exenv.ex_brkbase = (caddr_t)edp.ux_datorg; 2300Sstevel@tonic-gate exenv.ex_brksize = edp.ux_dsize + edp.ux_bsize; 2310Sstevel@tonic-gate exenv.ex_magic = edp.ux_mag; 2320Sstevel@tonic-gate exenv.ex_vp = edp.vp; 2330Sstevel@tonic-gate setexecenv(&exenv); 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate done: 2360Sstevel@tonic-gate if (error != 0) 2370Sstevel@tonic-gate psignal(pp, SIGKILL); 2380Sstevel@tonic-gate else { 2390Sstevel@tonic-gate /* 2400Sstevel@tonic-gate * Ensure that the max fds do not exceed 256 (this is 2410Sstevel@tonic-gate * applicable to 4.x binaries, which is why we only 2420Sstevel@tonic-gate * do it on a.out files). 2430Sstevel@tonic-gate */ 2440Sstevel@tonic-gate struct rlimit64 fdno_rlim; 2450Sstevel@tonic-gate rctl_alloc_gp_t *gp = rctl_rlimit_set_prealloc(1); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate mutex_enter(&curproc->p_lock); 2480Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[RLIMIT_NOFILE], curproc, 2490Sstevel@tonic-gate &fdno_rlim); 2500Sstevel@tonic-gate if (fdno_rlim.rlim_cur > 256) { 2510Sstevel@tonic-gate fdno_rlim.rlim_cur = fdno_rlim.rlim_max = 256; 2520Sstevel@tonic-gate (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE], 2530Sstevel@tonic-gate curproc, &fdno_rlim, gp, 2540Sstevel@tonic-gate rctlproc_flags[RLIMIT_NOFILE], 2550Sstevel@tonic-gate rctlproc_signals[RLIMIT_NOFILE], CRED()); 2560Sstevel@tonic-gate } else if (fdno_rlim.rlim_max > 256) { 2570Sstevel@tonic-gate fdno_rlim.rlim_max = 256; 2580Sstevel@tonic-gate (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE], 2590Sstevel@tonic-gate curproc, &fdno_rlim, gp, 2600Sstevel@tonic-gate rctlproc_flags[RLIMIT_NOFILE], 2610Sstevel@tonic-gate rctlproc_signals[RLIMIT_NOFILE], CRED()); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate rctl_prealloc_destroy(gp); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate return (error); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* 2720Sstevel@tonic-gate * Read in and validate the file header. 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate static int 2750Sstevel@tonic-gate get_aout_head(struct vnode **vpp, struct exdata *edp, long *execsz, int *isdyn) 2760Sstevel@tonic-gate { 2770Sstevel@tonic-gate struct vnode *vp = *vpp; 2780Sstevel@tonic-gate struct exec filhdr; 2790Sstevel@tonic-gate int error; 2800Sstevel@tonic-gate ssize_t resid; 2810Sstevel@tonic-gate rlim64_t limit; 2820Sstevel@tonic-gate rlim64_t roundlimit; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate if (error = vn_rdwr(UIO_READ, vp, (caddr_t)&filhdr, 2850Sstevel@tonic-gate (ssize_t)sizeof (filhdr), (offset_t)0, UIO_SYSSPACE, 0, 2860Sstevel@tonic-gate (rlim64_t)0, CRED(), &resid)) 2870Sstevel@tonic-gate return (error); 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate if (resid != 0) 2900Sstevel@tonic-gate return (ENOEXEC); 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate switch (filhdr.a_magic) { 2930Sstevel@tonic-gate case OMAGIC: 2940Sstevel@tonic-gate filhdr.a_data += filhdr.a_text; 2950Sstevel@tonic-gate filhdr.a_text = 0; 2960Sstevel@tonic-gate break; 2970Sstevel@tonic-gate case ZMAGIC: 2980Sstevel@tonic-gate case NMAGIC: 2990Sstevel@tonic-gate break; 3000Sstevel@tonic-gate default: 3010Sstevel@tonic-gate return (ENOEXEC); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate /* 3050Sstevel@tonic-gate * Check total memory requirements (in pages) for a new process 3060Sstevel@tonic-gate * against the available memory or upper limit of memory allowed. 3070Sstevel@tonic-gate * 3080Sstevel@tonic-gate * For the 64-bit kernel, the limit can be set large enough so that 3090Sstevel@tonic-gate * rounding it up to a page can overflow, so we check for btopr() 3100Sstevel@tonic-gate * overflowing here by comparing it with the unrounded limit in pages. 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate *execsz += btopr(filhdr.a_text + filhdr.a_data); 3130Sstevel@tonic-gate limit = btop(curproc->p_vmem_ctl); 3140Sstevel@tonic-gate roundlimit = btopr(curproc->p_vmem_ctl); 3150Sstevel@tonic-gate if ((roundlimit > limit && *execsz > roundlimit) || 3160Sstevel@tonic-gate (roundlimit < limit && *execsz > limit)) { 3170Sstevel@tonic-gate mutex_enter(&curproc->p_lock); 3180Sstevel@tonic-gate (void) rctl_action(rctlproc_legacy[RLIMIT_VMEM], 3190Sstevel@tonic-gate curproc->p_rctls, curproc, RCA_SAFE); 3200Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 3210Sstevel@tonic-gate return (ENOMEM); 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate edp->ux_mach = filhdr.a_machtype; 3250Sstevel@tonic-gate edp->ux_tsize = filhdr.a_text; 3260Sstevel@tonic-gate edp->ux_dsize = filhdr.a_data; 3270Sstevel@tonic-gate edp->ux_bsize = filhdr.a_bss; 3280Sstevel@tonic-gate edp->ux_mag = filhdr.a_magic; 3290Sstevel@tonic-gate edp->ux_toffset = gettfile(&filhdr); 3300Sstevel@tonic-gate edp->ux_doffset = getdfile(&filhdr); 3310Sstevel@tonic-gate edp->ux_txtorg = gettmem(&filhdr); 3320Sstevel@tonic-gate edp->ux_datorg = getdmem(&filhdr); 333712Smuffin edp->ux_entloc = (caddr_t)(uintptr_t)filhdr.a_entry; 3340Sstevel@tonic-gate edp->vp = vp; 3350Sstevel@tonic-gate *isdyn = filhdr.a_dynamic; 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate return (0); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate static int 3410Sstevel@tonic-gate aoutcore(vnode_t *vp, proc_t *pp, struct cred *credp, rlim64_t rlimit, int sig, 3420Sstevel@tonic-gate core_content_t content) 3430Sstevel@tonic-gate { 3440Sstevel@tonic-gate #ifdef _LP64 3450Sstevel@tonic-gate return (elf32core(vp, pp, credp, rlimit, sig, content)); 3460Sstevel@tonic-gate #else 3470Sstevel@tonic-gate return (elfcore(vp, pp, credp, rlimit, sig, content)); 3480Sstevel@tonic-gate #endif 3490Sstevel@tonic-gate } 350