svr4_sysvec.c revision 112470
149267Snewton/* 249267Snewton * Copyright (c) 1998 Mark Newton 349267Snewton * All rights reserved. 449267Snewton * 549267Snewton * Redistribution and use in source and binary forms, with or without 649267Snewton * modification, are permitted provided that the following conditions 749267Snewton * are met: 849267Snewton * 1. Redistributions of source code must retain the above copyright 949267Snewton * notice, this list of conditions and the following disclaimer. 1049267Snewton * 2. Redistributions in binary form must reproduce the above copyright 1149267Snewton * notice, this list of conditions and the following disclaimer in the 1249267Snewton * documentation and/or other materials provided with the distribution. 1349267Snewton * 3. All advertising materials mentioning features or use of this software 1449267Snewton * must display the following acknowledgement: 1549267Snewton * This product includes software developed by Christos Zoulas. 1649267Snewton * 4. The name of the author may not be used to endorse or promote products 1749267Snewton * derived from this software without specific prior written permission. 1849267Snewton * 1949267Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2049267Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2149267Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2249267Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2349267Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2449267Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2549267Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2649267Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2749267Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2849267Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2949267Snewton * 3050477Speter * $FreeBSD: head/sys/compat/svr4/svr4_sysvec.c 112470 2003-03-21 19:49:34Z jhb $ 3149267Snewton */ 3249267Snewton 3343412Snewton/* XXX we use functions that might not exist. */ 3443412Snewton#include "opt_compat.h" 3543412Snewton 3643412Snewton#ifndef COMPAT_43 3743412Snewton#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" 3843412Snewton#endif 3943412Snewton 4043412Snewton#include <sys/param.h> 4148503Sgreen#include <sys/systm.h> 4243412Snewton#include <sys/proc.h> 4343412Snewton#include <sys/sysent.h> 4443412Snewton#include <sys/imgact.h> 4543412Snewton#include <sys/imgact_elf.h> 4643412Snewton#include <sys/socket.h> 4794455Sjhb#include <sys/lock.h> 4843412Snewton#include <sys/malloc.h> 4994455Sjhb#include <sys/mutex.h> 5043412Snewton#include <sys/namei.h> 5143412Snewton#include <sys/vnode.h> 5243412Snewton#include <sys/module.h> 5343412Snewton#include <vm/vm.h> 5443412Snewton#include <sys/exec.h> 5543412Snewton#include <sys/kernel.h> 5643412Snewton#include <machine/cpu.h> 5743412Snewton#include <netinet/in.h> 5843412Snewton 5965302Sobrien#include <compat/svr4/svr4.h> 6065302Sobrien#include <compat/svr4/svr4_types.h> 6165302Sobrien#include <compat/svr4/svr4_syscall.h> 6265302Sobrien#include <compat/svr4/svr4_signal.h> 6365302Sobrien#include <compat/svr4/svr4_sockio.h> 6465302Sobrien#include <compat/svr4/svr4_socket.h> 6565302Sobrien#include <compat/svr4/svr4_errno.h> 6665302Sobrien#include <compat/svr4/svr4_proto.h> 6765302Sobrien#include <compat/svr4/svr4_siginfo.h> 6865302Sobrien#include <compat/svr4/svr4_util.h> 6943412Snewton 7043412Snewtonint bsd_to_svr4_errno[ELAST+1] = { 7143412Snewton 0, 7243412Snewton SVR4_EPERM, 7343412Snewton SVR4_ENOENT, 7443412Snewton SVR4_ESRCH, 7543412Snewton SVR4_EINTR, 7643412Snewton SVR4_EIO, 7743412Snewton SVR4_ENXIO, 7843412Snewton SVR4_E2BIG, 7943412Snewton SVR4_ENOEXEC, 8043412Snewton SVR4_EBADF, 8143412Snewton SVR4_ECHILD, 8243412Snewton SVR4_EDEADLK, 8343412Snewton SVR4_ENOMEM, 8443412Snewton SVR4_EACCES, 8543412Snewton SVR4_EFAULT, 8643412Snewton SVR4_ENOTBLK, 8743412Snewton SVR4_EBUSY, 8843412Snewton SVR4_EEXIST, 8943412Snewton SVR4_EXDEV, 9043412Snewton SVR4_ENODEV, 9143412Snewton SVR4_ENOTDIR, 9243412Snewton SVR4_EISDIR, 9343412Snewton SVR4_EINVAL, 9443412Snewton SVR4_ENFILE, 9543412Snewton SVR4_EMFILE, 9643412Snewton SVR4_ENOTTY, 9743412Snewton SVR4_ETXTBSY, 9843412Snewton SVR4_EFBIG, 9943412Snewton SVR4_ENOSPC, 10043412Snewton SVR4_ESPIPE, 10143412Snewton SVR4_EROFS, 10243412Snewton SVR4_EMLINK, 10343412Snewton SVR4_EPIPE, 10443412Snewton SVR4_EDOM, 10543412Snewton SVR4_ERANGE, 10643412Snewton SVR4_EAGAIN, 10743412Snewton SVR4_EINPROGRESS, 10843412Snewton SVR4_EALREADY, 10943412Snewton SVR4_ENOTSOCK, 11043412Snewton SVR4_EDESTADDRREQ, 11143412Snewton SVR4_EMSGSIZE, 11243412Snewton SVR4_EPROTOTYPE, 11343412Snewton SVR4_ENOPROTOOPT, 11443412Snewton SVR4_EPROTONOSUPPORT, 11543412Snewton SVR4_ESOCKTNOSUPPORT, 11643412Snewton SVR4_EOPNOTSUPP, 11743412Snewton SVR4_EPFNOSUPPORT, 11843412Snewton SVR4_EAFNOSUPPORT, 11943412Snewton SVR4_EADDRINUSE, 12043412Snewton SVR4_EADDRNOTAVAIL, 12143412Snewton SVR4_ENETDOWN, 12243412Snewton SVR4_ENETUNREACH, 12343412Snewton SVR4_ENETRESET, 12443412Snewton SVR4_ECONNABORTED, 12543412Snewton SVR4_ECONNRESET, 12643412Snewton SVR4_ENOBUFS, 12743412Snewton SVR4_EISCONN, 12843412Snewton SVR4_ENOTCONN, 12943412Snewton SVR4_ESHUTDOWN, 13043412Snewton SVR4_ETOOMANYREFS, 13143412Snewton SVR4_ETIMEDOUT, 13243412Snewton SVR4_ECONNREFUSED, 13343412Snewton SVR4_ELOOP, 13443412Snewton SVR4_ENAMETOOLONG, 13543412Snewton SVR4_EHOSTDOWN, 13643412Snewton SVR4_EHOSTUNREACH, 13743412Snewton SVR4_ENOTEMPTY, 13843412Snewton SVR4_EPROCLIM, 13943412Snewton SVR4_EUSERS, 14043412Snewton SVR4_EDQUOT, 14143412Snewton SVR4_ESTALE, 14243412Snewton SVR4_EREMOTE, 14343412Snewton SVR4_EBADRPC, 14443412Snewton SVR4_ERPCMISMATCH, 14543412Snewton SVR4_EPROGUNAVAIL, 14643412Snewton SVR4_EPROGMISMATCH, 14743412Snewton SVR4_EPROCUNAVAIL, 14843412Snewton SVR4_ENOLCK, 14943412Snewton SVR4_ENOSYS, 15043412Snewton SVR4_EFTYPE, 15143412Snewton SVR4_EAUTH, 15243412Snewton SVR4_ENEEDAUTH, 15343412Snewton SVR4_EIDRM, 15443412Snewton SVR4_ENOMSG, 15543412Snewton}; 15643412Snewton 15743412Snewton 15859342Sobrienstatic int svr4_fixup(register_t **stack_base, struct image_params *imgp); 15943412Snewton 16043412Snewtonextern struct sysent svr4_sysent[]; 16143412Snewton#undef szsigcode 16243412Snewton#undef sigcode 16343412Snewton 16443412Snewtonextern int svr4_szsigcode; 16543412Snewtonextern char svr4_sigcode[]; 16643412Snewton 16743412Snewtonstruct sysentvec svr4_sysvec = { 16843412Snewton SVR4_SYS_MAXSYSCALL, 16943412Snewton svr4_sysent, 17043412Snewton 0xff, 17151793Smarcel SVR4_SIGTBLSZ, 17243412Snewton bsd_to_svr4_sig, 17343412Snewton ELAST, /* ELAST */ 17443412Snewton bsd_to_svr4_errno, 175102808Sjake NULL, 17643412Snewton svr4_fixup, 17743412Snewton svr4_sendsig, 17843412Snewton svr4_sigcode, 17943412Snewton &svr4_szsigcode, 18049267Snewton NULL, 18149267Snewton "SVR4", 182100384Speter elf32_coredump, 18368520Smarcel NULL, 184102808Sjake SVR4_MINSIGSTKSZ, 185102808Sjake PAGE_SIZE, 186102808Sjake VM_MIN_ADDRESS, 187102808Sjake VM_MAXUSER_ADDRESS, 188102808Sjake USRSTACK, 189102808Sjake PS_STRINGS, 190102808Sjake VM_PROT_ALL, 191102808Sjake exec_copyout_strings, 192102808Sjake exec_setregs 19343412Snewton}; 19443412Snewton 19543412SnewtonElf32_Brandinfo svr4_brand = { 19699669Srobert ELFOSABI_SYSV, 197100384Speter EM_386, /* XXX only implemented for x86 so far. */ 19872999Sobrien "SVR4", 19959342Sobrien svr4_emul_path, 20043412Snewton "/lib/libc.so.1", 20143412Snewton &svr4_sysvec 20243412Snewton}; 20343412Snewton 20443412Snewtonconst char svr4_emul_path[] = "/compat/svr4"; 20543412Snewton 20643412Snewtonstatic int 20759342Sobriensvr4_fixup(register_t **stack_base, struct image_params *imgp) 20843412Snewton{ 209112470Sjhb Elf32_Auxargs *args; 21059342Sobrien register_t *pos; 21143412Snewton 212112470Sjhb KASSERT(curthread->td_proc == imgp->proc && 213112470Sjhb (curthread->td_proc->p_flag & P_THREADED) == 0, 214112470Sjhb ("unsafe svr4_fixup(), should be curproc")); 215112470Sjhb args = (Elf32_Auxargs *)imgp->auxargs; 21643412Snewton pos = *stack_base + (imgp->argc + imgp->envc + 2); 21743412Snewton 218112470Sjhb if (args->trace) 21943412Snewton AUXARGS_ENTRY(pos, AT_DEBUG, 1); 220112470Sjhb if (args->execfd != -1) 22143412Snewton AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 22243412Snewton AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 22343412Snewton AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 22443412Snewton AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 22543412Snewton AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 22643412Snewton AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 22743412Snewton AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 22843412Snewton AUXARGS_ENTRY(pos, AT_BASE, args->base); 22977183Srwatson AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); 23077183Srwatson AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); 23177183Srwatson AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); 23277183Srwatson AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); 23343412Snewton AUXARGS_ENTRY(pos, AT_NULL, 0); 23443412Snewton 23543412Snewton free(imgp->auxargs, M_TEMP); 23643412Snewton imgp->auxargs = NULL; 23743412Snewton 23843412Snewton (*stack_base)--; 239112470Sjhb **stack_base = (register_t)imgp->argc; 24043412Snewton return 0; 24143412Snewton} 24243412Snewton 24343412Snewton/* 24443412Snewton * Search an alternate path before passing pathname arguments on 24572091Sasmodai * to system calls. Useful for keeping a separate 'emulation tree'. 24643412Snewton * 24743412Snewton * If cflag is set, we check if an attempt can be made to create 24843412Snewton * the named file, i.e. we check if the directory it should 24943412Snewton * be in exists. 25043412Snewton * 25143412Snewton * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. 25243412Snewton */ 25343412Snewtonint 25483366Sjuliansvr4_emul_find(td, sgp, prefix, path, pbuf, cflag) 25583366Sjulian struct thread *td; 25643412Snewton caddr_t *sgp; /* Pointer to stackgap memory */ 25743412Snewton const char *prefix; 25843412Snewton char *path; 25943412Snewton char **pbuf; 26043412Snewton int cflag; 26143412Snewton{ 26243412Snewton struct nameidata nd; 26343412Snewton struct nameidata ndroot; 26443412Snewton struct vattr vat; 26543412Snewton struct vattr vatroot; 26643412Snewton int error; 26743412Snewton char *ptr, *buf, *cp; 26843412Snewton size_t sz, len; 26943412Snewton 270111119Simp buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 27143412Snewton *pbuf = path; 27243412Snewton 27343412Snewton for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 27443412Snewton continue; 27543412Snewton 27643412Snewton sz = MAXPATHLEN - (ptr - buf); 27743412Snewton 27843412Snewton /* 27943412Snewton * If sgp is not given then the path is already in kernel space 28043412Snewton */ 28143412Snewton if (sgp == NULL) 28243412Snewton error = copystr(path, ptr, sz, &len); 28343412Snewton else 28443412Snewton error = copyinstr(path, ptr, sz, &len); 28543412Snewton 28643412Snewton if (error) { 28743412Snewton free(buf, M_TEMP); 28843412Snewton return error; 28943412Snewton } 29043412Snewton 29143412Snewton if (*ptr != '/') { 29243412Snewton free(buf, M_TEMP); 29343412Snewton return EINVAL; 29443412Snewton } 29543412Snewton 29643412Snewton /* 29743412Snewton * We know that there is a / somewhere in this pathname. 29843412Snewton * Search backwards for it, to find the file's parent dir 29943412Snewton * to see if it exists in the alternate tree. If it does, 30043412Snewton * and we want to create a file (cflag is set). We don't 30143412Snewton * need to worry about the root comparison in this case. 30243412Snewton */ 30343412Snewton 30443412Snewton if (cflag) { 30543412Snewton for (cp = &ptr[len] - 1; *cp != '/'; cp--); 30643412Snewton *cp = '\0'; 30743412Snewton 30883366Sjulian NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 30943412Snewton 31043412Snewton if ((error = namei(&nd)) != 0) { 31143412Snewton free(buf, M_TEMP); 31243412Snewton return error; 31343412Snewton } 31454655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 31543412Snewton 31643412Snewton *cp = '/'; 31743412Snewton } 31843412Snewton else { 31983366Sjulian NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 32043412Snewton 32143412Snewton if ((error = namei(&nd)) != 0) { 32243412Snewton free(buf, M_TEMP); 32343412Snewton return error; 32443412Snewton } 32554655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 32643412Snewton 32743412Snewton /* 32843412Snewton * We now compare the vnode of the svr4_root to the one 32943412Snewton * vnode asked. If they resolve to be the same, then we 33043412Snewton * ignore the match so that the real root gets used. 33143412Snewton * This avoids the problem of traversing "../.." to find the 33243412Snewton * root directory and never finding it, because "/" resolves 33343412Snewton * to the emulation root directory. This is expensive :-( 33443412Snewton */ 33543412Snewton NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, 33683366Sjulian td); 33743412Snewton 33843412Snewton if ((error = namei(&ndroot)) != 0) { 33943412Snewton /* Cannot happen! */ 34043412Snewton free(buf, M_TEMP); 34143412Snewton vrele(nd.ni_vp); 34243412Snewton return error; 34343412Snewton } 34454655Seivind NDFREE(&ndroot, NDF_ONLY_PNBUF); 34543412Snewton 34691406Sjhb if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) { 34743412Snewton goto done; 34843412Snewton } 34943412Snewton 35091406Sjhb if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td)) 35171697Sjhb != 0) { 35243412Snewton goto done; 35343412Snewton } 35443412Snewton 35543412Snewton if (vat.va_fsid == vatroot.va_fsid && 35643412Snewton vat.va_fileid == vatroot.va_fileid) { 35743412Snewton error = ENOENT; 35843412Snewton goto done; 35943412Snewton } 36043412Snewton 36143412Snewton } 36243412Snewton if (sgp == NULL) 36343412Snewton *pbuf = buf; 36443412Snewton else { 36543412Snewton sz = &ptr[len] - buf; 36643412Snewton *pbuf = stackgap_alloc(sgp, sz + 1); 36743412Snewton error = copyout(buf, *pbuf, sz); 36843412Snewton free(buf, M_TEMP); 36943412Snewton } 37043412Snewton 37143412Snewton 37243412Snewtondone: 37343412Snewton vrele(nd.ni_vp); 37443412Snewton if (!cflag) 37543412Snewton vrele(ndroot.ni_vp); 37643412Snewton return error; 37743412Snewton} 37843412Snewton 37943412Snewtonstatic int 38043412Snewtonsvr4_elf_modevent(module_t mod, int type, void *data) 38143412Snewton{ 38243412Snewton int error; 38343412Snewton 38443412Snewton error = 0; 38543412Snewton 38643412Snewton switch(type) { 38743412Snewton case MOD_LOAD: 388100384Speter if (elf32_insert_brand_entry(&svr4_brand) < 0) 38943412Snewton error = EINVAL; 39043412Snewton if (error) 39143412Snewton printf("cannot insert svr4 elf brand handler\n"); 39243412Snewton else if (bootverbose) 39343412Snewton printf("svr4 ELF exec handler installed\n"); 39443412Snewton break; 39543412Snewton case MOD_UNLOAD: 39643597Snewton /* Only allow the emulator to be removed if it isn't in use. */ 397100384Speter if (elf32_brand_inuse(&svr4_brand) != 0) { 39843597Snewton error = EBUSY; 399100384Speter } else if (elf32_remove_brand_entry(&svr4_brand) < 0) { 40043412Snewton error = EINVAL; 40143597Snewton } 40243597Snewton 40343412Snewton if (error) 40443597Snewton printf("Could not deinstall ELF interpreter entry (error %d)\n", 40543597Snewton error); 40643412Snewton else if (bootverbose) 40743412Snewton printf("svr4 ELF exec handler removed\n"); 40843412Snewton break; 40943412Snewton default: 41043412Snewton break; 41143412Snewton } 41243412Snewton return error; 41343412Snewton} 41443412Snewton 41543412Snewtonstatic moduledata_t svr4_elf_mod = { 41643412Snewton "svr4elf", 41743412Snewton svr4_elf_modevent, 41843412Snewton 0 41943412Snewton}; 42043412SnewtonDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 42160060SgreenMODULE_DEPEND(svr4elf, streams, 1, 1, 1); 422