1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2000, 2001 David O'Brien 5 * Copyright (c) 1996 Søren Schmidt 6 * 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 * in this position and unchanged. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/capsicum.h> 37 #include <sys/elf_common.h> 38 #include <sys/errno.h> 39 40 #include <capsicum_helpers.h> 41 #include <err.h> 42 #include <fcntl.h> 43 #include <stdbool.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include <libcasper.h> 50 #include <casper/cap_fileargs.h> 51 52 static int elftype(const char *); 53 static const char *iselftype(int); 54 static void printelftypes(void); 55 static void usage(void); 56 57 struct ELFtypes { 58 const char *str; 59 int value; 60 }; 61 /* XXX - any more types? */ 62 static struct ELFtypes elftypes[] = { 63 { "FreeBSD", ELFOSABI_FREEBSD }, 64 { "Linux", ELFOSABI_LINUX }, 65 { "Solaris", ELFOSABI_SOLARIS }, 66 { "SVR4", ELFOSABI_SYSV } 67 }; 68 69 int 70 main(int argc, char **argv) 71 { 72 73 const char *strtype = "FreeBSD"; 74 int ch, flags, retval, type; 75 bool change, force, listed; 76 fileargs_t *fa; 77 cap_rights_t rights; 78 79 type = ELFOSABI_FREEBSD; 80 retval = 0; 81 change = false; 82 force = false; 83 listed = false; 84 85 while ((ch = getopt(argc, argv, "f:lt:v")) != -1) 86 switch (ch) { 87 case 'f': 88 if (change) 89 errx(1, "f option incompatible with t option"); 90 force = true; 91 type = atoi(optarg); 92 if (errno == ERANGE || type < 0 || type > 255) { 93 warnx("invalid argument to option f: %s", 94 optarg); 95 usage(); 96 } 97 break; 98 case 'l': 99 printelftypes(); 100 listed = true; 101 break; 102 case 'v': 103 /* does nothing */ 104 break; 105 case 't': 106 if (force) 107 errx(1, "t option incompatible with f option"); 108 change = true; 109 strtype = optarg; 110 break; 111 default: 112 usage(); 113 } 114 argc -= optind; 115 argv += optind; 116 if (argc == 0) { 117 if (listed) 118 exit(0); 119 else { 120 warnx("no file(s) specified"); 121 usage(); 122 } 123 } 124 125 if (!force && (type = elftype(strtype)) == -1) { 126 warnx("invalid ELF type '%s'", strtype); 127 printelftypes(); 128 usage(); 129 } 130 131 flags = change || force ? O_RDWR : O_RDONLY; 132 cap_rights_init(&rights, CAP_READ, CAP_SEEK); 133 if (flags == O_RDWR) 134 cap_rights_set(&rights, CAP_WRITE); 135 136 fa = fileargs_init(argc, argv, flags, 0, &rights, FA_OPEN); 137 if (fa == NULL) 138 err(1, "unable to init casper"); 139 140 caph_cache_catpages(); 141 if (caph_limit_stdio() < 0 || caph_enter_casper() < 0) 142 err(1, "unable to enter capability mode"); 143 144 while (argc != 0) { 145 int fd; 146 char buffer[EI_NIDENT]; 147 148 if ((fd = fileargs_open(fa, argv[0])) < 0) { 149 warn("error opening file %s", argv[0]); 150 retval = 1; 151 goto fail; 152 } 153 if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) { 154 warnx("file '%s' too short", argv[0]); 155 retval = 1; 156 goto fail; 157 } 158 if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 || 159 buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) { 160 warnx("file '%s' is not ELF format", argv[0]); 161 retval = 1; 162 goto fail; 163 } 164 if (!change && !force) { 165 fprintf(stdout, 166 "File '%s' is of brand '%s' (%u).\n", 167 argv[0], iselftype(buffer[EI_OSABI]), 168 buffer[EI_OSABI]); 169 if (!iselftype(type)) { 170 warnx("ELF ABI Brand '%u' is unknown", 171 type); 172 printelftypes(); 173 } 174 } 175 else { 176 buffer[EI_OSABI] = type; 177 lseek(fd, 0, SEEK_SET); 178 if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) { 179 warn("error writing %s %d", argv[0], fd); 180 retval = 1; 181 goto fail; 182 } 183 } 184 fail: 185 close(fd); 186 argc--; 187 argv++; 188 } 189 190 fileargs_free(fa); 191 return (retval); 192 } 193 194 static void 195 usage(void) 196 { 197 (void)fprintf(stderr, 198 "usage: brandelf [-lv] [-f ELF_ABI_number] [-t string] file ...\n"); 199 exit(1); 200 } 201 202 static const char * 203 iselftype(int etype) 204 { 205 size_t elfwalk; 206 207 for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++) 208 if (etype == elftypes[elfwalk].value) 209 return (elftypes[elfwalk].str); 210 return (0); 211 } 212 213 static int 214 elftype(const char *elfstrtype) 215 { 216 size_t elfwalk; 217 218 for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++) 219 if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) 220 return (elftypes[elfwalk].value); 221 return (-1); 222 } 223 224 static void 225 printelftypes(void) 226 { 227 size_t elfwalk; 228 229 fprintf(stderr, "known ELF types are: "); 230 for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++) 231 fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str, 232 elftypes[elfwalk].value); 233 fprintf(stderr, "\n"); 234 } 235