svr4_sysvec.c revision 94455
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1998 Mark Newton 31556Srgrimes * All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 3. All advertising materials mentioning features or use of this software 141556Srgrimes * must display the following acknowledgement: 151556Srgrimes * This product includes software developed by Christos Zoulas. 161556Srgrimes * 4. The name of the author may not be used to endorse or promote products 171556Srgrimes * derived from this software without specific prior written permission. 181556Srgrimes * 191556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 201556Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 211556Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 221556Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 231556Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 241556Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 251556Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 261556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 271556Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 281556Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 291556Srgrimes * 301556Srgrimes * $FreeBSD: head/sys/compat/svr4/svr4_sysvec.c 94455 2002-04-11 21:00:38Z jhb $ 311556Srgrimes */ 321556Srgrimes 331556Srgrimes/* XXX we use functions that might not exist. */ 341556Srgrimes#include "opt_compat.h" 351556Srgrimes 361556Srgrimes#ifndef COMPAT_43 371556Srgrimes#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" 3836150Scharnier#endif 3936150Scharnier 4036150Scharnier#include <sys/param.h> 4136150Scharnier#include <sys/systm.h> 4236150Scharnier#include <sys/proc.h> 431556Srgrimes#include <sys/sysent.h> 441556Srgrimes#include <sys/imgact.h> 4517987Speter#include <sys/imgact_elf.h> 4617987Speter#include <sys/socket.h> 4717987Speter#include <sys/lock.h> 4817987Speter#include <sys/malloc.h> 4917987Speter#include <sys/mutex.h> 501556Srgrimes#include <sys/namei.h> 511556Srgrimes#include <sys/vnode.h> 521556Srgrimes#include <sys/module.h> 531556Srgrimes#include <vm/vm.h> 541556Srgrimes#include <sys/exec.h> 551556Srgrimes#include <sys/kernel.h> 561556Srgrimes#include <machine/cpu.h> 5717987Speter#include <netinet/in.h> 5817987Speter 591556Srgrimes#include <compat/svr4/svr4.h> 6017987Speter#include <compat/svr4/svr4_types.h> 6117987Speter#include <compat/svr4/svr4_syscall.h> 621556Srgrimes#include <compat/svr4/svr4_signal.h> 6317987Speter#include <compat/svr4/svr4_sockio.h> 641556Srgrimes#include <compat/svr4/svr4_socket.h> 651556Srgrimes#include <compat/svr4/svr4_errno.h> 661556Srgrimes#include <compat/svr4/svr4_proto.h> 671556Srgrimes#include <compat/svr4/svr4_siginfo.h> 681556Srgrimes#include <compat/svr4/svr4_util.h> 691556Srgrimes 701556Srgrimesint bsd_to_svr4_errno[ELAST+1] = { 711556Srgrimes 0, 721556Srgrimes SVR4_EPERM, 731556Srgrimes SVR4_ENOENT, 741556Srgrimes SVR4_ESRCH, 751556Srgrimes SVR4_EINTR, 761556Srgrimes SVR4_EIO, 771556Srgrimes SVR4_ENXIO, 781556Srgrimes SVR4_E2BIG, 791556Srgrimes SVR4_ENOEXEC, 8017987Speter SVR4_EBADF, 8120425Ssteve SVR4_ECHILD, 8217987Speter SVR4_EDEADLK, 831556Srgrimes SVR4_ENOMEM, 841556Srgrimes SVR4_EACCES, 851556Srgrimes SVR4_EFAULT, 861556Srgrimes SVR4_ENOTBLK, 871556Srgrimes SVR4_EBUSY, 881556Srgrimes SVR4_EEXIST, 891556Srgrimes SVR4_EXDEV, 901556Srgrimes SVR4_ENODEV, 911556Srgrimes SVR4_ENOTDIR, 921556Srgrimes SVR4_EISDIR, 931556Srgrimes SVR4_EINVAL, 941556Srgrimes SVR4_ENFILE, 951556Srgrimes SVR4_EMFILE, 9620425Ssteve SVR4_ENOTTY, 971556Srgrimes SVR4_ETXTBSY, 981556Srgrimes SVR4_EFBIG, 991556Srgrimes SVR4_ENOSPC, 1001556Srgrimes SVR4_ESPIPE, 1011556Srgrimes SVR4_EROFS, 1021556Srgrimes SVR4_EMLINK, 1031556Srgrimes SVR4_EPIPE, 1041556Srgrimes SVR4_EDOM, 1051556Srgrimes SVR4_ERANGE, 1061556Srgrimes SVR4_EAGAIN, 1071556Srgrimes SVR4_EINPROGRESS, 1081556Srgrimes SVR4_EALREADY, 1091556Srgrimes SVR4_ENOTSOCK, 1101556Srgrimes SVR4_EDESTADDRREQ, 1111556Srgrimes SVR4_EMSGSIZE, 1121556Srgrimes SVR4_EPROTOTYPE, 1131556Srgrimes SVR4_ENOPROTOOPT, 1141556Srgrimes SVR4_EPROTONOSUPPORT, 1151556Srgrimes SVR4_ESOCKTNOSUPPORT, 1161556Srgrimes SVR4_EOPNOTSUPP, 1171556Srgrimes SVR4_EPFNOSUPPORT, 1181556Srgrimes SVR4_EAFNOSUPPORT, 1191556Srgrimes SVR4_EADDRINUSE, 1201556Srgrimes SVR4_EADDRNOTAVAIL, 1211556Srgrimes SVR4_ENETDOWN, 1221556Srgrimes SVR4_ENETUNREACH, 1231556Srgrimes SVR4_ENETRESET, 1241556Srgrimes SVR4_ECONNABORTED, 1251556Srgrimes SVR4_ECONNRESET, 1261556Srgrimes SVR4_ENOBUFS, 1271556Srgrimes SVR4_EISCONN, 1281556Srgrimes SVR4_ENOTCONN, 1291556Srgrimes SVR4_ESHUTDOWN, 1301556Srgrimes SVR4_ETOOMANYREFS, 1311556Srgrimes SVR4_ETIMEDOUT, 1321556Srgrimes SVR4_ECONNREFUSED, 1331556Srgrimes SVR4_ELOOP, 1341556Srgrimes SVR4_ENAMETOOLONG, 1351556Srgrimes SVR4_EHOSTDOWN, 1361556Srgrimes SVR4_EHOSTUNREACH, 1371556Srgrimes SVR4_ENOTEMPTY, 1381556Srgrimes SVR4_EPROCLIM, 1391556Srgrimes SVR4_EUSERS, 1401556Srgrimes SVR4_EDQUOT, 1411556Srgrimes SVR4_ESTALE, 1421556Srgrimes SVR4_EREMOTE, 1431556Srgrimes SVR4_EBADRPC, 1441556Srgrimes SVR4_ERPCMISMATCH, 1451556Srgrimes SVR4_EPROGUNAVAIL, 1461556Srgrimes SVR4_EPROGMISMATCH, 14717987Speter SVR4_EPROCUNAVAIL, 14817987Speter SVR4_ENOLCK, 14920425Ssteve SVR4_ENOSYS, 15020425Ssteve SVR4_EFTYPE, 15117987Speter SVR4_EAUTH, 1521556Srgrimes SVR4_ENEEDAUTH, 1531556Srgrimes SVR4_EIDRM, 1541556Srgrimes SVR4_ENOMSG, 15520425Ssteve}; 15620425Ssteve 1571556Srgrimes 1581556Srgrimesstatic int svr4_fixup(register_t **stack_base, struct image_params *imgp); 1591556Srgrimes 1601556Srgrimesextern struct sysent svr4_sysent[]; 1611556Srgrimes#undef szsigcode 1621556Srgrimes#undef sigcode 1631556Srgrimes 1641556Srgrimesextern int svr4_szsigcode; 1651556Srgrimesextern char svr4_sigcode[]; 16617987Speter 1671556Srgrimesstruct sysentvec svr4_sysvec = { 16817987Speter SVR4_SYS_MAXSYSCALL, 16917987Speter svr4_sysent, 1701556Srgrimes 0xff, 1711556Srgrimes SVR4_SIGTBLSZ, 1721556Srgrimes bsd_to_svr4_sig, 1731556Srgrimes ELAST, /* ELAST */ 1741556Srgrimes bsd_to_svr4_errno, 1751556Srgrimes 0, 1761556Srgrimes svr4_fixup, 1771556Srgrimes svr4_sendsig, 1781556Srgrimes svr4_sigcode, 1791556Srgrimes &svr4_szsigcode, 1801556Srgrimes NULL, 1811556Srgrimes "SVR4", 1821556Srgrimes elf_coredump, 1831556Srgrimes NULL, 1841556Srgrimes SVR4_MINSIGSTKSZ 1851556Srgrimes}; 18617987Speter 18717987SpeterElf32_Brandinfo svr4_brand = { 18817987Speter ELFOSABI_SOLARIS, /* XXX Or should we use ELFOSABI_SYSV here? */ 18917987Speter "SVR4", 19017987Speter svr4_emul_path, 19117987Speter "/lib/libc.so.1", 19217987Speter &svr4_sysvec 19317987Speter}; 19417987Speter 19517987Speterconst char svr4_emul_path[] = "/compat/svr4"; 19617987Speter 19717987Speterstatic int 19817987Spetersvr4_fixup(register_t **stack_base, struct image_params *imgp) 19917987Speter{ 20017987Speter Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 2011556Srgrimes register_t *pos; 2021556Srgrimes 2031556Srgrimes pos = *stack_base + (imgp->argc + imgp->envc + 2); 2048855Srgrimes 2051556Srgrimes if (args->trace) { 2061556Srgrimes AUXARGS_ENTRY(pos, AT_DEBUG, 1); 2071556Srgrimes } 2081556Srgrimes if (args->execfd != -1) { 2091556Srgrimes AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 21024348Simp } 2111556Srgrimes AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 2121556Srgrimes AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 2131556Srgrimes AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 2141556Srgrimes AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 2151556Srgrimes AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 2161556Srgrimes AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 2171556Srgrimes AUXARGS_ENTRY(pos, AT_BASE, args->base); 2181556Srgrimes PROC_LOCK(imgp->proc); 2191556Srgrimes AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); 2201556Srgrimes AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); 2211556Srgrimes AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); 2221556Srgrimes AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); 2231556Srgrimes PROC_UNLOCK(imgp->proc); 2241556Srgrimes AUXARGS_ENTRY(pos, AT_NULL, 0); 2251556Srgrimes 2261556Srgrimes free(imgp->auxargs, M_TEMP); 2271556Srgrimes imgp->auxargs = NULL; 2281556Srgrimes 2291556Srgrimes (*stack_base)--; 2301556Srgrimes **stack_base = (int)imgp->argc; 2311556Srgrimes return 0; 2321556Srgrimes} 2331556Srgrimes 2341556Srgrimes/* 2351556Srgrimes * Search an alternate path before passing pathname arguments on 2361556Srgrimes * to system calls. Useful for keeping a separate 'emulation tree'. 2371556Srgrimes * 2381556Srgrimes * If cflag is set, we check if an attempt can be made to create 2391556Srgrimes * the named file, i.e. we check if the directory it should 2401556Srgrimes * be in exists. 2411556Srgrimes * 2421556Srgrimes * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. 2431556Srgrimes */ 2441556Srgrimesint 2451556Srgrimessvr4_emul_find(td, sgp, prefix, path, pbuf, cflag) 2461556Srgrimes struct thread *td; 2471556Srgrimes caddr_t *sgp; /* Pointer to stackgap memory */ 2481556Srgrimes const char *prefix; 2491556Srgrimes char *path; 2501556Srgrimes char **pbuf; 2511556Srgrimes int cflag; 2521556Srgrimes{ 2531556Srgrimes struct nameidata nd; 2541556Srgrimes struct nameidata ndroot; 2551556Srgrimes struct vattr vat; 2561556Srgrimes struct vattr vatroot; 2571556Srgrimes int error; 2581556Srgrimes char *ptr, *buf, *cp; 2591556Srgrimes size_t sz, len; 2601556Srgrimes 2611556Srgrimes buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 2621556Srgrimes *pbuf = path; 2631556Srgrimes 2641556Srgrimes for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 2651556Srgrimes continue; 2661556Srgrimes 2671556Srgrimes sz = MAXPATHLEN - (ptr - buf); 2681556Srgrimes 2691556Srgrimes /* 2701556Srgrimes * If sgp is not given then the path is already in kernel space 2711556Srgrimes */ 2721556Srgrimes if (sgp == NULL) 2731556Srgrimes error = copystr(path, ptr, sz, &len); 2741556Srgrimes else 2751556Srgrimes error = copyinstr(path, ptr, sz, &len); 2761556Srgrimes 2778855Srgrimes if (error) { 2781556Srgrimes free(buf, M_TEMP); 2791556Srgrimes return error; 2801556Srgrimes } 2811556Srgrimes 2821556Srgrimes if (*ptr != '/') { 2831556Srgrimes free(buf, M_TEMP); 2841556Srgrimes return EINVAL; 2851556Srgrimes } 2861556Srgrimes 2871556Srgrimes /* 2881556Srgrimes * We know that there is a / somewhere in this pathname. 2891556Srgrimes * Search backwards for it, to find the file's parent dir 2901556Srgrimes * to see if it exists in the alternate tree. If it does, 2911556Srgrimes * and we want to create a file (cflag is set). We don't 2921556Srgrimes * need to worry about the root comparison in this case. 2931556Srgrimes */ 2941556Srgrimes 2951556Srgrimes if (cflag) { 2961556Srgrimes for (cp = &ptr[len] - 1; *cp != '/'; cp--); 2971556Srgrimes *cp = '\0'; 2981556Srgrimes 2991556Srgrimes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 3001556Srgrimes 3011556Srgrimes if ((error = namei(&nd)) != 0) { 3021556Srgrimes free(buf, M_TEMP); 3031556Srgrimes return error; 3041556Srgrimes } 3051556Srgrimes NDFREE(&nd, NDF_ONLY_PNBUF); 3061556Srgrimes 3071556Srgrimes *cp = '/'; 3081556Srgrimes } 3091556Srgrimes else { 3101556Srgrimes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 3111556Srgrimes 3121556Srgrimes if ((error = namei(&nd)) != 0) { 3131556Srgrimes free(buf, M_TEMP); 3141556Srgrimes return error; 3158855Srgrimes } 3161556Srgrimes NDFREE(&nd, NDF_ONLY_PNBUF); 3171556Srgrimes 3181556Srgrimes /* 3191556Srgrimes * We now compare the vnode of the svr4_root to the one 3201556Srgrimes * vnode asked. If they resolve to be the same, then we 3211556Srgrimes * ignore the match so that the real root gets used. 3221556Srgrimes * This avoids the problem of traversing "../.." to find the 3231556Srgrimes * root directory and never finding it, because "/" resolves 3241556Srgrimes * to the emulation root directory. This is expensive :-( 3251556Srgrimes */ 3261556Srgrimes NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, 3271556Srgrimes td); 3281556Srgrimes 3291556Srgrimes if ((error = namei(&ndroot)) != 0) { 3301556Srgrimes /* Cannot happen! */ 33118016Speter free(buf, M_TEMP); 3321556Srgrimes vrele(nd.ni_vp); 3331556Srgrimes return error; 3341556Srgrimes } 3351556Srgrimes NDFREE(&ndroot, NDF_ONLY_PNBUF); 3361556Srgrimes 3371556Srgrimes if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) { 3381556Srgrimes goto done; 3391556Srgrimes } 3401556Srgrimes 3411556Srgrimes if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td)) 3421556Srgrimes != 0) { 3431556Srgrimes goto done; 3441556Srgrimes } 3451556Srgrimes 3461556Srgrimes if (vat.va_fsid == vatroot.va_fsid && 3471556Srgrimes vat.va_fileid == vatroot.va_fileid) { 3481556Srgrimes error = ENOENT; 3491556Srgrimes goto done; 3501556Srgrimes } 3518855Srgrimes 3521556Srgrimes } 3531556Srgrimes if (sgp == NULL) 3541556Srgrimes *pbuf = buf; 3551556Srgrimes else { 3561556Srgrimes sz = &ptr[len] - buf; 3571556Srgrimes *pbuf = stackgap_alloc(sgp, sz + 1); 3581556Srgrimes error = copyout(buf, *pbuf, sz); 3591556Srgrimes free(buf, M_TEMP); 3601556Srgrimes } 3618855Srgrimes 3621556Srgrimes 3631556Srgrimesdone: 3641556Srgrimes vrele(nd.ni_vp); 3651556Srgrimes if (!cflag) 3661556Srgrimes vrele(ndroot.ni_vp); 3671556Srgrimes return error; 3681556Srgrimes} 3691556Srgrimes 3701556Srgrimesstatic int 3711556Srgrimessvr4_elf_modevent(module_t mod, int type, void *data) 3721556Srgrimes{ 3731556Srgrimes int error; 3741556Srgrimes 3751556Srgrimes error = 0; 3761556Srgrimes 3771556Srgrimes switch(type) { 3781556Srgrimes case MOD_LOAD: 3791556Srgrimes if (elf_insert_brand_entry(&svr4_brand) < 0) 3801556Srgrimes error = EINVAL; 3811556Srgrimes if (error) 3821556Srgrimes printf("cannot insert svr4 elf brand handler\n"); 3831556Srgrimes else if (bootverbose) 3841556Srgrimes printf("svr4 ELF exec handler installed\n"); 3851556Srgrimes break; 3861556Srgrimes case MOD_UNLOAD: 3878855Srgrimes /* Only allow the emulator to be removed if it isn't in use. */ 3881556Srgrimes if (elf_brand_inuse(&svr4_brand) != 0) { 3891556Srgrimes error = EBUSY; 3901556Srgrimes } else if (elf_remove_brand_entry(&svr4_brand) < 0) { 3911556Srgrimes error = EINVAL; 39217987Speter } 3931556Srgrimes 3941556Srgrimes if (error) 3951556Srgrimes printf("Could not deinstall ELF interpreter entry (error %d)\n", 3961556Srgrimes error); 3971556Srgrimes else if (bootverbose) 3981556Srgrimes printf("svr4 ELF exec handler removed\n"); 3991556Srgrimes break; 4001556Srgrimes default: 4011556Srgrimes break; 4021556Srgrimes } 4031556Srgrimes return error; 4041556Srgrimes} 4051556Srgrimes 4061556Srgrimesstatic moduledata_t svr4_elf_mod = { 4071556Srgrimes "svr4elf", 4081556Srgrimes svr4_elf_modevent, 4091556Srgrimes 0 4101556Srgrimes}; 4111556SrgrimesDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 4121556SrgrimesMODULE_DEPEND(svr4elf, streams, 1, 1, 1); 4131556Srgrimes