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 #include <sys/param.h>
34 #include <sys/capsicum.h>
35 #include <sys/elf_common.h>
36 #include <sys/errno.h>
37
38 #include <capsicum_helpers.h>
39 #include <err.h>
40 #include <fcntl.h>
41 #include <stdbool.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 #include <libcasper.h>
48 #include <casper/cap_fileargs.h>
49
50 static int elftype(const char *);
51 static const char *iselftype(int);
52 static void printelftypes(void);
53 static void usage(void);
54
55 struct ELFtypes {
56 const char *str;
57 int value;
58 };
59 /* XXX - any more types? */
60 static struct ELFtypes elftypes[] = {
61 { "FreeBSD", ELFOSABI_FREEBSD },
62 { "Linux", ELFOSABI_LINUX },
63 { "Solaris", ELFOSABI_SOLARIS },
64 { "SVR4", ELFOSABI_SYSV }
65 };
66
67 int
main(int argc,char ** argv)68 main(int argc, char **argv)
69 {
70
71 const char *strtype = "FreeBSD";
72 int ch, flags, retval, type;
73 bool change, force, listed;
74 fileargs_t *fa;
75 cap_rights_t rights;
76
77 type = ELFOSABI_FREEBSD;
78 retval = 0;
79 change = false;
80 force = false;
81 listed = false;
82
83 while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
84 switch (ch) {
85 case 'f':
86 if (change)
87 errx(1, "f option incompatible with t option");
88 force = true;
89 type = atoi(optarg);
90 if (errno == ERANGE || type < 0 || type > 255) {
91 warnx("invalid argument to option f: %s",
92 optarg);
93 usage();
94 }
95 break;
96 case 'l':
97 printelftypes();
98 listed = true;
99 break;
100 case 'v':
101 /* does nothing */
102 break;
103 case 't':
104 if (force)
105 errx(1, "t option incompatible with f option");
106 change = true;
107 strtype = optarg;
108 break;
109 default:
110 usage();
111 }
112 argc -= optind;
113 argv += optind;
114 if (argc == 0) {
115 if (listed)
116 exit(0);
117 else {
118 warnx("no file(s) specified");
119 usage();
120 }
121 }
122
123 if (!force && (type = elftype(strtype)) == -1) {
124 warnx("invalid ELF type '%s'", strtype);
125 printelftypes();
126 usage();
127 }
128
129 flags = change || force ? O_RDWR : O_RDONLY;
130 cap_rights_init(&rights, CAP_READ, CAP_SEEK);
131 if (flags == O_RDWR)
132 cap_rights_set(&rights, CAP_WRITE);
133
134 fa = fileargs_init(argc, argv, flags, 0, &rights, FA_OPEN);
135 if (fa == NULL)
136 err(1, "unable to init casper");
137
138 caph_cache_catpages();
139 if (caph_limit_stdio() < 0 || caph_enter_casper() < 0)
140 err(1, "unable to enter capability mode");
141
142 while (argc != 0) {
143 int fd;
144 char buffer[EI_NIDENT];
145
146 if ((fd = fileargs_open(fa, argv[0])) < 0) {
147 warn("error opening file %s", argv[0]);
148 retval = 1;
149 goto fail;
150 }
151 if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
152 warnx("file '%s' too short", argv[0]);
153 retval = 1;
154 goto fail;
155 }
156 if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
157 buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
158 warnx("file '%s' is not ELF format", argv[0]);
159 retval = 1;
160 goto fail;
161 }
162 if (!change && !force) {
163 fprintf(stdout,
164 "File '%s' is of brand '%s' (%u).\n",
165 argv[0], iselftype(buffer[EI_OSABI]),
166 buffer[EI_OSABI]);
167 if (!iselftype(type)) {
168 warnx("ELF ABI Brand '%u' is unknown",
169 type);
170 printelftypes();
171 }
172 }
173 else {
174 buffer[EI_OSABI] = type;
175 lseek(fd, 0, SEEK_SET);
176 if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
177 warn("error writing %s %d", argv[0], fd);
178 retval = 1;
179 goto fail;
180 }
181 }
182 fail:
183 close(fd);
184 argc--;
185 argv++;
186 }
187
188 fileargs_free(fa);
189 return (retval);
190 }
191
192 static void
usage(void)193 usage(void)
194 {
195 (void)fprintf(stderr,
196 "usage: brandelf [-lv] [-f ELF_ABI_number] [-t string] file ...\n");
197 exit(1);
198 }
199
200 static const char *
iselftype(int etype)201 iselftype(int etype)
202 {
203 size_t elfwalk;
204
205 for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++)
206 if (etype == elftypes[elfwalk].value)
207 return (elftypes[elfwalk].str);
208 return (0);
209 }
210
211 static int
elftype(const char * elfstrtype)212 elftype(const char *elfstrtype)
213 {
214 size_t elfwalk;
215
216 for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++)
217 if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
218 return (elftypes[elfwalk].value);
219 return (-1);
220 }
221
222 static void
printelftypes(void)223 printelftypes(void)
224 {
225 size_t elfwalk;
226
227 fprintf(stderr, "known ELF types are: ");
228 for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++)
229 fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str,
230 elftypes[elfwalk].value);
231 fprintf(stderr, "\n");
232 }
233