]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/compat/svr4/svr4_sysvec.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / compat / svr4 / svr4_sysvec.c
1 /*-
2  * Copyright (c) 1998 Mark Newton
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Christos Zoulas.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 /* XXX we use functions that might not exist. */
35 #include "opt_compat.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/proc.h>
40 #include <sys/sysent.h>
41 #include <sys/imgact.h>
42 #include <sys/imgact_elf.h>
43 #include <sys/fcntl.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
48 #include <sys/namei.h>
49 #include <sys/socket.h>
50 #include <sys/syscallsubr.h>
51 #include <sys/vnode.h>
52 #include <vm/vm.h>
53 #include <sys/exec.h>
54 #include <sys/kernel.h>
55 #include <machine/cpu.h>
56 #include <netinet/in.h>
57
58 #include <compat/svr4/svr4.h>
59 #include <compat/svr4/svr4_types.h>
60 #include <compat/svr4/svr4_syscall.h>
61 #include <compat/svr4/svr4_signal.h>
62 #include <compat/svr4/svr4_socket.h>
63 #include <compat/svr4/svr4_sockio.h>
64 #include <compat/svr4/svr4_errno.h>
65 #include <compat/svr4/svr4_proto.h>
66 #include <compat/svr4/svr4_siginfo.h>
67 #include <compat/svr4/svr4_util.h>
68
69 int bsd_to_svr4_errno[ELAST+1] = {
70         0,
71         SVR4_EPERM,
72         SVR4_ENOENT,
73         SVR4_ESRCH,
74         SVR4_EINTR,
75         SVR4_EIO,
76         SVR4_ENXIO,
77         SVR4_E2BIG,
78         SVR4_ENOEXEC,
79         SVR4_EBADF,
80         SVR4_ECHILD,
81         SVR4_EDEADLK,
82         SVR4_ENOMEM,
83         SVR4_EACCES,
84         SVR4_EFAULT,
85         SVR4_ENOTBLK,
86         SVR4_EBUSY,
87         SVR4_EEXIST,
88         SVR4_EXDEV,
89         SVR4_ENODEV,
90         SVR4_ENOTDIR,
91         SVR4_EISDIR,
92         SVR4_EINVAL,
93         SVR4_ENFILE,
94         SVR4_EMFILE,
95         SVR4_ENOTTY,
96         SVR4_ETXTBSY,
97         SVR4_EFBIG,
98         SVR4_ENOSPC,
99         SVR4_ESPIPE,
100         SVR4_EROFS,
101         SVR4_EMLINK,
102         SVR4_EPIPE,
103         SVR4_EDOM,
104         SVR4_ERANGE,
105         SVR4_EAGAIN,
106         SVR4_EINPROGRESS,
107         SVR4_EALREADY,
108         SVR4_ENOTSOCK,
109         SVR4_EDESTADDRREQ,
110         SVR4_EMSGSIZE,
111         SVR4_EPROTOTYPE,
112         SVR4_ENOPROTOOPT,
113         SVR4_EPROTONOSUPPORT,
114         SVR4_ESOCKTNOSUPPORT,
115         SVR4_EOPNOTSUPP,
116         SVR4_EPFNOSUPPORT,
117         SVR4_EAFNOSUPPORT,
118         SVR4_EADDRINUSE,
119         SVR4_EADDRNOTAVAIL,
120         SVR4_ENETDOWN,
121         SVR4_ENETUNREACH,
122         SVR4_ENETRESET,
123         SVR4_ECONNABORTED,
124         SVR4_ECONNRESET,
125         SVR4_ENOBUFS,
126         SVR4_EISCONN,
127         SVR4_ENOTCONN,
128         SVR4_ESHUTDOWN,
129         SVR4_ETOOMANYREFS,
130         SVR4_ETIMEDOUT,
131         SVR4_ECONNREFUSED,
132         SVR4_ELOOP,
133         SVR4_ENAMETOOLONG,
134         SVR4_EHOSTDOWN,
135         SVR4_EHOSTUNREACH,
136         SVR4_ENOTEMPTY,
137         SVR4_EPROCLIM,
138         SVR4_EUSERS,
139         SVR4_EDQUOT,
140         SVR4_ESTALE,
141         SVR4_EREMOTE,
142         SVR4_EBADRPC,
143         SVR4_ERPCMISMATCH,
144         SVR4_EPROGUNAVAIL,
145         SVR4_EPROGMISMATCH,
146         SVR4_EPROCUNAVAIL,
147         SVR4_ENOLCK,
148         SVR4_ENOSYS,
149         SVR4_EFTYPE,
150         SVR4_EAUTH,
151         SVR4_ENEEDAUTH,
152         SVR4_EIDRM,
153         SVR4_ENOMSG,
154 };
155
156
157 static int      svr4_fixup(register_t **stack_base, struct image_params *imgp);
158
159 extern struct sysent svr4_sysent[];
160 #undef szsigcode
161 #undef sigcode
162
163 extern int svr4_szsigcode;
164 extern char svr4_sigcode[];
165
166 struct sysentvec svr4_sysvec = {
167         .sv_size        = SVR4_SYS_MAXSYSCALL,
168         .sv_table       = svr4_sysent,
169         .sv_mask        = 0xff,
170         .sv_sigsize     = SVR4_NSIG-1, /* NB: signal trans table indexed with signno-1 */
171         .sv_sigtbl      = bsd_to_svr4_sig+1,
172         .sv_errsize     = ELAST,  /* ELAST */
173         .sv_errtbl      = bsd_to_svr4_errno,
174         .sv_transtrap   = NULL,
175         .sv_fixup       = svr4_fixup,
176         .sv_sendsig     = svr4_sendsig,
177         .sv_sigcode     = svr4_sigcode,
178         .sv_szsigcode   = &svr4_szsigcode,
179         .sv_prepsyscall = NULL,
180         .sv_name        = "SVR4",
181         .sv_coredump    = elf32_coredump,
182         .sv_imgact_try  = NULL,
183         .sv_minsigstksz = SVR4_MINSIGSTKSZ,
184         .sv_pagesize    = PAGE_SIZE,
185         .sv_minuser     = VM_MIN_ADDRESS,
186         .sv_maxuser     = VM_MAXUSER_ADDRESS,
187         .sv_usrstack    = USRSTACK,
188         .sv_psstrings   = PS_STRINGS,
189         .sv_stackprot   = VM_PROT_ALL,
190         .sv_copyout_strings = exec_copyout_strings,
191         .sv_setregs     = exec_setregs,
192         .sv_fixlimit    = NULL,
193         .sv_maxssiz     = NULL,
194         .sv_flags       = SV_ABI_UNDEF | SV_IA32 | SV_ILP32,
195         .sv_set_syscall_retval = cpu_set_syscall_retval,
196         .sv_fetch_syscall_args = cpu_fetch_syscall_args,
197         .sv_syscallnames = NULL,
198         .sv_schedtail   = NULL,
199 };
200
201 const char      svr4_emul_path[] = "/compat/svr4";
202
203 Elf32_Brandinfo svr4_brand = {
204         .brand          = ELFOSABI_SYSV,
205         .machine        = EM_386, /* XXX only implemented for x86 so far. */
206         .compat_3_brand = "SVR4",
207         .emul_path      = svr4_emul_path,
208         .interp_path    = "/lib/libc.so.1",
209         .sysvec         = &svr4_sysvec,
210         .interp_newpath = NULL,
211         .brand_note     = NULL,
212         .flags          = 0
213 };
214
215 static int
216 svr4_fixup(register_t **stack_base, struct image_params *imgp)
217 {
218         Elf32_Auxargs *args;
219         register_t *pos;
220              
221         KASSERT(curthread->td_proc == imgp->proc,
222             ("unsafe svr4_fixup(), should be curproc"));
223         args = (Elf32_Auxargs *)imgp->auxargs;
224         pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);  
225     
226         if (args->execfd != -1)
227                 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
228         AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
229         AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
230         AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
231         AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
232         AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
233         AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
234         AUXARGS_ENTRY(pos, AT_BASE, args->base);
235         AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
236         AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
237         AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
238         AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
239         AUXARGS_ENTRY(pos, AT_NULL, 0);
240         
241         free(imgp->auxargs, M_TEMP);      
242         imgp->auxargs = NULL;
243
244         (*stack_base)--;
245         **stack_base = (register_t)imgp->args->argc;
246         return 0;
247 }
248
249 /*
250  * Search an alternate path before passing pathname arguments on
251  * to system calls. Useful for keeping a separate 'emulation tree'.
252  *
253  * If cflag is set, we check if an attempt can be made to create
254  * the named file, i.e. we check if the directory it should
255  * be in exists.
256  */
257 int
258 svr4_emul_find(struct thread *td, char *path, enum uio_seg pathseg,
259     char **pbuf, int create)
260 {
261
262         return (kern_alternate_path(td, svr4_emul_path, path, pathseg, pbuf,
263             create, AT_FDCWD));
264 }
265
266 static int
267 svr4_elf_modevent(module_t mod, int type, void *data)
268 {
269         int error;
270
271         error = 0;
272
273         switch(type) {
274         case MOD_LOAD:
275                 if (elf32_insert_brand_entry(&svr4_brand) < 0) {
276                         printf("cannot insert svr4 elf brand handler\n");
277                         error = EINVAL;
278                         break;
279                 }
280                 if (bootverbose)
281                         printf("svr4 ELF exec handler installed\n");
282                 svr4_sockcache_init();
283                 break;
284         case MOD_UNLOAD:
285                 /* Only allow the emulator to be removed if it isn't in use. */
286                 if (elf32_brand_inuse(&svr4_brand) != 0) {
287                         error = EBUSY;
288                 } else if (elf32_remove_brand_entry(&svr4_brand) < 0) {
289                         error = EINVAL;
290                 }
291
292                 if (error) {
293                         printf("Could not deinstall ELF interpreter entry (error %d)\n",
294                                error);
295                         break;
296                 }
297                 if (bootverbose)
298                         printf("svr4 ELF exec handler removed\n");
299                 svr4_sockcache_destroy();
300                 break;
301         default:
302                 return (EOPNOTSUPP);
303                 break;
304         }
305         return error;
306 }
307
308 static moduledata_t svr4_elf_mod = {
309         "svr4elf",
310         svr4_elf_modevent,
311         0
312 };
313 DECLARE_MODULE_TIED(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
314 MODULE_DEPEND(svr4elf, streams, 1, 1, 1);