svr4_sysvec.c revision 132199
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 */ 3049267Snewton 31116174Sobrien#include <sys/cdefs.h> 32116174Sobrien__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_sysvec.c 132199 2004-07-15 08:26:07Z phk $"); 33116174Sobrien 3443412Snewton/* XXX we use functions that might not exist. */ 3543412Snewton#include "opt_compat.h" 3643412Snewton 3743412Snewton#ifndef COMPAT_43 3843412Snewton#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" 3943412Snewton#endif 4043412Snewton 4143412Snewton#include <sys/param.h> 4248503Sgreen#include <sys/systm.h> 4343412Snewton#include <sys/proc.h> 4443412Snewton#include <sys/sysent.h> 4543412Snewton#include <sys/imgact.h> 4643412Snewton#include <sys/imgact_elf.h> 4743412Snewton#include <sys/socket.h> 4894455Sjhb#include <sys/lock.h> 4943412Snewton#include <sys/malloc.h> 5094455Sjhb#include <sys/mutex.h> 5143412Snewton#include <sys/namei.h> 5243412Snewton#include <sys/vnode.h> 5343412Snewton#include <sys/module.h> 5443412Snewton#include <vm/vm.h> 5543412Snewton#include <sys/exec.h> 5643412Snewton#include <sys/kernel.h> 5743412Snewton#include <machine/cpu.h> 5843412Snewton#include <netinet/in.h> 5943412Snewton 6065302Sobrien#include <compat/svr4/svr4.h> 6165302Sobrien#include <compat/svr4/svr4_types.h> 6265302Sobrien#include <compat/svr4/svr4_syscall.h> 6365302Sobrien#include <compat/svr4/svr4_signal.h> 6465302Sobrien#include <compat/svr4/svr4_sockio.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, 192120422Speter exec_setregs, 193120422Speter NULL 19443412Snewton}; 19543412Snewton 19643412SnewtonElf32_Brandinfo svr4_brand = { 19799669Srobert ELFOSABI_SYSV, 198100384Speter EM_386, /* XXX only implemented for x86 so far. */ 19972999Sobrien "SVR4", 20059342Sobrien svr4_emul_path, 20143412Snewton "/lib/libc.so.1", 202123742Speter &svr4_sysvec, 203123742Speter NULL, 20443412Snewton}; 20543412Snewton 20643412Snewtonconst char svr4_emul_path[] = "/compat/svr4"; 20743412Snewton 20843412Snewtonstatic int 20959342Sobriensvr4_fixup(register_t **stack_base, struct image_params *imgp) 21043412Snewton{ 211112470Sjhb Elf32_Auxargs *args; 21259342Sobrien register_t *pos; 21343412Snewton 214112470Sjhb KASSERT(curthread->td_proc == imgp->proc && 215116361Sdavidxu (curthread->td_proc->p_flag & P_SA) == 0, 216112470Sjhb ("unsafe svr4_fixup(), should be curproc")); 217112470Sjhb args = (Elf32_Auxargs *)imgp->auxargs; 21843412Snewton pos = *stack_base + (imgp->argc + imgp->envc + 2); 21943412Snewton 220112470Sjhb if (args->trace) 22143412Snewton AUXARGS_ENTRY(pos, AT_DEBUG, 1); 222112470Sjhb if (args->execfd != -1) 22343412Snewton AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 22443412Snewton AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 22543412Snewton AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 22643412Snewton AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 22743412Snewton AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 22843412Snewton AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 22943412Snewton AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 23043412Snewton AUXARGS_ENTRY(pos, AT_BASE, args->base); 23177183Srwatson AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); 23277183Srwatson AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); 23377183Srwatson AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); 23477183Srwatson AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); 23543412Snewton AUXARGS_ENTRY(pos, AT_NULL, 0); 23643412Snewton 23743412Snewton free(imgp->auxargs, M_TEMP); 23843412Snewton imgp->auxargs = NULL; 23943412Snewton 24043412Snewton (*stack_base)--; 241112470Sjhb **stack_base = (register_t)imgp->argc; 24243412Snewton return 0; 24343412Snewton} 24443412Snewton 24543412Snewton/* 24643412Snewton * Search an alternate path before passing pathname arguments on 24772091Sasmodai * to system calls. Useful for keeping a separate 'emulation tree'. 24843412Snewton * 24943412Snewton * If cflag is set, we check if an attempt can be made to create 25043412Snewton * the named file, i.e. we check if the directory it should 25143412Snewton * be in exists. 25243412Snewton * 25343412Snewton * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. 25443412Snewton */ 25543412Snewtonint 25683366Sjuliansvr4_emul_find(td, sgp, prefix, path, pbuf, cflag) 25783366Sjulian struct thread *td; 25843412Snewton caddr_t *sgp; /* Pointer to stackgap memory */ 25943412Snewton const char *prefix; 26043412Snewton char *path; 26143412Snewton char **pbuf; 26243412Snewton int cflag; 26343412Snewton{ 26443412Snewton struct nameidata nd; 26543412Snewton struct nameidata ndroot; 26643412Snewton struct vattr vat; 26743412Snewton struct vattr vatroot; 26843412Snewton int error; 26943412Snewton char *ptr, *buf, *cp; 27043412Snewton size_t sz, len; 27143412Snewton 272111119Simp buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 27343412Snewton *pbuf = path; 27443412Snewton 27543412Snewton for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 27643412Snewton continue; 27743412Snewton 27843412Snewton sz = MAXPATHLEN - (ptr - buf); 27943412Snewton 28043412Snewton /* 28143412Snewton * If sgp is not given then the path is already in kernel space 28243412Snewton */ 28343412Snewton if (sgp == NULL) 28443412Snewton error = copystr(path, ptr, sz, &len); 28543412Snewton else 28643412Snewton error = copyinstr(path, ptr, sz, &len); 28743412Snewton 28843412Snewton if (error) { 28943412Snewton free(buf, M_TEMP); 29043412Snewton return error; 29143412Snewton } 29243412Snewton 29343412Snewton if (*ptr != '/') { 29443412Snewton free(buf, M_TEMP); 29543412Snewton return EINVAL; 29643412Snewton } 29743412Snewton 29843412Snewton /* 29943412Snewton * We know that there is a / somewhere in this pathname. 30043412Snewton * Search backwards for it, to find the file's parent dir 30143412Snewton * to see if it exists in the alternate tree. If it does, 30243412Snewton * and we want to create a file (cflag is set). We don't 30343412Snewton * need to worry about the root comparison in this case. 30443412Snewton */ 30543412Snewton 30643412Snewton if (cflag) { 30743412Snewton for (cp = &ptr[len] - 1; *cp != '/'; cp--); 30843412Snewton *cp = '\0'; 30943412Snewton 31083366Sjulian NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 31143412Snewton 31243412Snewton if ((error = namei(&nd)) != 0) { 31343412Snewton free(buf, M_TEMP); 31443412Snewton return error; 31543412Snewton } 31654655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 31743412Snewton 31843412Snewton *cp = '/'; 31943412Snewton } 32043412Snewton else { 32183366Sjulian NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 32243412Snewton 32343412Snewton if ((error = namei(&nd)) != 0) { 32443412Snewton free(buf, M_TEMP); 32543412Snewton return error; 32643412Snewton } 32754655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 32843412Snewton 32943412Snewton /* 33043412Snewton * We now compare the vnode of the svr4_root to the one 33143412Snewton * vnode asked. If they resolve to be the same, then we 33243412Snewton * ignore the match so that the real root gets used. 33343412Snewton * This avoids the problem of traversing "../.." to find the 33443412Snewton * root directory and never finding it, because "/" resolves 33543412Snewton * to the emulation root directory. This is expensive :-( 33643412Snewton */ 33743412Snewton NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, 33883366Sjulian td); 33943412Snewton 34043412Snewton if ((error = namei(&ndroot)) != 0) { 34143412Snewton /* Cannot happen! */ 34243412Snewton free(buf, M_TEMP); 34343412Snewton vrele(nd.ni_vp); 34443412Snewton return error; 34543412Snewton } 34654655Seivind NDFREE(&ndroot, NDF_ONLY_PNBUF); 34743412Snewton 34891406Sjhb if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) { 34943412Snewton goto done; 35043412Snewton } 35143412Snewton 35291406Sjhb if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td)) 35371697Sjhb != 0) { 35443412Snewton goto done; 35543412Snewton } 35643412Snewton 35743412Snewton if (vat.va_fsid == vatroot.va_fsid && 35843412Snewton vat.va_fileid == vatroot.va_fileid) { 35943412Snewton error = ENOENT; 36043412Snewton goto done; 36143412Snewton } 36243412Snewton 36343412Snewton } 36443412Snewton if (sgp == NULL) 36543412Snewton *pbuf = buf; 36643412Snewton else { 36743412Snewton sz = &ptr[len] - buf; 368121275Stjr if ((*pbuf = stackgap_alloc(sgp, sz + 1)) != NULL) 369121275Stjr error = copyout(buf, *pbuf, sz); 370121275Stjr else 371121275Stjr error = ENAMETOOLONG; 37243412Snewton free(buf, M_TEMP); 37343412Snewton } 37443412Snewton 37543412Snewton 37643412Snewtondone: 37743412Snewton vrele(nd.ni_vp); 37843412Snewton if (!cflag) 37943412Snewton vrele(ndroot.ni_vp); 38043412Snewton return error; 38143412Snewton} 38243412Snewton 38343412Snewtonstatic int 38443412Snewtonsvr4_elf_modevent(module_t mod, int type, void *data) 38543412Snewton{ 38643412Snewton int error; 38743412Snewton 38843412Snewton error = 0; 38943412Snewton 39043412Snewton switch(type) { 39143412Snewton case MOD_LOAD: 392100384Speter if (elf32_insert_brand_entry(&svr4_brand) < 0) 39343412Snewton error = EINVAL; 39443412Snewton if (error) 39543412Snewton printf("cannot insert svr4 elf brand handler\n"); 39643412Snewton else if (bootverbose) 39743412Snewton printf("svr4 ELF exec handler installed\n"); 39843412Snewton break; 39943412Snewton case MOD_UNLOAD: 40043597Snewton /* Only allow the emulator to be removed if it isn't in use. */ 401100384Speter if (elf32_brand_inuse(&svr4_brand) != 0) { 40243597Snewton error = EBUSY; 403100384Speter } else if (elf32_remove_brand_entry(&svr4_brand) < 0) { 40443412Snewton error = EINVAL; 40543597Snewton } 40643597Snewton 40743412Snewton if (error) 40843597Snewton printf("Could not deinstall ELF interpreter entry (error %d)\n", 40943597Snewton error); 41043412Snewton else if (bootverbose) 41143412Snewton printf("svr4 ELF exec handler removed\n"); 41243412Snewton break; 41343412Snewton default: 414132199Sphk return (EOPNOTSUPP); 41543412Snewton break; 41643412Snewton } 41743412Snewton return error; 41843412Snewton} 41943412Snewton 42043412Snewtonstatic moduledata_t svr4_elf_mod = { 42143412Snewton "svr4elf", 42243412Snewton svr4_elf_modevent, 42343412Snewton 0 42443412Snewton}; 42543412SnewtonDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 42660060SgreenMODULE_DEPEND(svr4elf, streams, 1, 1, 1); 427