Catch up with reality, this is GCC 3.4.4.
[dragonfly.git] / sys / emulation / 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  * $FreeBSD: src/sys/svr4/svr4_sysvec.c,v 1.10.2.2 2002/07/09 14:12:43 robert Exp $
31  * $DragonFly: src/sys/emulation/svr4/Attic/svr4_sysvec.c,v 1.13 2005/06/01 16:51:46 joerg Exp $
32  */
33
34 /* XXX we use functions that might not exist. */
35 #include "opt_compat.h"
36
37 #ifndef COMPAT_43
38 #error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!"
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/buf.h>
44 #include <sys/proc.h>
45 #include <sys/sysent.h>
46 #include <sys/imgact.h>
47 #include <sys/imgact_elf.h>
48 #include <sys/socket.h>
49 #include <sys/malloc.h>
50 #include <sys/nlookup.h>
51 #include <sys/vnode.h>
52 #include <sys/module.h>
53 #include <vm/vm.h>
54 #include <vm/vm_zone.h>
55 #include <sys/exec.h>
56 #include <sys/kernel.h>
57 #include <machine/cpu.h>
58 #include <netinet/in.h>
59
60 #include <emulation/43bsd/43bsd_socket.h>
61
62 #include "svr4.h"
63 #include "svr4_types.h"
64 #include "svr4_syscall.h"
65 #include "svr4_signal.h"
66 #include "svr4_sockio.h"
67 #include "svr4_socket.h"
68 #include "svr4_errno.h"
69 #include "svr4_proto.h"
70 #include "svr4_siginfo.h"
71 #include "svr4_util.h"
72
73 int bsd_to_svr4_errno[ELAST+1] = {
74         0,
75         SVR4_EPERM,
76         SVR4_ENOENT,
77         SVR4_ESRCH,
78         SVR4_EINTR,
79         SVR4_EIO,
80         SVR4_ENXIO,
81         SVR4_E2BIG,
82         SVR4_ENOEXEC,
83         SVR4_EBADF,
84         SVR4_ECHILD,
85         SVR4_EDEADLK,
86         SVR4_ENOMEM,
87         SVR4_EACCES,
88         SVR4_EFAULT,
89         SVR4_ENOTBLK,
90         SVR4_EBUSY,
91         SVR4_EEXIST,
92         SVR4_EXDEV,
93         SVR4_ENODEV,
94         SVR4_ENOTDIR,
95         SVR4_EISDIR,
96         SVR4_EINVAL,
97         SVR4_ENFILE,
98         SVR4_EMFILE,
99         SVR4_ENOTTY,
100         SVR4_ETXTBSY,
101         SVR4_EFBIG,
102         SVR4_ENOSPC,
103         SVR4_ESPIPE,
104         SVR4_EROFS,
105         SVR4_EMLINK,
106         SVR4_EPIPE,
107         SVR4_EDOM,
108         SVR4_ERANGE,
109         SVR4_EAGAIN,
110         SVR4_EINPROGRESS,
111         SVR4_EALREADY,
112         SVR4_ENOTSOCK,
113         SVR4_EDESTADDRREQ,
114         SVR4_EMSGSIZE,
115         SVR4_EPROTOTYPE,
116         SVR4_ENOPROTOOPT,
117         SVR4_EPROTONOSUPPORT,
118         SVR4_ESOCKTNOSUPPORT,
119         SVR4_EOPNOTSUPP,
120         SVR4_EPFNOSUPPORT,
121         SVR4_EAFNOSUPPORT,
122         SVR4_EADDRINUSE,
123         SVR4_EADDRNOTAVAIL,
124         SVR4_ENETDOWN,
125         SVR4_ENETUNREACH,
126         SVR4_ENETRESET,
127         SVR4_ECONNABORTED,
128         SVR4_ECONNRESET,
129         SVR4_ENOBUFS,
130         SVR4_EISCONN,
131         SVR4_ENOTCONN,
132         SVR4_ESHUTDOWN,
133         SVR4_ETOOMANYREFS,
134         SVR4_ETIMEDOUT,
135         SVR4_ECONNREFUSED,
136         SVR4_ELOOP,
137         SVR4_ENAMETOOLONG,
138         SVR4_EHOSTDOWN,
139         SVR4_EHOSTUNREACH,
140         SVR4_ENOTEMPTY,
141         SVR4_EPROCLIM,
142         SVR4_EUSERS,
143         SVR4_EDQUOT,
144         SVR4_ESTALE,
145         SVR4_EREMOTE,
146         SVR4_EBADRPC,
147         SVR4_ERPCMISMATCH,
148         SVR4_EPROGUNAVAIL,
149         SVR4_EPROGMISMATCH,
150         SVR4_EPROCUNAVAIL,
151         SVR4_ENOLCK,
152         SVR4_ENOSYS,
153         SVR4_EFTYPE,
154         SVR4_EAUTH,
155         SVR4_ENEEDAUTH,
156         SVR4_EIDRM,
157         SVR4_ENOMSG,
158 };
159
160
161 static int      svr4_fixup(register_t **stack_base, struct image_params *imgp);
162
163 extern struct sysent svr4_sysent[];
164 #undef szsigcode
165 #undef sigcode
166
167 extern int svr4_szsigcode;
168 extern char svr4_sigcode[];
169
170 struct sysentvec svr4_sysvec = {
171   SVR4_SYS_MAXSYSCALL,
172   svr4_sysent,
173   0xff,
174   SVR4_SIGTBLSZ,
175   bsd_to_svr4_sig,
176   ELAST,  /* ELAST */
177   bsd_to_svr4_errno,
178   0,
179   svr4_fixup,
180   svr4_sendsig,
181   svr4_sigcode,
182   &svr4_szsigcode,
183   NULL,
184   "SVR4",
185   elf_coredump,
186   NULL,
187   SVR4_MINSIGSTKSZ
188 };
189
190 Elf32_Brandinfo svr4_brand = {
191   ELFOSABI_SYSV,
192   "SVR4",
193   NULL, /* Keep this, otherwise SYSV binaries are undetectable! */
194   "/compat/svr4",
195   "/lib/libc.so.1",
196   &svr4_sysvec
197 };
198
199 const char      svr4_emul_path[] = "/compat/svr4";
200
201 static int
202 svr4_fixup(register_t **stack_base, struct image_params *imgp)
203 {
204         Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
205         register_t *pos;
206              
207         pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);  
208     
209         if (args->trace) {
210                 AUXARGS_ENTRY(pos, AT_DEBUG, 1);
211         }
212         if (args->execfd != -1) {
213                 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
214         }       
215         AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
216         AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
217         AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
218         AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
219         AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
220         AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
221         AUXARGS_ENTRY(pos, AT_BASE, args->base);
222         AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
223         AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
224         AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
225         AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
226         AUXARGS_ENTRY(pos, AT_NULL, 0);
227         
228         free(imgp->auxargs, M_TEMP);      
229         imgp->auxargs = NULL;
230
231         (*stack_base)--;
232         **stack_base = (int)imgp->args->argc;
233         return 0;
234 }
235
236 /*
237  * Search an alternate path before passing pathname arguments on
238  * to system calls. Useful for keeping a separate 'emulation tree'.
239  *
240  * If cflag is set, we check if an attempt can be made to create
241  * the named file, i.e. we check if the directory it should
242  * be in exists.
243  *
244  * Code shamelessly stolen by Mark Newton from IBCS2 emulation code.
245  */
246 int
247 svr4_emul_find(sgp, prefix, path, pbuf, cflag)
248         caddr_t          *sgp;          /* Pointer to stackgap memory */
249         const char       *prefix;
250         char             *path;
251         char            **pbuf;
252         int               cflag;
253 {
254         struct thread *td = curthread;  /* XXX */
255         struct nlookupdata       nd;
256         struct nlookupdata       ndroot;
257         struct vattr             vat;
258         struct vattr             vatroot;
259         struct vnode            *vp;
260         int                      error;
261         char                    *ptr, *buf, *cp;
262         size_t                   sz, len;
263         struct ucred *cred;
264
265         KKASSERT(td->td_proc);
266         cred = td->td_proc->p_ucred;
267
268         buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
269         *pbuf = path;
270
271         for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
272                 continue;
273
274         sz = MAXPATHLEN - (ptr - buf);
275
276         /* 
277          * If sgp is not given then the path is already in kernel space
278          */
279         if (sgp == NULL)
280                 error = copystr(path, ptr, sz, &len);
281         else
282                 error = copyinstr(path, ptr, sz, &len);
283
284         if (error) {
285                 free(buf, M_TEMP);
286                 return error;
287         }
288
289         if (*ptr != '/') {
290                 free(buf, M_TEMP);
291                 return EINVAL;
292         }
293
294         /*
295          * We know that there is a / somewhere in this pathname.
296          * Search backwards for it, to find the file's parent dir
297          * to see if it exists in the alternate tree. If it does,
298          * and we want to create a file (cflag is set). We don't
299          * need to worry about the root comparison in this case.
300          */
301
302         if (cflag) {
303                 for (cp = &ptr[len] - 1; *cp != '/'; cp--);
304                 *cp = '\0';
305
306                 error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_FOLLOW);
307                 if (error == 0)
308                         error = nlookup(&nd);
309                 nlookup_done(&nd);
310                 if (error) {
311                         free(buf, M_TEMP);
312                         return (error);
313                 }
314                 *cp = '/';
315         } else {
316                 error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_FOLLOW);
317                 if (error == 0)
318                         error = nlookup(&nd);
319                 vp = NULL;
320                 if (error == 0)
321                         error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
322                 nlookup_done(&nd);
323                 if (error) {
324                         free(buf, M_TEMP);
325                         return (error);
326                 }
327                 error = VOP_GETATTR(vp, &vat, td);
328                 vrele(vp);
329                 if (error)
330                         goto done;
331
332                 /*
333                  * We now compare the vnode of the svr4_root to the one
334                  * vnode asked. If they resolve to be the same, then we
335                  * ignore the match so that the real root gets used.
336                  * This avoids the problem of traversing "../.." to find the
337                  * root directory and never finding it, because "/" resolves
338                  * to the emulation root directory. This is expensive :-(
339                  */
340                 error = nlookup_init(&ndroot, svr4_emul_path, UIO_SYSSPACE,
341                                         NLC_FOLLOW);
342                 if (error == 0)
343                         error = nlookup(&ndroot);
344                 vp = NULL;
345                 if (error == 0)
346                         error = cache_vref(ndroot.nl_ncp, ndroot.nl_cred, &vp);
347                 nlookup_done(&ndroot);
348                 if (error) {
349                         free(buf, M_TEMP);
350                         return (error);
351                 }
352                 error = VOP_GETATTR(vp, &vatroot, td);
353                 vrele(vp);
354                 if (error)
355                         goto done;
356
357                 if (vat.va_fsid == vatroot.va_fsid &&
358                     vat.va_fileid == vatroot.va_fileid) {
359                         error = ENOENT;
360                         goto done;
361                 }
362         }
363         if (sgp == NULL) {
364                 *pbuf = buf;
365         } else {
366                 sz = &ptr[len] - buf;
367                 *pbuf = stackgap_alloc(sgp, sz + 1);
368                 error = copyout(buf, *pbuf, sz);
369                 free(buf, M_TEMP);
370         }
371 done:
372         return error;
373 }
374
375 static int
376 svr4_elf_modevent(module_t mod, int type, void *data)
377 {
378         int error;
379
380         error = 0;
381
382         switch(type) {
383         case MOD_LOAD:
384                 if (elf_insert_brand_entry(&svr4_brand) < 0)
385                         error = EINVAL;
386                 if (error)
387                         printf("cannot insert svr4 elf brand handler\n");
388                 else if (bootverbose)
389                         printf("svr4 ELF exec handler installed\n");
390                 break;
391         case MOD_UNLOAD:
392                 /* Only allow the emulator to be removed if it isn't in use. */
393                 if (elf_brand_inuse(&svr4_brand) != 0) {
394                         error = EBUSY;
395                 } else if (elf_remove_brand_entry(&svr4_brand) < 0) {
396                         error = EINVAL;
397                 }
398
399                 if (error)
400                         printf("Could not deinstall ELF interpreter entry (error %d)\n",
401                                error);
402                 else if (bootverbose)
403                         printf("svr4 ELF exec handler removed\n");
404                 break;
405         default:
406                 break;
407         }
408         return error;
409 }
410
411 static moduledata_t svr4_elf_mod = {
412         "svr4elf",
413         svr4_elf_modevent,
414         0
415 };
416 DECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);