xref: /openbsd-src/usr.bin/rdist/isexec.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: isexec.c,v 1.8 2009/10/27 23:59:42 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1983 Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "defs.h"
33 
34 static int _isexec(int);
35 
36 #if	EXE_TYPE == EXE_AOUT
37 /*
38  * BSD style A.OUT
39  */
40 #include <a.out.h>
41 
42 static int
43 _isexec(int fd)
44 {
45 	struct exec ehdr;
46 
47 	if ((read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) &&
48 	    !N_BADMAG(ehdr))
49 		return(TRUE);
50 	else
51 		return(FALSE);
52 }
53 #endif /* EXE_AOUT */
54 
55 
56 #if	EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_ELF
57 /*
58  * Elf
59  */
60 #include <elf_abi.h>
61 #define ISELF(h)	(h.e_type == ET_EXEC)
62 #endif	/* EXE_ELF_AND_COFF || EXE_ELF */
63 
64 #if 	EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_COFF
65 
66 /*
67  * COFF
68  */
69 #if defined(FILEHDR_H)
70 #include FILEHDR_H
71 #endif	/* FILEHDR_H */
72 
73 #if !defined(ISCOFF)
74 
75 /*
76  * Stupid AIX
77  */
78 #if defined(U802WRMAGIC) && defined(U802ROMAGIC) && defined(U802TOCMAGIC)
79 #define ISCOFF(x) (((x)==U802WRMAGIC) || ((x)==U802TOCMAGIC) || \
80 		   ((x)==U802TOCMAGIC))
81 #endif	/* U802... */
82 /*
83  * Stupid Umax4.3
84  */
85 #if 	defined(NS32GMAGIC) || defined(NS32SMAGIC)
86 #define ISCOFF(x) (((x)==NS32GMAGIC) || ((x)==NS32SMAGIC))
87 #endif 	/* NS32 ... */
88 
89 #endif	/* ISCOFF */
90 
91 #endif /* EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_COFF */
92 
93 #if	EXE_TYPE == EXE_ELF_AND_COFF
94 /*
95  * ELF and COFF
96  */
97 typedef union {
98     struct filehdr 	coffhdr;
99     Elf32_Ehdr 		elfhdr;
100 } hdr_t;
101 #endif	/* EXE_TYPE == EXE_ELF_AND_COFF */
102 
103 #if	EXE_TYPE == EXE_ELF
104 /*
105  * Elf
106  */
107 typedef Elf32_Ehdr 	hdr_t;
108 #endif	/* EXE_TYPE == EXE_ELF */
109 
110 #if	EXE_TYPE == EXE_COFF
111 /*
112  * COFF
113  */
114 
115 #if	defined(FILEHDR_H)
116 #include FILEHDR_H
117 #endif	/* FILEHDR_H */
118 
119 typedef struct filehdr 	hdr_t;
120 #endif	/* EXE_TYPE == EXE_COFF */
121 
122 #if	EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_ELF || EXE_TYPE == EXE_COFF
123 /*
124  * System V style COFF and System V R4 style ELF
125  */
126 static int
127 _isexec(int fd)
128 {
129 	hdr_t hdr;
130 
131 	if (read(fd, &hdr, sizeof(hdr)) == sizeof(hdr)) {
132 #if EXE_TYPE == EXE_ELF_AND_COFF
133 	    if (ISELF(hdr.elfhdr) || ISCOFF(hdr.coffhdr.f_magic))
134 		return(TRUE);
135 #endif
136 #if EXE_TYPE == EXE_ELF
137 	    if (ISELF(hdr))
138 		return(TRUE);
139 #endif
140 #if EXE_TYPE == EXE_COFF
141 	    if (ISCOFF(hdr.f_magic))
142 		return(TRUE);
143 #endif
144 	}
145 
146 	return(FALSE);
147 }
148 #endif /* EXE_ELF_AND_COFF */
149 
150 
151 #if	EXE_TYPE == EXE_MACHO
152 /*
153  * Mach-O format
154  */
155 
156 #if	defined(NEXTSTEP) && NEXTSTEP >= 3
157 #	include <mach-o/loader.h>
158 #else
159 #	include <sys/loader.h>
160 #endif	/* NEXTSTEP */
161 
162 #ifndef MH_CIGAM
163 #define MH_CIGAM  	0xcefaedfe
164 #endif
165 #ifndef FAT_MAGIC
166 #define FAT_MAGIC 	0xcafebabe
167 #endif
168 #ifndef FAT_CIGAM
169 #define FAT_CIGAM 	0xbebafeca
170 #endif
171 
172 static int
173 _isexec(int fd)
174 {
175 	struct mach_header ehdr;
176 
177 	if ((read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) &&
178 	    (ehdr.magic == MH_MAGIC || ehdr.magic == MH_CIGAM ||
179 	     ehdr.magic == FAT_MAGIC || ehdr.magic == FAT_CIGAM))
180 		return(TRUE);
181 	else
182 		return(FALSE);
183 }
184 #endif /* EXE_COFF */
185 
186 
187 #if	EXE_TYPE == EXE_HPEXEC
188 /*
189  * HP 9000 executable format
190  */
191 
192 #ifdef hp9000s300
193 
194 #include <a.out.h>
195 #define header exec
196 #define ISEXEC(a) ((a.file_type)==EXEC_MAGIC || (a.file_type)==SHARE_MAGIC || \
197 		   (a.file_type)==DEMAND_MAGIC)
198 
199 #else	/* ! hp9000s300 */
200 
201 #define ISEXEC(a) ((a)==EXEC_MAGIC || (a)==SHARE_MAGIC || (a)==DEMAND_MAGIC)
202 #include <filehdr.h>
203 
204 #endif	/* hp9000s300 */
205 
206 static int
207 _isexec(int fd)
208 {
209 	struct header ehdr;
210 
211 	if ((read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) &&
212 	    ISEXEC(ehdr.a_magic))
213 		return(TRUE);
214 	else
215 		return(FALSE);
216 }
217 #endif	/* EXE_HPEXEC */
218 
219 
220 #if	!defined(EXE_TYPE)
221 /*
222  * Fake _isexec() call for unknown executable formats.
223  */
224 static int
225 _isexec(int fd)
226 {
227 	return(FALSE);
228 }
229 #endif	/* !defined(EXE_TYPE) */
230 
231 /*
232  * Determine whether 'file' is an executable or not.
233  */
234 int
235 isexec(char *file, struct stat *statp)
236 {
237 	int fd, r;
238 
239 	/*
240 	 * Must be a regular file that has some executable mode bit on
241 	 */
242 	if (!S_ISREG(statp->st_mode) ||
243 	    !(statp->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
244 		return(FALSE);
245 
246 	if ((fd = open(file, O_RDONLY, 0)) < 0)
247 		return(FALSE);
248 	r = _isexec(fd);
249 	(void) close(fd);
250 
251 	return(r);
252 }
253 
254