svr4_sysvec.c revision 177785
1167465Smp/*-
259243Sobrien * Copyright (c) 1998 Mark Newton
359243Sobrien * All rights reserved.
459243Sobrien *
559243Sobrien * Redistribution and use in source and binary forms, with or without
659243Sobrien * modification, are permitted provided that the following conditions
759243Sobrien * are met:
859243Sobrien * 1. Redistributions of source code must retain the above copyright
959243Sobrien *    notice, this list of conditions and the following disclaimer.
1059243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1159243Sobrien *    notice, this list of conditions and the following disclaimer in the
1259243Sobrien *    documentation and/or other materials provided with the distribution.
1359243Sobrien * 3. All advertising materials mentioning features or use of this software
1459243Sobrien *    must display the following acknowledgement:
1559243Sobrien *      This product includes software developed by Christos Zoulas.
1659243Sobrien * 4. The name of the author may not be used to endorse or promote products
17100616Smp *    derived from this software without specific prior written permission.
1859243Sobrien *
1959243Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2059243Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2159243Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2259243Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2359243Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2459243Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2559243Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2659243Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2759243Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2859243Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2959243Sobrien */
3059243Sobrien
3159243Sobrien#include <sys/cdefs.h>
3259243Sobrien__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_sysvec.c 177785 2008-03-31 12:01:21Z kib $");
3359243Sobrien
3459243Sobrien/* XXX we use functions that might not exist. */
35167465Smp#include "opt_compat.h"
3659243Sobrien
3759243Sobrien#ifndef COMPAT_43
3859243Sobrien#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!"
3959243Sobrien#endif
4059243Sobrien
4169408Sache#include <sys/param.h>
4259243Sobrien#include <sys/systm.h>
43167465Smp#include <sys/proc.h>
44167465Smp#include <sys/sysent.h>
4569408Sache#include <sys/imgact.h>
4659243Sobrien#include <sys/imgact_elf.h>
4759243Sobrien#include <sys/fcntl.h>
4859243Sobrien#include <sys/lock.h>
4959243Sobrien#include <sys/malloc.h>
5059243Sobrien#include <sys/module.h>
5159243Sobrien#include <sys/mutex.h>
5259243Sobrien#include <sys/namei.h>
5359243Sobrien#include <sys/socket.h>
5459243Sobrien#include <sys/syscallsubr.h>
5559243Sobrien#include <sys/vnode.h>
5659243Sobrien#include <vm/vm.h>
5759243Sobrien#include <sys/exec.h>
58145479Smp#include <sys/kernel.h>
59145479Smp#include <machine/cpu.h>
60145479Smp#include <netinet/in.h>
61145479Smp
62145479Smp#include <compat/svr4/svr4.h>
63145479Smp#include <compat/svr4/svr4_types.h>
64167465Smp#include <compat/svr4/svr4_syscall.h>
6559243Sobrien#include <compat/svr4/svr4_signal.h>
66167465Smp#include <compat/svr4/svr4_socket.h>
67167465Smp#include <compat/svr4/svr4_sockio.h>
68167465Smp#include <compat/svr4/svr4_errno.h>
6959243Sobrien#include <compat/svr4/svr4_proto.h>
70167465Smp#include <compat/svr4/svr4_siginfo.h>
71167465Smp#include <compat/svr4/svr4_util.h>
72167465Smp
7359243Sobrienint bsd_to_svr4_errno[ELAST+1] = {
74167465Smp        0,
75167465Smp        SVR4_EPERM,
7659243Sobrien        SVR4_ENOENT,
77167465Smp        SVR4_ESRCH,
78167465Smp        SVR4_EINTR,
7959243Sobrien        SVR4_EIO,
8059243Sobrien        SVR4_ENXIO,
8159243Sobrien        SVR4_E2BIG,
8259243Sobrien        SVR4_ENOEXEC,
8359243Sobrien        SVR4_EBADF,
8459243Sobrien        SVR4_ECHILD,
8559243Sobrien        SVR4_EDEADLK,
86167465Smp        SVR4_ENOMEM,
87167465Smp        SVR4_EACCES,
88167465Smp        SVR4_EFAULT,
8961524Sobrien        SVR4_ENOTBLK,
9061524Sobrien        SVR4_EBUSY,
9161524Sobrien        SVR4_EEXIST,
9261524Sobrien        SVR4_EXDEV,
9361524Sobrien        SVR4_ENODEV,
9459243Sobrien        SVR4_ENOTDIR,
9559243Sobrien        SVR4_EISDIR,
9659243Sobrien        SVR4_EINVAL,
9759243Sobrien        SVR4_ENFILE,
9859243Sobrien        SVR4_EMFILE,
99167465Smp        SVR4_ENOTTY,
10059243Sobrien        SVR4_ETXTBSY,
101167465Smp        SVR4_EFBIG,
102167465Smp        SVR4_ENOSPC,
103167465Smp        SVR4_ESPIPE,
104145479Smp        SVR4_EROFS,
105145479Smp        SVR4_EMLINK,
10659243Sobrien        SVR4_EPIPE,
10759243Sobrien        SVR4_EDOM,
10859243Sobrien        SVR4_ERANGE,
109167465Smp        SVR4_EAGAIN,
110167465Smp        SVR4_EINPROGRESS,
11159243Sobrien        SVR4_EALREADY,
112167465Smp        SVR4_ENOTSOCK,
11359243Sobrien        SVR4_EDESTADDRREQ,
114167465Smp        SVR4_EMSGSIZE,
11559243Sobrien        SVR4_EPROTOTYPE,
11659243Sobrien        SVR4_ENOPROTOOPT,
11759243Sobrien        SVR4_EPROTONOSUPPORT,
11859243Sobrien        SVR4_ESOCKTNOSUPPORT,
11959243Sobrien        SVR4_EOPNOTSUPP,
12059243Sobrien        SVR4_EPFNOSUPPORT,
12159243Sobrien        SVR4_EAFNOSUPPORT,
12259243Sobrien        SVR4_EADDRINUSE,
12359243Sobrien        SVR4_EADDRNOTAVAIL,
12459243Sobrien        SVR4_ENETDOWN,
125167465Smp        SVR4_ENETUNREACH,
12659243Sobrien        SVR4_ENETRESET,
127167465Smp        SVR4_ECONNABORTED,
12859243Sobrien        SVR4_ECONNRESET,
12959243Sobrien        SVR4_ENOBUFS,
130167465Smp        SVR4_EISCONN,
13159243Sobrien        SVR4_ENOTCONN,
13259243Sobrien        SVR4_ESHUTDOWN,
13359243Sobrien        SVR4_ETOOMANYREFS,
13459243Sobrien        SVR4_ETIMEDOUT,
13559243Sobrien        SVR4_ECONNREFUSED,
136167465Smp        SVR4_ELOOP,
137167465Smp        SVR4_ENAMETOOLONG,
13859243Sobrien        SVR4_EHOSTDOWN,
139167465Smp        SVR4_EHOSTUNREACH,
14059243Sobrien        SVR4_ENOTEMPTY,
14159243Sobrien        SVR4_EPROCLIM,
14259243Sobrien        SVR4_EUSERS,
143167465Smp        SVR4_EDQUOT,
14459243Sobrien        SVR4_ESTALE,
145167465Smp        SVR4_EREMOTE,
14659243Sobrien        SVR4_EBADRPC,
14759243Sobrien        SVR4_ERPCMISMATCH,
14859243Sobrien        SVR4_EPROGUNAVAIL,
14959243Sobrien        SVR4_EPROGMISMATCH,
150167465Smp        SVR4_EPROCUNAVAIL,
15159243Sobrien        SVR4_ENOLCK,
15259243Sobrien        SVR4_ENOSYS,
15359243Sobrien        SVR4_EFTYPE,
15459243Sobrien        SVR4_EAUTH,
15559243Sobrien        SVR4_ENEEDAUTH,
15659243Sobrien        SVR4_EIDRM,
15759243Sobrien        SVR4_ENOMSG,
15859243Sobrien};
15959243Sobrien
16059243Sobrien
16159243Sobrienstatic int 	svr4_fixup(register_t **stack_base, struct image_params *imgp);
162167465Smp
16359243Sobrienextern struct sysent svr4_sysent[];
16459243Sobrien#undef szsigcode
16559243Sobrien#undef sigcode
166167465Smp
16759243Sobrienextern int svr4_szsigcode;
16859243Sobrienextern char svr4_sigcode[];
16959243Sobrien
170167465Smpstruct sysentvec svr4_sysvec = {
17159243Sobrien  SVR4_SYS_MAXSYSCALL,
17259243Sobrien  svr4_sysent,
17359243Sobrien  0xff,
17459243Sobrien  SVR4_NSIG-1,		/* NB: signal trans table indexed with signno-1 */
17559243Sobrien  bsd_to_svr4_sig+1,
17659243Sobrien  ELAST,  /* ELAST */
17759243Sobrien  bsd_to_svr4_errno,
17859243Sobrien  NULL,
179167465Smp  svr4_fixup,
180167465Smp  svr4_sendsig,
181167465Smp  svr4_sigcode,
182167465Smp  &svr4_szsigcode,
18359243Sobrien  NULL,
18459243Sobrien  "SVR4",
18559243Sobrien  elf32_coredump,
18659243Sobrien  NULL,
187167465Smp  SVR4_MINSIGSTKSZ,
18859243Sobrien  PAGE_SIZE,
18959243Sobrien  VM_MIN_ADDRESS,
19059243Sobrien  VM_MAXUSER_ADDRESS,
19159243Sobrien  USRSTACK,
19259243Sobrien  PS_STRINGS,
193167465Smp  VM_PROT_ALL,
19459243Sobrien  exec_copyout_strings,
195167465Smp  exec_setregs,
19659243Sobrien  NULL
19759243Sobrien};
19859243Sobrien
19959243Sobrienconst char      svr4_emul_path[] = "/compat/svr4";
20059243Sobrien
201167465SmpElf32_Brandinfo svr4_brand = {
202167465Smp  ELFOSABI_SYSV,
203167465Smp  EM_386,			/* XXX only implemented for x86 so far. */
204167465Smp  "SVR4",
205167465Smp  svr4_emul_path,
206167465Smp  "/lib/libc.so.1",
20759243Sobrien  &svr4_sysvec,
20859243Sobrien  NULL,
209167465Smp};
210167465Smp
211167465Smpstatic int
21259243Sobriensvr4_fixup(register_t **stack_base, struct image_params *imgp)
21359243Sobrien{
21459243Sobrien	Elf32_Auxargs *args;
21559243Sobrien	register_t *pos;
21659243Sobrien
21759243Sobrien	KASSERT(curthread->td_proc == imgp->proc,
21859243Sobrien	    ("unsafe svr4_fixup(), should be curproc"));
21959243Sobrien	args = (Elf32_Auxargs *)imgp->auxargs;
22059243Sobrien	pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
22159243Sobrien
22259243Sobrien	if (args->trace)
22359243Sobrien		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
224167465Smp	if (args->execfd != -1)
225167465Smp		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
226167465Smp	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
227167465Smp	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
22859243Sobrien	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
229167465Smp	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
23059243Sobrien	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
23159243Sobrien	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
23259243Sobrien	AUXARGS_ENTRY(pos, AT_BASE, args->base);
23359243Sobrien	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
23459243Sobrien	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
23559243Sobrien	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
23659243Sobrien	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
23759243Sobrien	AUXARGS_ENTRY(pos, AT_NULL, 0);
238100616Smp
239100616Smp	free(imgp->auxargs, M_TEMP);
24059243Sobrien	imgp->auxargs = NULL;
24159243Sobrien
24259243Sobrien	(*stack_base)--;
24359243Sobrien	**stack_base = (register_t)imgp->args->argc;
24459243Sobrien	return 0;
24559243Sobrien}
24659243Sobrien
24759243Sobrien/*
24859243Sobrien * Search an alternate path before passing pathname arguments on
24959243Sobrien * to system calls. Useful for keeping a separate 'emulation tree'.
25059243Sobrien *
25159243Sobrien * If cflag is set, we check if an attempt can be made to create
25259243Sobrien * the named file, i.e. we check if the directory it should
25359243Sobrien * be in exists.
25459243Sobrien */
25559243Sobrienint
25659243Sobriensvr4_emul_find(struct thread *td, char *path, enum uio_seg pathseg,
25759243Sobrien    char **pbuf, int create)
25859243Sobrien{
25959243Sobrien
260167465Smp	return (kern_alternate_path(td, svr4_emul_path, path, pathseg, pbuf,
26159243Sobrien	    create));
26259243Sobrien}
26359243Sobrien
26459243Sobrienstatic int
265167465Smpsvr4_elf_modevent(module_t mod, int type, void *data)
26659243Sobrien{
26759243Sobrien	int error;
26859243Sobrien
26959243Sobrien	error = 0;
27059243Sobrien
27159243Sobrien	switch(type) {
272167465Smp	case MOD_LOAD:
27359243Sobrien		if (elf32_insert_brand_entry(&svr4_brand) < 0) {
27459243Sobrien			printf("cannot insert svr4 elf brand handler\n");
27559243Sobrien			error = EINVAL;
27659243Sobrien			break;
27759243Sobrien		}
27859243Sobrien		if (bootverbose)
27959243Sobrien			printf("svr4 ELF exec handler installed\n");
28059243Sobrien		svr4_sockcache_init();
281167465Smp		break;
28259243Sobrien	case MOD_UNLOAD:
28359243Sobrien		/* Only allow the emulator to be removed if it isn't in use. */
28459243Sobrien		if (elf32_brand_inuse(&svr4_brand) != 0) {
28559243Sobrien			error = EBUSY;
28659243Sobrien		} else if (elf32_remove_brand_entry(&svr4_brand) < 0) {
28759243Sobrien			error = EINVAL;
28859243Sobrien		}
289167465Smp
290100616Smp		if (error) {
29159243Sobrien			printf("Could not deinstall ELF interpreter entry (error %d)\n",
29259243Sobrien			       error);
29359243Sobrien			break;
29459243Sobrien		}
29559243Sobrien		if (bootverbose)
29659243Sobrien			printf("svr4 ELF exec handler removed\n");
297167465Smp		svr4_sockcache_destroy();
29859243Sobrien		break;
29959243Sobrien	default:
30059243Sobrien		return (EOPNOTSUPP);
301167465Smp		break;
30259243Sobrien	}
30359243Sobrien	return error;
30459243Sobrien}
30559243Sobrien
30659243Sobrienstatic moduledata_t svr4_elf_mod = {
307100616Smp	"svr4elf",
30859243Sobrien	svr4_elf_modevent,
309167465Smp	0
31059243Sobrien};
311167465SmpDECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
31259243SobrienMODULE_DEPEND(svr4elf, streams, 1, 1, 1);
31359243Sobrien