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