]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/brandelf/brandelf.c
zfs: merge openzfs/zfs@0ee9b0239
[FreeBSD/FreeBSD.git] / usr.bin / brandelf / brandelf.c
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) __dead2;
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
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
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 *
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
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
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 }