svr4_sysvec.c revision 139743
1139743Simp/*-
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 139743 2005-01-05 22:34:37Z imp $");
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