]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/brandelf/brandelf.c
sysctl(9): Fix a few mandoc related issues
[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 __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 }