xref: /freebsd/usr.bin/brandelf/brandelf.c (revision 5e3934b15a2741b2de6b217e77dc9d798d740804)
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