svr4_sysvec.c revision 72091
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 72091 2001-02-06 11:21:58Z asmodai $ 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> 4743412Snewton#include <sys/malloc.h> 4843412Snewton#include <sys/namei.h> 4943412Snewton#include <sys/vnode.h> 5043412Snewton#include <sys/module.h> 5143412Snewton#include <vm/vm.h> 5243412Snewton#include <sys/exec.h> 5343412Snewton#include <sys/kernel.h> 5443412Snewton#include <machine/cpu.h> 5543412Snewton#include <netinet/in.h> 5643412Snewton 5765302Sobrien#include <compat/svr4/svr4.h> 5865302Sobrien#include <compat/svr4/svr4_types.h> 5965302Sobrien#include <compat/svr4/svr4_syscall.h> 6065302Sobrien#include <compat/svr4/svr4_signal.h> 6165302Sobrien#include <compat/svr4/svr4_sockio.h> 6265302Sobrien#include <compat/svr4/svr4_socket.h> 6365302Sobrien#include <compat/svr4/svr4_errno.h> 6465302Sobrien#include <compat/svr4/svr4_proto.h> 6565302Sobrien#include <compat/svr4/svr4_siginfo.h> 6665302Sobrien#include <compat/svr4/svr4_util.h> 6743412Snewton 6843412Snewtonint bsd_to_svr4_errno[ELAST+1] = { 6943412Snewton 0, 7043412Snewton SVR4_EPERM, 7143412Snewton SVR4_ENOENT, 7243412Snewton SVR4_ESRCH, 7343412Snewton SVR4_EINTR, 7443412Snewton SVR4_EIO, 7543412Snewton SVR4_ENXIO, 7643412Snewton SVR4_E2BIG, 7743412Snewton SVR4_ENOEXEC, 7843412Snewton SVR4_EBADF, 7943412Snewton SVR4_ECHILD, 8043412Snewton SVR4_EDEADLK, 8143412Snewton SVR4_ENOMEM, 8243412Snewton SVR4_EACCES, 8343412Snewton SVR4_EFAULT, 8443412Snewton SVR4_ENOTBLK, 8543412Snewton SVR4_EBUSY, 8643412Snewton SVR4_EEXIST, 8743412Snewton SVR4_EXDEV, 8843412Snewton SVR4_ENODEV, 8943412Snewton SVR4_ENOTDIR, 9043412Snewton SVR4_EISDIR, 9143412Snewton SVR4_EINVAL, 9243412Snewton SVR4_ENFILE, 9343412Snewton SVR4_EMFILE, 9443412Snewton SVR4_ENOTTY, 9543412Snewton SVR4_ETXTBSY, 9643412Snewton SVR4_EFBIG, 9743412Snewton SVR4_ENOSPC, 9843412Snewton SVR4_ESPIPE, 9943412Snewton SVR4_EROFS, 10043412Snewton SVR4_EMLINK, 10143412Snewton SVR4_EPIPE, 10243412Snewton SVR4_EDOM, 10343412Snewton SVR4_ERANGE, 10443412Snewton SVR4_EAGAIN, 10543412Snewton SVR4_EINPROGRESS, 10643412Snewton SVR4_EALREADY, 10743412Snewton SVR4_ENOTSOCK, 10843412Snewton SVR4_EDESTADDRREQ, 10943412Snewton SVR4_EMSGSIZE, 11043412Snewton SVR4_EPROTOTYPE, 11143412Snewton SVR4_ENOPROTOOPT, 11243412Snewton SVR4_EPROTONOSUPPORT, 11343412Snewton SVR4_ESOCKTNOSUPPORT, 11443412Snewton SVR4_EOPNOTSUPP, 11543412Snewton SVR4_EPFNOSUPPORT, 11643412Snewton SVR4_EAFNOSUPPORT, 11743412Snewton SVR4_EADDRINUSE, 11843412Snewton SVR4_EADDRNOTAVAIL, 11943412Snewton SVR4_ENETDOWN, 12043412Snewton SVR4_ENETUNREACH, 12143412Snewton SVR4_ENETRESET, 12243412Snewton SVR4_ECONNABORTED, 12343412Snewton SVR4_ECONNRESET, 12443412Snewton SVR4_ENOBUFS, 12543412Snewton SVR4_EISCONN, 12643412Snewton SVR4_ENOTCONN, 12743412Snewton SVR4_ESHUTDOWN, 12843412Snewton SVR4_ETOOMANYREFS, 12943412Snewton SVR4_ETIMEDOUT, 13043412Snewton SVR4_ECONNREFUSED, 13143412Snewton SVR4_ELOOP, 13243412Snewton SVR4_ENAMETOOLONG, 13343412Snewton SVR4_EHOSTDOWN, 13443412Snewton SVR4_EHOSTUNREACH, 13543412Snewton SVR4_ENOTEMPTY, 13643412Snewton SVR4_EPROCLIM, 13743412Snewton SVR4_EUSERS, 13843412Snewton SVR4_EDQUOT, 13943412Snewton SVR4_ESTALE, 14043412Snewton SVR4_EREMOTE, 14143412Snewton SVR4_EBADRPC, 14243412Snewton SVR4_ERPCMISMATCH, 14343412Snewton SVR4_EPROGUNAVAIL, 14443412Snewton SVR4_EPROGMISMATCH, 14543412Snewton SVR4_EPROCUNAVAIL, 14643412Snewton SVR4_ENOLCK, 14743412Snewton SVR4_ENOSYS, 14843412Snewton SVR4_EFTYPE, 14943412Snewton SVR4_EAUTH, 15043412Snewton SVR4_ENEEDAUTH, 15143412Snewton SVR4_EIDRM, 15243412Snewton SVR4_ENOMSG, 15343412Snewton}; 15443412Snewton 15543412Snewton 15659342Sobrienstatic int svr4_fixup(register_t **stack_base, struct image_params *imgp); 15743412Snewton 15843412Snewtonextern struct sysent svr4_sysent[]; 15943412Snewton#undef szsigcode 16043412Snewton#undef sigcode 16143412Snewton 16243412Snewtonextern int svr4_szsigcode; 16343412Snewtonextern char svr4_sigcode[]; 16443412Snewton 16543412Snewtonstruct sysentvec svr4_sysvec = { 16643412Snewton SVR4_SYS_MAXSYSCALL, 16743412Snewton svr4_sysent, 16843412Snewton 0xff, 16951793Smarcel SVR4_SIGTBLSZ, 17043412Snewton bsd_to_svr4_sig, 17143412Snewton ELAST, /* ELAST */ 17243412Snewton bsd_to_svr4_errno, 17343412Snewton 0, 17443412Snewton svr4_fixup, 17543412Snewton svr4_sendsig, 17643412Snewton svr4_sigcode, 17743412Snewton &svr4_szsigcode, 17849267Snewton NULL, 17949267Snewton "SVR4", 18068520Smarcel elf_coredump, 18168520Smarcel NULL, 18268520Smarcel SVR4_MINSIGSTKSZ 18343412Snewton}; 18443412Snewton 18543412SnewtonElf32_Brandinfo svr4_brand = { 18659342Sobrien ELFOSABI_SOLARIS, /* XXX Or should we use ELFOSABI_SYSV here? */ 18759342Sobrien svr4_emul_path, 18843412Snewton "/lib/libc.so.1", 18943412Snewton &svr4_sysvec 19043412Snewton}; 19143412Snewton 19243412Snewtonconst char svr4_emul_path[] = "/compat/svr4"; 19343412Snewton 19443412Snewtonstatic int 19559342Sobriensvr4_fixup(register_t **stack_base, struct image_params *imgp) 19643412Snewton{ 19743412Snewton Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 19859342Sobrien register_t *pos; 19943412Snewton 20043412Snewton pos = *stack_base + (imgp->argc + imgp->envc + 2); 20143412Snewton 20243412Snewton if (args->trace) { 20343412Snewton AUXARGS_ENTRY(pos, AT_DEBUG, 1); 20443412Snewton } 20543412Snewton if (args->execfd != -1) { 20643412Snewton AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 20743412Snewton } 20843412Snewton AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 20943412Snewton AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 21043412Snewton AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 21143412Snewton AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 21243412Snewton AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 21343412Snewton AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 21443412Snewton AUXARGS_ENTRY(pos, AT_BASE, args->base); 21543412Snewton AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); 21643412Snewton AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); 21743412Snewton AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); 21843412Snewton AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); 21943412Snewton AUXARGS_ENTRY(pos, AT_NULL, 0); 22043412Snewton 22143412Snewton free(imgp->auxargs, M_TEMP); 22243412Snewton imgp->auxargs = NULL; 22343412Snewton 22443412Snewton (*stack_base)--; 22543412Snewton **stack_base = (int)imgp->argc; 22643412Snewton return 0; 22743412Snewton} 22843412Snewton 22943412Snewton/* 23043412Snewton * Search an alternate path before passing pathname arguments on 23172091Sasmodai * to system calls. Useful for keeping a separate 'emulation tree'. 23243412Snewton * 23343412Snewton * If cflag is set, we check if an attempt can be made to create 23443412Snewton * the named file, i.e. we check if the directory it should 23543412Snewton * be in exists. 23643412Snewton * 23743412Snewton * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. 23843412Snewton */ 23943412Snewtonint 24043412Snewtonsvr4_emul_find(p, sgp, prefix, path, pbuf, cflag) 24143412Snewton struct proc *p; 24243412Snewton caddr_t *sgp; /* Pointer to stackgap memory */ 24343412Snewton const char *prefix; 24443412Snewton char *path; 24543412Snewton char **pbuf; 24643412Snewton int cflag; 24743412Snewton{ 24843412Snewton struct nameidata nd; 24943412Snewton struct nameidata ndroot; 25043412Snewton struct vattr vat; 25143412Snewton struct vattr vatroot; 25243412Snewton int error; 25343412Snewton char *ptr, *buf, *cp; 25443412Snewton size_t sz, len; 25543412Snewton 25643412Snewton buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 25743412Snewton *pbuf = path; 25843412Snewton 25943412Snewton for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 26043412Snewton continue; 26143412Snewton 26243412Snewton sz = MAXPATHLEN - (ptr - buf); 26343412Snewton 26443412Snewton /* 26543412Snewton * If sgp is not given then the path is already in kernel space 26643412Snewton */ 26743412Snewton if (sgp == NULL) 26843412Snewton error = copystr(path, ptr, sz, &len); 26943412Snewton else 27043412Snewton error = copyinstr(path, ptr, sz, &len); 27143412Snewton 27243412Snewton if (error) { 27343412Snewton free(buf, M_TEMP); 27443412Snewton return error; 27543412Snewton } 27643412Snewton 27743412Snewton if (*ptr != '/') { 27843412Snewton free(buf, M_TEMP); 27943412Snewton return EINVAL; 28043412Snewton } 28143412Snewton 28243412Snewton /* 28343412Snewton * We know that there is a / somewhere in this pathname. 28443412Snewton * Search backwards for it, to find the file's parent dir 28543412Snewton * to see if it exists in the alternate tree. If it does, 28643412Snewton * and we want to create a file (cflag is set). We don't 28743412Snewton * need to worry about the root comparison in this case. 28843412Snewton */ 28943412Snewton 29043412Snewton if (cflag) { 29143412Snewton for (cp = &ptr[len] - 1; *cp != '/'; cp--); 29243412Snewton *cp = '\0'; 29343412Snewton 29443412Snewton NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); 29543412Snewton 29643412Snewton if ((error = namei(&nd)) != 0) { 29743412Snewton free(buf, M_TEMP); 29843412Snewton return error; 29943412Snewton } 30054655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 30143412Snewton 30243412Snewton *cp = '/'; 30343412Snewton } 30443412Snewton else { 30543412Snewton NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); 30643412Snewton 30743412Snewton if ((error = namei(&nd)) != 0) { 30843412Snewton free(buf, M_TEMP); 30943412Snewton return error; 31043412Snewton } 31154655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 31243412Snewton 31343412Snewton /* 31443412Snewton * We now compare the vnode of the svr4_root to the one 31543412Snewton * vnode asked. If they resolve to be the same, then we 31643412Snewton * ignore the match so that the real root gets used. 31743412Snewton * This avoids the problem of traversing "../.." to find the 31843412Snewton * root directory and never finding it, because "/" resolves 31943412Snewton * to the emulation root directory. This is expensive :-( 32043412Snewton */ 32143412Snewton NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, 32243412Snewton p); 32343412Snewton 32443412Snewton if ((error = namei(&ndroot)) != 0) { 32543412Snewton /* Cannot happen! */ 32643412Snewton free(buf, M_TEMP); 32743412Snewton vrele(nd.ni_vp); 32843412Snewton return error; 32943412Snewton } 33054655Seivind NDFREE(&ndroot, NDF_ONLY_PNBUF); 33143412Snewton 33271697Sjhb if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) { 33343412Snewton goto done; 33443412Snewton } 33543412Snewton 33671697Sjhb if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p)) 33771697Sjhb != 0) { 33843412Snewton goto done; 33943412Snewton } 34043412Snewton 34143412Snewton if (vat.va_fsid == vatroot.va_fsid && 34243412Snewton vat.va_fileid == vatroot.va_fileid) { 34343412Snewton error = ENOENT; 34443412Snewton goto done; 34543412Snewton } 34643412Snewton 34743412Snewton } 34843412Snewton if (sgp == NULL) 34943412Snewton *pbuf = buf; 35043412Snewton else { 35143412Snewton sz = &ptr[len] - buf; 35243412Snewton *pbuf = stackgap_alloc(sgp, sz + 1); 35343412Snewton error = copyout(buf, *pbuf, sz); 35443412Snewton free(buf, M_TEMP); 35543412Snewton } 35643412Snewton 35743412Snewton 35843412Snewtondone: 35943412Snewton vrele(nd.ni_vp); 36043412Snewton if (!cflag) 36143412Snewton vrele(ndroot.ni_vp); 36243412Snewton return error; 36343412Snewton} 36443412Snewton 36543412Snewtonstatic int 36643412Snewtonsvr4_elf_modevent(module_t mod, int type, void *data) 36743412Snewton{ 36843412Snewton int error; 36943412Snewton 37043412Snewton error = 0; 37143412Snewton 37243412Snewton switch(type) { 37343412Snewton case MOD_LOAD: 37443412Snewton if (elf_insert_brand_entry(&svr4_brand) < 0) 37543412Snewton error = EINVAL; 37643412Snewton if (error) 37743412Snewton printf("cannot insert svr4 elf brand handler\n"); 37843412Snewton else if (bootverbose) 37943412Snewton printf("svr4 ELF exec handler installed\n"); 38043412Snewton break; 38143412Snewton case MOD_UNLOAD: 38243597Snewton /* Only allow the emulator to be removed if it isn't in use. */ 38343597Snewton if (elf_brand_inuse(&svr4_brand) != 0) { 38443597Snewton error = EBUSY; 38543597Snewton } else if (elf_remove_brand_entry(&svr4_brand) < 0) { 38643412Snewton error = EINVAL; 38743597Snewton } 38843597Snewton 38943412Snewton if (error) 39043597Snewton printf("Could not deinstall ELF interpreter entry (error %d)\n", 39143597Snewton error); 39243412Snewton else if (bootverbose) 39343412Snewton printf("svr4 ELF exec handler removed\n"); 39443412Snewton break; 39543412Snewton default: 39643412Snewton break; 39743412Snewton } 39843412Snewton return error; 39943412Snewton} 40043412Snewton 40143412Snewtonstatic moduledata_t svr4_elf_mod = { 40243412Snewton "svr4elf", 40343412Snewton svr4_elf_modevent, 40443412Snewton 0 40543412Snewton}; 40643412SnewtonDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 40760060SgreenMODULE_DEPEND(svr4elf, streams, 1, 1, 1); 408