svr4_sysvec.c revision 43597
143412Snewton/* XXX we use functions that might not exist. */ 243412Snewton#include "opt_compat.h" 343412Snewton 443412Snewton#ifndef COMPAT_43 543412Snewton#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" 643412Snewton#endif 743412Snewton 843412Snewton#include <sys/param.h> 943412Snewton#include <sys/buf.h> 1043412Snewton#include <sys/proc.h> 1143412Snewton#include <sys/systm.h> 1243412Snewton#include <sys/sysent.h> 1343412Snewton#include <sys/imgact.h> 1443412Snewton#include <sys/imgact_elf.h> 1543412Snewton#include <sys/socket.h> 1643412Snewton#include <sys/sockio.h> 1743412Snewton#include <sys/signalvar.h> 1843412Snewton#include <sys/malloc.h> 1943412Snewton#include <sys/namei.h> 2043412Snewton#include <sys/vnode.h> 2143412Snewton#include <sys/module.h> 2243412Snewton#include <vm/vm.h> 2343412Snewton#include <vm/vm_param.h> 2443412Snewton#include <vm/vm_prot.h> 2543412Snewton#include <vm/vm_page.h> 2643412Snewton#include <vm/vm_extern.h> 2743412Snewton#include <sys/exec.h> 2843412Snewton#include <sys/kernel.h> 2943412Snewton#include <machine/cpu.h> 3043412Snewton#include <netinet/in.h> 3143412Snewton 3243412Snewton#include <svr4/svr4.h> 3343412Snewton#include <svr4/svr4_types.h> 3443412Snewton#include <svr4/svr4_syscall.h> 3543412Snewton#include <svr4/svr4_signal.h> 3643412Snewton#include <svr4/svr4_sockio.h> 3743412Snewton#include <svr4/svr4_socket.h> 3843412Snewton#include <svr4/svr4_errno.h> 3943412Snewton#include <svr4/svr4_proto.h> 4043412Snewton#include <svr4/svr4_siginfo.h> 4143412Snewton#include <svr4/svr4_util.h> 4243412Snewton 4343412Snewtonextern int bsd_to_svr4_sig[]; 4443412Snewtonextern int svr4_to_bsd_sig[]; 4543412Snewton 4643412Snewtonint bsd_to_svr4_errno[ELAST+1] = { 4743412Snewton 0, 4843412Snewton SVR4_EPERM, 4943412Snewton SVR4_ENOENT, 5043412Snewton SVR4_ESRCH, 5143412Snewton SVR4_EINTR, 5243412Snewton SVR4_EIO, 5343412Snewton SVR4_ENXIO, 5443412Snewton SVR4_E2BIG, 5543412Snewton SVR4_ENOEXEC, 5643412Snewton SVR4_EBADF, 5743412Snewton SVR4_ECHILD, 5843412Snewton SVR4_EDEADLK, 5943412Snewton SVR4_ENOMEM, 6043412Snewton SVR4_EACCES, 6143412Snewton SVR4_EFAULT, 6243412Snewton SVR4_ENOTBLK, 6343412Snewton SVR4_EBUSY, 6443412Snewton SVR4_EEXIST, 6543412Snewton SVR4_EXDEV, 6643412Snewton SVR4_ENODEV, 6743412Snewton SVR4_ENOTDIR, 6843412Snewton SVR4_EISDIR, 6943412Snewton SVR4_EINVAL, 7043412Snewton SVR4_ENFILE, 7143412Snewton SVR4_EMFILE, 7243412Snewton SVR4_ENOTTY, 7343412Snewton SVR4_ETXTBSY, 7443412Snewton SVR4_EFBIG, 7543412Snewton SVR4_ENOSPC, 7643412Snewton SVR4_ESPIPE, 7743412Snewton SVR4_EROFS, 7843412Snewton SVR4_EMLINK, 7943412Snewton SVR4_EPIPE, 8043412Snewton SVR4_EDOM, 8143412Snewton SVR4_ERANGE, 8243412Snewton SVR4_EAGAIN, 8343412Snewton SVR4_EINPROGRESS, 8443412Snewton SVR4_EALREADY, 8543412Snewton SVR4_ENOTSOCK, 8643412Snewton SVR4_EDESTADDRREQ, 8743412Snewton SVR4_EMSGSIZE, 8843412Snewton SVR4_EPROTOTYPE, 8943412Snewton SVR4_ENOPROTOOPT, 9043412Snewton SVR4_EPROTONOSUPPORT, 9143412Snewton SVR4_ESOCKTNOSUPPORT, 9243412Snewton SVR4_EOPNOTSUPP, 9343412Snewton SVR4_EPFNOSUPPORT, 9443412Snewton SVR4_EAFNOSUPPORT, 9543412Snewton SVR4_EADDRINUSE, 9643412Snewton SVR4_EADDRNOTAVAIL, 9743412Snewton SVR4_ENETDOWN, 9843412Snewton SVR4_ENETUNREACH, 9943412Snewton SVR4_ENETRESET, 10043412Snewton SVR4_ECONNABORTED, 10143412Snewton SVR4_ECONNRESET, 10243412Snewton SVR4_ENOBUFS, 10343412Snewton SVR4_EISCONN, 10443412Snewton SVR4_ENOTCONN, 10543412Snewton SVR4_ESHUTDOWN, 10643412Snewton SVR4_ETOOMANYREFS, 10743412Snewton SVR4_ETIMEDOUT, 10843412Snewton SVR4_ECONNREFUSED, 10943412Snewton SVR4_ELOOP, 11043412Snewton SVR4_ENAMETOOLONG, 11143412Snewton SVR4_EHOSTDOWN, 11243412Snewton SVR4_EHOSTUNREACH, 11343412Snewton SVR4_ENOTEMPTY, 11443412Snewton SVR4_EPROCLIM, 11543412Snewton SVR4_EUSERS, 11643412Snewton SVR4_EDQUOT, 11743412Snewton SVR4_ESTALE, 11843412Snewton SVR4_EREMOTE, 11943412Snewton SVR4_EBADRPC, 12043412Snewton SVR4_ERPCMISMATCH, 12143412Snewton SVR4_EPROGUNAVAIL, 12243412Snewton SVR4_EPROGMISMATCH, 12343412Snewton SVR4_EPROCUNAVAIL, 12443412Snewton SVR4_ENOLCK, 12543412Snewton SVR4_ENOSYS, 12643412Snewton SVR4_EFTYPE, 12743412Snewton SVR4_EAUTH, 12843412Snewton SVR4_ENEEDAUTH, 12943412Snewton SVR4_EIDRM, 13043412Snewton SVR4_ENOMSG, 13143412Snewton}; 13243412Snewton 13343412Snewton 13443412Snewtonstatic int svr4_fixup(long **stack_base, struct image_params *imgp); 13543412Snewton 13643412Snewtonextern struct sysent svr4_sysent[]; 13743412Snewton#undef szsigcode 13843412Snewton#undef sigcode 13943412Snewton 14043412Snewtonextern int svr4_szsigcode; 14143412Snewtonextern char svr4_sigcode[]; 14243412Snewton 14343412Snewtonstruct sysentvec svr4_sysvec = { 14443412Snewton SVR4_SYS_MAXSYSCALL, 14543412Snewton svr4_sysent, 14643412Snewton 0xff, 14743412Snewton NSIG, 14843412Snewton bsd_to_svr4_sig, 14943412Snewton ELAST, /* ELAST */ 15043412Snewton bsd_to_svr4_errno, 15143412Snewton 0, 15243412Snewton svr4_fixup, 15343412Snewton svr4_sendsig, 15443412Snewton svr4_sigcode, 15543412Snewton &svr4_szsigcode, 15643412Snewton 0, 15743412Snewton "SVR4" 15843412Snewton}; 15943412Snewton 16043412SnewtonElf32_Brandinfo svr4_brand = { 16143412Snewton "SVR4", 16243412Snewton "/compat/svr4", 16343412Snewton "/lib/libc.so.1", 16443412Snewton &svr4_sysvec 16543412Snewton}; 16643412Snewton 16743412Snewtonconst char svr4_emul_path[] = "/compat/svr4"; 16843412Snewton 16943412Snewtonstatic int 17043412Snewtonsvr4_fixup(long **stack_base, struct image_params *imgp) 17143412Snewton{ 17243412Snewton Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 17343412Snewton long *pos; 17443412Snewton 17543412Snewton pos = *stack_base + (imgp->argc + imgp->envc + 2); 17643412Snewton 17743412Snewton if (args->trace) { 17843412Snewton AUXARGS_ENTRY(pos, AT_DEBUG, 1); 17943412Snewton } 18043412Snewton if (args->execfd != -1) { 18143412Snewton AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 18243412Snewton } 18343412Snewton AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 18443412Snewton AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 18543412Snewton AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 18643412Snewton AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 18743412Snewton AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 18843412Snewton AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 18943412Snewton AUXARGS_ENTRY(pos, AT_BASE, args->base); 19043412Snewton AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); 19143412Snewton AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); 19243412Snewton AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); 19343412Snewton AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); 19443412Snewton AUXARGS_ENTRY(pos, AT_NULL, 0); 19543412Snewton 19643412Snewton free(imgp->auxargs, M_TEMP); 19743412Snewton imgp->auxargs = NULL; 19843412Snewton 19943412Snewton (*stack_base)--; 20043412Snewton **stack_base = (int)imgp->argc; 20143412Snewton return 0; 20243412Snewton} 20343412Snewton 20443412Snewton/* 20543412Snewton * Search an alternate path before passing pathname arguments on 20643412Snewton * to system calls. Useful for keeping a seperate 'emulation tree'. 20743412Snewton * 20843412Snewton * If cflag is set, we check if an attempt can be made to create 20943412Snewton * the named file, i.e. we check if the directory it should 21043412Snewton * be in exists. 21143412Snewton * 21243412Snewton * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. 21343412Snewton */ 21443412Snewtonint 21543412Snewtonsvr4_emul_find(p, sgp, prefix, path, pbuf, cflag) 21643412Snewton struct proc *p; 21743412Snewton caddr_t *sgp; /* Pointer to stackgap memory */ 21843412Snewton const char *prefix; 21943412Snewton char *path; 22043412Snewton char **pbuf; 22143412Snewton int cflag; 22243412Snewton{ 22343412Snewton struct nameidata nd; 22443412Snewton struct nameidata ndroot; 22543412Snewton struct vattr vat; 22643412Snewton struct vattr vatroot; 22743412Snewton int error; 22843412Snewton char *ptr, *buf, *cp; 22943412Snewton size_t sz, len; 23043412Snewton 23143412Snewton buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 23243412Snewton *pbuf = path; 23343412Snewton 23443412Snewton for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 23543412Snewton continue; 23643412Snewton 23743412Snewton sz = MAXPATHLEN - (ptr - buf); 23843412Snewton 23943412Snewton /* 24043412Snewton * If sgp is not given then the path is already in kernel space 24143412Snewton */ 24243412Snewton if (sgp == NULL) 24343412Snewton error = copystr(path, ptr, sz, &len); 24443412Snewton else 24543412Snewton error = copyinstr(path, ptr, sz, &len); 24643412Snewton 24743412Snewton if (error) { 24843412Snewton free(buf, M_TEMP); 24943412Snewton return error; 25043412Snewton } 25143412Snewton 25243412Snewton if (*ptr != '/') { 25343412Snewton free(buf, M_TEMP); 25443412Snewton return EINVAL; 25543412Snewton } 25643412Snewton 25743412Snewton /* 25843412Snewton * We know that there is a / somewhere in this pathname. 25943412Snewton * Search backwards for it, to find the file's parent dir 26043412Snewton * to see if it exists in the alternate tree. If it does, 26143412Snewton * and we want to create a file (cflag is set). We don't 26243412Snewton * need to worry about the root comparison in this case. 26343412Snewton */ 26443412Snewton 26543412Snewton if (cflag) { 26643412Snewton for (cp = &ptr[len] - 1; *cp != '/'; cp--); 26743412Snewton *cp = '\0'; 26843412Snewton 26943412Snewton NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); 27043412Snewton 27143412Snewton if ((error = namei(&nd)) != 0) { 27243412Snewton free(buf, M_TEMP); 27343412Snewton return error; 27443412Snewton } 27543412Snewton 27643412Snewton *cp = '/'; 27743412Snewton } 27843412Snewton else { 27943412Snewton NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); 28043412Snewton 28143412Snewton if ((error = namei(&nd)) != 0) { 28243412Snewton free(buf, M_TEMP); 28343412Snewton return error; 28443412Snewton } 28543412Snewton 28643412Snewton /* 28743412Snewton * We now compare the vnode of the svr4_root to the one 28843412Snewton * vnode asked. If they resolve to be the same, then we 28943412Snewton * ignore the match so that the real root gets used. 29043412Snewton * This avoids the problem of traversing "../.." to find the 29143412Snewton * root directory and never finding it, because "/" resolves 29243412Snewton * to the emulation root directory. This is expensive :-( 29343412Snewton */ 29443412Snewton NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, 29543412Snewton p); 29643412Snewton 29743412Snewton if ((error = namei(&ndroot)) != 0) { 29843412Snewton /* Cannot happen! */ 29943412Snewton free(buf, M_TEMP); 30043412Snewton vrele(nd.ni_vp); 30143412Snewton return error; 30243412Snewton } 30343412Snewton 30443412Snewton if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) { 30543412Snewton goto done; 30643412Snewton } 30743412Snewton 30843412Snewton if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p)) 30943412Snewton != 0) { 31043412Snewton goto done; 31143412Snewton } 31243412Snewton 31343412Snewton if (vat.va_fsid == vatroot.va_fsid && 31443412Snewton vat.va_fileid == vatroot.va_fileid) { 31543412Snewton error = ENOENT; 31643412Snewton goto done; 31743412Snewton } 31843412Snewton 31943412Snewton } 32043412Snewton if (sgp == NULL) 32143412Snewton *pbuf = buf; 32243412Snewton else { 32343412Snewton sz = &ptr[len] - buf; 32443412Snewton *pbuf = stackgap_alloc(sgp, sz + 1); 32543412Snewton error = copyout(buf, *pbuf, sz); 32643412Snewton free(buf, M_TEMP); 32743412Snewton } 32843412Snewton 32943412Snewton 33043412Snewtondone: 33143412Snewton vrele(nd.ni_vp); 33243412Snewton if (!cflag) 33343412Snewton vrele(ndroot.ni_vp); 33443412Snewton return error; 33543412Snewton} 33643412Snewton 33743412Snewton/* 33843412Snewton * XXX: wrong, for the same reason described in linux_sysvec.c 33943412Snewton */ 34043412Snewtonstatic int svr4_elf_modevent __P((module_t mod, int type, void *data)); 34143412Snewton 34243412Snewtonstatic int 34343412Snewtonsvr4_elf_modevent(module_t mod, int type, void *data) 34443412Snewton{ 34543412Snewton int error; 34643412Snewton 34743412Snewton error = 0; 34843412Snewton 34943412Snewton switch(type) { 35043412Snewton case MOD_LOAD: 35143412Snewton if (elf_insert_brand_entry(&svr4_brand) < 0) 35243412Snewton error = EINVAL; 35343412Snewton if (error) 35443412Snewton printf("cannot insert svr4 elf brand handler\n"); 35543412Snewton else if (bootverbose) 35643412Snewton printf("svr4 ELF exec handler installed\n"); 35743412Snewton break; 35843412Snewton case MOD_UNLOAD: 35943597Snewton /* Only allow the emulator to be removed if it isn't in use. */ 36043597Snewton if (elf_brand_inuse(&svr4_brand) != 0) { 36143597Snewton error = EBUSY; 36243597Snewton } else if (elf_remove_brand_entry(&svr4_brand) < 0) { 36343412Snewton error = EINVAL; 36443597Snewton } 36543597Snewton 36643412Snewton if (error) 36743597Snewton printf("Could not deinstall ELF interpreter entry (error %d)\n", 36843597Snewton error); 36943412Snewton else if (bootverbose) 37043412Snewton printf("svr4 ELF exec handler removed\n"); 37143412Snewton break; 37243412Snewton default: 37343412Snewton break; 37443412Snewton } 37543412Snewton return error; 37643412Snewton} 37743412Snewton 37843412Snewtonstatic moduledata_t svr4_elf_mod = { 37943412Snewton "svr4elf", 38043412Snewton svr4_elf_modevent, 38143412Snewton 0 38243412Snewton}; 38343412SnewtonDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 384