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