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