1 /*	$OpenBSD: exec.c,v 1.26 2003/08/11 06:23:09 deraadt Exp $	*/
2 /*	$NetBSD: exec.c,v 1.15 1996/10/13 02:29:01 christos Exp $	*/
3 
4 /*-
5  * Copyright (c) 1982, 1986, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/exec.h>
35 #include <sys/reboot.h>
36 #ifndef INSECURE
37 #include <sys/stat.h>
38 #endif
39 
40 #include "stand.h"
41 
42 static char *ssym, *esym;
43 
44 extern u_int opendev;
45 
46 void
exec(char * path,void * loadaddr,int howto)47 exec(char *path, void *loadaddr, int howto)
48 {
49 	int io;
50 #ifndef INSECURE
51 	struct stat sb;
52 #endif
53 	struct exec x;
54 	u_int i;
55 	ssize_t sz;
56 	char *addr;
57 #ifdef EXEC_DEBUG
58 	char *daddr, *etxt;
59 #endif
60 
61 	io = open(path, 0);
62 	if (io < 0)
63 		return;
64 
65 	(void) fstat(io, &sb);
66 	if (sb.st_mode & 2)
67 		printf("non-secure file, check permissions!\n");
68 
69 	sz = read(io, (char *)&x, sizeof(x));
70 	if (sz != sizeof(x) || N_BADMAG(x)) {
71 		close(io);
72 		errno = EFTYPE;
73 		return;
74 	}
75 
76 #ifdef EXEC_DEBUG
77 	printf("\nstruct exec {%x, %x, %x, %x, %x, %x, %x, %x}\n",
78 		x.a_midmag, x.a_text, x.a_data, x.a_bss, x.a_syms,
79 		x.a_entry, x.a_trsize, x.a_drsize);
80 #endif
81 
82 	/* Text */
83 	printf("%u", x.a_text);
84 	addr = loadaddr;
85 	sz = x.a_text;
86 	if (N_GETMAGIC(x) == ZMAGIC) {
87 		bcopy((char *)&x, addr, sizeof x);
88 		addr += sizeof x;
89 		sz -= sizeof x;
90 	}
91 	if (read(io, (char *)addr, sz) != sz)
92 		goto shread;
93 	addr += sz;
94 #ifdef EXEC_DEBUG
95 	printf("\ntext {%x, %x, %x, %x}\n",
96 	    addr[0], addr[1], addr[2], addr[3]);
97 	etxt = addr;
98 #endif
99 	if (N_GETMAGIC(x) == NMAGIC)
100 		while ((long)addr & (N_PAGSIZ(x) - 1))
101 			*addr++ = 0;
102 
103 	/* Data */
104 #ifdef EXEC_DEBUG
105 	daddr = addr;
106 #endif
107 	printf("+%u", x.a_data);
108 	if (read(io, addr, x.a_data) != (ssize_t)x.a_data)
109 		goto shread;
110 	addr += x.a_data;
111 
112 	/* Bss */
113 	printf("+%u", x.a_bss);
114 	for (i = 0; i < x.a_bss; i++)
115 		*addr++ = 0;
116 
117 	/* Symbols */
118 	if (x.a_syms) {
119 		ssym = addr;
120 		bcopy(&x.a_syms, addr, sizeof(x.a_syms));
121 		addr += sizeof(x.a_syms);
122 		printf("+[%u", x.a_syms);
123 		if (read(io, addr, x.a_syms) != (ssize_t)x.a_syms)
124 			goto shread;
125 		addr += x.a_syms;
126 
127 		if (read(io, &i, sizeof(u_int)) != sizeof(u_int))
128 			goto shread;
129 
130 		bcopy(&i, addr, sizeof(u_int));
131 		if (i) {
132 			sz = i - sizeof(int);
133 			addr += sizeof(int);
134 			if (read(io, addr, sz) != sz)
135 				goto shread;
136 			addr += sz;
137 		}
138 
139 		/* and that many bytes of string table */
140 		printf("+%d]", sz);
141 		esym = addr;
142 	} else {
143 		ssym = 0;
144 		esym = 0;
145 	}
146 
147 	close(io);
148 
149 	/* and note the end address of all this	*/
150 	printf(" total=0x%lx", (u_long)addr);
151 
152 /* XXX - Hack alert!
153    This is no good, loadaddr is passed into
154    machdep_start(), and it should do whatever
155    is needed.
156 
157 	x.a_entry += (long)loadaddr;
158 */
159 	printf(" start=0x%x\n", x.a_entry);
160 
161 #ifdef EXEC_DEBUG
162 	printf("loadaddr=%p etxt=%p daddr=%p ssym=%p esym=%p\n",
163 	    loadaddr, etxt, daddr, ssym, esym);
164 	printf("\n\nReturn to boot...\n");
165 	getchar();
166 #endif
167 
168 	machdep_start((char *)((register_t)x.a_entry), howto, loadaddr, ssym,
169 	    esym);
170 
171 	/* exec failed */
172 	errno = ENOEXEC;
173 	return;
174 
175 shread:
176 	close(io);
177 	errno = EIO;
178 	return;
179 }
180