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