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