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