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