1*d91f98a8Spgoyette /* $NetBSD: compat_exec.c,v 1.18 2019/01/27 02:08:39 pgoyette Exp $ */
2f09036d6Schristos
3f09036d6Schristos /*
4f09036d6Schristos * Copyright (c) 1993, 1994 Christopher G. Demetriou
5f09036d6Schristos * All rights reserved.
6f09036d6Schristos *
7f09036d6Schristos * Redistribution and use in source and binary forms, with or without
8f09036d6Schristos * modification, are permitted provided that the following conditions
9f09036d6Schristos * are met:
10f09036d6Schristos * 1. Redistributions of source code must retain the above copyright
11f09036d6Schristos * notice, this list of conditions and the following disclaimer.
12f09036d6Schristos * 2. Redistributions in binary form must reproduce the above copyright
13f09036d6Schristos * notice, this list of conditions and the following disclaimer in the
14f09036d6Schristos * documentation and/or other materials provided with the distribution.
15f09036d6Schristos * 3. All advertising materials mentioning features or use of this software
16f09036d6Schristos * must display the following acknowledgement:
17f09036d6Schristos * This product includes software developed by Christopher G. Demetriou.
18f09036d6Schristos * 4. The name of the author may not be used to endorse or promote products
19f09036d6Schristos * derived from this software without specific prior written permission
20f09036d6Schristos *
21f09036d6Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22f09036d6Schristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23f09036d6Schristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24f09036d6Schristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25f09036d6Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26f09036d6Schristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27f09036d6Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28f09036d6Schristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29f09036d6Schristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30f09036d6Schristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31f09036d6Schristos */
32f09036d6Schristos
33dab6ef8bSlukem #include <sys/cdefs.h>
34*d91f98a8Spgoyette __KERNEL_RCSID(0, "$NetBSD: compat_exec.c,v 1.18 2019/01/27 02:08:39 pgoyette Exp $");
35baf57f2dSmatt
36baf57f2dSmatt #ifdef _KERNEL_OPT
37*d91f98a8Spgoyette #include "opt_compat_netbsd.h"
38baf57f2dSmatt #include "opt_execfmt.h"
39baf57f2dSmatt #endif
40dab6ef8bSlukem
41f09036d6Schristos #include <sys/param.h>
42f09036d6Schristos #include <sys/systm.h>
43f09036d6Schristos #include <sys/proc.h>
44f09036d6Schristos #include <sys/vnode.h>
45f09036d6Schristos #include <sys/exec.h>
46f09036d6Schristos #include <sys/resourcevar.h>
47f09036d6Schristos
48baf57f2dSmatt #ifdef EXEC_AOUT
497bb407d6Smatt #include <sys/exec_aout.h>
507bb407d6Smatt
51f09036d6Schristos /*
52f09036d6Schristos * exec_aout_prep_oldzmagic():
53f09036d6Schristos * Prepare the vmcmds to build a vmspace for an old ZMAGIC
54f09036d6Schristos * binary. [386BSD/BSDI/4.4BSD/NetBSD0.8]
55f09036d6Schristos *
56f09036d6Schristos * Cloned from exec_aout_prep_zmagic() in kern/exec_aout.c; a more verbose
57f09036d6Schristos * description of operation is there.
58f09036d6Schristos * There were copies of this in the mac68k, hp300, and i386 ports.
59f09036d6Schristos */
60f09036d6Schristos int
exec_aout_prep_oldzmagic(struct lwp * l,struct exec_package * epp)6128bae79bSdsl exec_aout_prep_oldzmagic(struct lwp *l, struct exec_package *epp)
62f09036d6Schristos {
63f09036d6Schristos struct exec *execp = epp->ep_hdr;
64993948e9Schs int error;
65f09036d6Schristos
66f09036d6Schristos epp->ep_taddr = 0;
67f09036d6Schristos epp->ep_tsize = execp->a_text;
68f09036d6Schristos epp->ep_daddr = epp->ep_taddr + execp->a_text;
69f09036d6Schristos epp->ep_dsize = execp->a_data + execp->a_bss;
70f09036d6Schristos epp->ep_entry = execp->a_entry;
71f09036d6Schristos
72993948e9Schs error = vn_marktext(epp->ep_vp);
73993948e9Schs if (error)
74993948e9Schs return (error);
75f09036d6Schristos
76f09036d6Schristos /* set up command for text segment */
77f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
78f4a068d5Sthorpej epp->ep_taddr, epp->ep_vp, PAGE_SIZE, /* XXX CLBYTES? */
79f09036d6Schristos VM_PROT_READ|VM_PROT_EXECUTE);
80f09036d6Schristos
81f09036d6Schristos /* set up command for data segment */
82f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
83f09036d6Schristos epp->ep_daddr, epp->ep_vp,
84f4a068d5Sthorpej execp->a_text + PAGE_SIZE, /* XXX CLBYTES? */
85f09036d6Schristos VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
86f09036d6Schristos
87f09036d6Schristos /* set up command for bss segment */
880b71a2d5Schristos if (execp->a_bss)
89f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
90f09036d6Schristos epp->ep_daddr + execp->a_data, NULLVP, 0,
91f09036d6Schristos VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
92f09036d6Schristos
9395e1ffb1Schristos return (*epp->ep_esch->es_setup_stack)(l, epp);
94f09036d6Schristos }
95f09036d6Schristos
96f09036d6Schristos
97f09036d6Schristos /*
98f09036d6Schristos * exec_aout_prep_oldnmagic():
99f09036d6Schristos * Prepare the vmcmds to build a vmspace for an old NMAGIC
100f09036d6Schristos * binary. [BSDI]
101f09036d6Schristos *
102f09036d6Schristos * Cloned from exec_aout_prep_nmagic() in kern/exec_aout.c; with text starting
103f09036d6Schristos * at 0.
104f09036d6Schristos * XXX: There must be a better way to share this code.
105f09036d6Schristos */
106f09036d6Schristos int
exec_aout_prep_oldnmagic(struct lwp * l,struct exec_package * epp)10728bae79bSdsl exec_aout_prep_oldnmagic(struct lwp *l, struct exec_package *epp)
108f09036d6Schristos {
109f09036d6Schristos struct exec *execp = epp->ep_hdr;
110f09036d6Schristos long bsize, baddr;
111f09036d6Schristos
112f09036d6Schristos epp->ep_taddr = 0;
113f09036d6Schristos epp->ep_tsize = execp->a_text;
114e8cc3884Sthorpej epp->ep_daddr = roundup(epp->ep_taddr + execp->a_text, AOUT_LDPGSZ);
115f09036d6Schristos epp->ep_dsize = execp->a_data + execp->a_bss;
116f09036d6Schristos epp->ep_entry = execp->a_entry;
117f09036d6Schristos
118f09036d6Schristos /* set up command for text segment */
119f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text,
120f09036d6Schristos epp->ep_taddr, epp->ep_vp, sizeof(struct exec),
121f09036d6Schristos VM_PROT_READ|VM_PROT_EXECUTE);
122f09036d6Schristos
123f09036d6Schristos /* set up command for data segment */
124f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data,
125f09036d6Schristos epp->ep_daddr, epp->ep_vp, execp->a_text + sizeof(struct exec),
126f09036d6Schristos VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
127f09036d6Schristos
128f09036d6Schristos /* set up command for bss segment */
129f4a068d5Sthorpej baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE);
130f09036d6Schristos bsize = epp->ep_daddr + epp->ep_dsize - baddr;
131f09036d6Schristos if (bsize > 0)
132f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
133f09036d6Schristos NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
134f09036d6Schristos
13595e1ffb1Schristos return (*epp->ep_esch->es_setup_stack)(l, epp);
136f09036d6Schristos }
137f09036d6Schristos
138f09036d6Schristos
139f09036d6Schristos /*
140f09036d6Schristos * exec_aout_prep_oldomagic():
141f09036d6Schristos * Prepare the vmcmds to build a vmspace for an old OMAGIC
142f09036d6Schristos * binary. [BSDI]
143f09036d6Schristos *
144f09036d6Schristos * Cloned from exec_aout_prep_omagic() in kern/exec_aout.c; with text starting
145f09036d6Schristos * at 0.
146f09036d6Schristos * XXX: There must be a better way to share this code.
147f09036d6Schristos */
148f09036d6Schristos int
exec_aout_prep_oldomagic(struct lwp * l,struct exec_package * epp)14928bae79bSdsl exec_aout_prep_oldomagic(struct lwp *l, struct exec_package *epp)
150f09036d6Schristos {
151f09036d6Schristos struct exec *execp = epp->ep_hdr;
152f09036d6Schristos long dsize, bsize, baddr;
153f09036d6Schristos
154f09036d6Schristos epp->ep_taddr = 0;
155f09036d6Schristos epp->ep_tsize = execp->a_text;
156f09036d6Schristos epp->ep_daddr = epp->ep_taddr + execp->a_text;
157f09036d6Schristos epp->ep_dsize = execp->a_data + execp->a_bss;
158f09036d6Schristos epp->ep_entry = execp->a_entry;
159f09036d6Schristos
160f09036d6Schristos /* set up command for text and data segments */
161f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
162f09036d6Schristos execp->a_text + execp->a_data, epp->ep_taddr, epp->ep_vp,
163f09036d6Schristos sizeof(struct exec), VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
164f09036d6Schristos
165f09036d6Schristos /* set up command for bss segment */
166f4a068d5Sthorpej baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE);
167f09036d6Schristos bsize = epp->ep_daddr + epp->ep_dsize - baddr;
168f09036d6Schristos if (bsize > 0)
169f09036d6Schristos NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
170f09036d6Schristos NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
171f09036d6Schristos
172f09036d6Schristos /*
173f09036d6Schristos * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize);
174f09036d6Schristos * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are
175f09036d6Schristos * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize'
176f09036d6Schristos * respectively to page boundaries.
177f09036d6Schristos * Compensate `ep_dsize' for the amount of data covered by the last
178f09036d6Schristos * text page.
179f09036d6Schristos */
180f4a068d5Sthorpej dsize = epp->ep_dsize + execp->a_text - roundup(execp->a_text,
181f4a068d5Sthorpej PAGE_SIZE);
182f09036d6Schristos epp->ep_dsize = (dsize > 0) ? dsize : 0;
18395e1ffb1Schristos return (*epp->ep_esch->es_setup_stack)(l, epp);
184f09036d6Schristos }
185baf57f2dSmatt #endif /* EXEC_AOUT */
186