svr4_sysvec.c revision 116174
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 */
3049267Snewton
31116174Sobrien#include <sys/cdefs.h>
32116174Sobrien__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_sysvec.c 116174 2003-06-10 21:44:29Z obrien $");
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,
192102808Sjake  exec_setregs
19343412Snewton};
19443412Snewton
19543412SnewtonElf32_Brandinfo svr4_brand = {
19699669Srobert  ELFOSABI_SYSV,
197100384Speter  EM_386,			/* XXX only implemented for x86 so far. */
19872999Sobrien  "SVR4",
19959342Sobrien  svr4_emul_path,
20043412Snewton  "/lib/libc.so.1",
20143412Snewton  &svr4_sysvec
20243412Snewton};
20343412Snewton
20443412Snewtonconst char      svr4_emul_path[] = "/compat/svr4";
20543412Snewton
20643412Snewtonstatic int
20759342Sobriensvr4_fixup(register_t **stack_base, struct image_params *imgp)
20843412Snewton{
209112470Sjhb	Elf32_Auxargs *args;
21059342Sobrien	register_t *pos;
21143412Snewton
212112470Sjhb	KASSERT(curthread->td_proc == imgp->proc &&
213112470Sjhb	    (curthread->td_proc->p_flag & P_THREADED) == 0,
214112470Sjhb	    ("unsafe svr4_fixup(), should be curproc"));
215112470Sjhb	args = (Elf32_Auxargs *)imgp->auxargs;
21643412Snewton	pos = *stack_base + (imgp->argc + imgp->envc + 2);
21743412Snewton
218112470Sjhb	if (args->trace)
21943412Snewton		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
220112470Sjhb	if (args->execfd != -1)
22143412Snewton		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
22243412Snewton	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
22343412Snewton	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
22443412Snewton	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
22543412Snewton	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
22643412Snewton	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
22743412Snewton	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
22843412Snewton	AUXARGS_ENTRY(pos, AT_BASE, args->base);
22977183Srwatson	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
23077183Srwatson	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
23177183Srwatson	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
23277183Srwatson	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
23343412Snewton	AUXARGS_ENTRY(pos, AT_NULL, 0);
23443412Snewton
23543412Snewton	free(imgp->auxargs, M_TEMP);
23643412Snewton	imgp->auxargs = NULL;
23743412Snewton
23843412Snewton	(*stack_base)--;
239112470Sjhb	**stack_base = (register_t)imgp->argc;
24043412Snewton	return 0;
24143412Snewton}
24243412Snewton
24343412Snewton/*
24443412Snewton * Search an alternate path before passing pathname arguments on
24572091Sasmodai * to system calls. Useful for keeping a separate 'emulation tree'.
24643412Snewton *
24743412Snewton * If cflag is set, we check if an attempt can be made to create
24843412Snewton * the named file, i.e. we check if the directory it should
24943412Snewton * be in exists.
25043412Snewton *
25143412Snewton * Code shamelessly stolen by Mark Newton from IBCS2 emulation code.
25243412Snewton */
25343412Snewtonint
25483366Sjuliansvr4_emul_find(td, sgp, prefix, path, pbuf, cflag)
25583366Sjulian	struct thread	 *td;
25643412Snewton	caddr_t		 *sgp;		/* Pointer to stackgap memory */
25743412Snewton	const char	 *prefix;
25843412Snewton	char		 *path;
25943412Snewton	char		**pbuf;
26043412Snewton	int		  cflag;
26143412Snewton{
26243412Snewton	struct nameidata	 nd;
26343412Snewton	struct nameidata	 ndroot;
26443412Snewton	struct vattr		 vat;
26543412Snewton	struct vattr		 vatroot;
26643412Snewton	int			 error;
26743412Snewton	char			*ptr, *buf, *cp;
26843412Snewton	size_t			 sz, len;
26943412Snewton
270111119Simp	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
27143412Snewton	*pbuf = path;
27243412Snewton
27343412Snewton	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
27443412Snewton		continue;
27543412Snewton
27643412Snewton	sz = MAXPATHLEN - (ptr - buf);
27743412Snewton
27843412Snewton	/*
27943412Snewton	 * If sgp is not given then the path is already in kernel space
28043412Snewton	 */
28143412Snewton	if (sgp == NULL)
28243412Snewton		error = copystr(path, ptr, sz, &len);
28343412Snewton	else
28443412Snewton		error = copyinstr(path, ptr, sz, &len);
28543412Snewton
28643412Snewton	if (error) {
28743412Snewton		free(buf, M_TEMP);
28843412Snewton		return error;
28943412Snewton	}
29043412Snewton
29143412Snewton	if (*ptr != '/') {
29243412Snewton		free(buf, M_TEMP);
29343412Snewton		return EINVAL;
29443412Snewton	}
29543412Snewton
29643412Snewton	/*
29743412Snewton	 * We know that there is a / somewhere in this pathname.
29843412Snewton	 * Search backwards for it, to find the file's parent dir
29943412Snewton	 * to see if it exists in the alternate tree. If it does,
30043412Snewton	 * and we want to create a file (cflag is set). We don't
30143412Snewton	 * need to worry about the root comparison in this case.
30243412Snewton	 */
30343412Snewton
30443412Snewton	if (cflag) {
30543412Snewton		for (cp = &ptr[len] - 1; *cp != '/'; cp--);
30643412Snewton		*cp = '\0';
30743412Snewton
30883366Sjulian		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
30943412Snewton
31043412Snewton		if ((error = namei(&nd)) != 0) {
31143412Snewton			free(buf, M_TEMP);
31243412Snewton			return error;
31343412Snewton		}
31454655Seivind		NDFREE(&nd, NDF_ONLY_PNBUF);
31543412Snewton
31643412Snewton		*cp = '/';
31743412Snewton	}
31843412Snewton	else {
31983366Sjulian		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
32043412Snewton
32143412Snewton		if ((error = namei(&nd)) != 0) {
32243412Snewton			free(buf, M_TEMP);
32343412Snewton			return error;
32443412Snewton		}
32554655Seivind		NDFREE(&nd, NDF_ONLY_PNBUF);
32643412Snewton
32743412Snewton		/*
32843412Snewton		 * We now compare the vnode of the svr4_root to the one
32943412Snewton		 * vnode asked. If they resolve to be the same, then we
33043412Snewton		 * ignore the match so that the real root gets used.
33143412Snewton		 * This avoids the problem of traversing "../.." to find the
33243412Snewton		 * root directory and never finding it, because "/" resolves
33343412Snewton		 * to the emulation root directory. This is expensive :-(
33443412Snewton		 */
33543412Snewton		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path,
33683366Sjulian		       td);
33743412Snewton
33843412Snewton		if ((error = namei(&ndroot)) != 0) {
33943412Snewton			/* Cannot happen! */
34043412Snewton			free(buf, M_TEMP);
34143412Snewton			vrele(nd.ni_vp);
34243412Snewton			return error;
34343412Snewton		}
34454655Seivind		NDFREE(&ndroot, NDF_ONLY_PNBUF);
34543412Snewton
34691406Sjhb		if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) {
34743412Snewton			goto done;
34843412Snewton		}
34943412Snewton
35091406Sjhb		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td))
35171697Sjhb		    != 0) {
35243412Snewton			goto done;
35343412Snewton		}
35443412Snewton
35543412Snewton		if (vat.va_fsid == vatroot.va_fsid &&
35643412Snewton		    vat.va_fileid == vatroot.va_fileid) {
35743412Snewton			error = ENOENT;
35843412Snewton			goto done;
35943412Snewton		}
36043412Snewton
36143412Snewton	}
36243412Snewton	if (sgp == NULL)
36343412Snewton		*pbuf = buf;
36443412Snewton	else {
36543412Snewton		sz = &ptr[len] - buf;
36643412Snewton		*pbuf = stackgap_alloc(sgp, sz + 1);
36743412Snewton		error = copyout(buf, *pbuf, sz);
36843412Snewton		free(buf, M_TEMP);
36943412Snewton	}
37043412Snewton
37143412Snewton
37243412Snewtondone:
37343412Snewton	vrele(nd.ni_vp);
37443412Snewton	if (!cflag)
37543412Snewton		vrele(ndroot.ni_vp);
37643412Snewton	return error;
37743412Snewton}
37843412Snewton
37943412Snewtonstatic int
38043412Snewtonsvr4_elf_modevent(module_t mod, int type, void *data)
38143412Snewton{
38243412Snewton	int error;
38343412Snewton
38443412Snewton	error = 0;
38543412Snewton
38643412Snewton	switch(type) {
38743412Snewton	case MOD_LOAD:
388100384Speter		if (elf32_insert_brand_entry(&svr4_brand) < 0)
38943412Snewton			error = EINVAL;
39043412Snewton		if (error)
39143412Snewton			printf("cannot insert svr4 elf brand handler\n");
39243412Snewton		else if (bootverbose)
39343412Snewton			printf("svr4 ELF exec handler installed\n");
39443412Snewton		break;
39543412Snewton	case MOD_UNLOAD:
39643597Snewton		/* Only allow the emulator to be removed if it isn't in use. */
397100384Speter		if (elf32_brand_inuse(&svr4_brand) != 0) {
39843597Snewton			error = EBUSY;
399100384Speter		} else if (elf32_remove_brand_entry(&svr4_brand) < 0) {
40043412Snewton			error = EINVAL;
40143597Snewton		}
40243597Snewton
40343412Snewton		if (error)
40443597Snewton			printf("Could not deinstall ELF interpreter entry (error %d)\n",
40543597Snewton			       error);
40643412Snewton		else if (bootverbose)
40743412Snewton			printf("svr4 ELF exec handler removed\n");
40843412Snewton		break;
40943412Snewton	default:
41043412Snewton		break;
41143412Snewton	}
41243412Snewton	return error;
41343412Snewton}
41443412Snewton
41543412Snewtonstatic moduledata_t svr4_elf_mod = {
41643412Snewton	"svr4elf",
41743412Snewton	svr4_elf_modevent,
41843412Snewton	0
41943412Snewton};
42043412SnewtonDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
42160060SgreenMODULE_DEPEND(svr4elf, streams, 1, 1, 1);
422