svn commit: r358780 - stable/12/tools/tools/controlelf
Ed Maste
emaste at FreeBSD.org
Sun Mar 8 21:02:36 UTC 2020
Author: emaste
Date: Sun Mar 8 21:02:35 2020
New Revision: 358780
URL: https://svnweb.freebsd.org/changeset/base/358780
Log:
Add tool to modify ELF binary feature control bits
MFC r352797: Add tool to modify ELF binary feature control bits
This will allow feature control bits (e.g. for ASLR, PROT_MAX) to be
inspected or modified.
Some clean-up and additional work is likely still required, but we can
iterate on this in the tree.
Submitted by: Bora Özarslan <borako.ozarslan at gmail.com>
MFC r352799: controlelf: clean up warnings
- use explicit ELF note name when not found
- no trailing . on warnings
- no \n
MFC r352801: controlelf: install standard BSD 2 clause license
MFC r352803: controlelf: some style(9) cleanup
MFC r352805: controlelf: add protmax control
MFC r352806: controlelf: tidy up option parsing
MFC r352808: controlelf: simplify feature string parsing
Also add error handling on failure to seek/write updated value.
MFC r352809: controlelf: exit with error if file endianness does not match host
We need to add support for cross-endian operation, but until that's done
just exit with an error rather than misbehaving.
MFC r352815: controlelf: update man page
Some minor corrections, clarifications or rewording.
Sponsored by: The FreeBSD Foundation
Added:
stable/12/tools/tools/controlelf/
- copied from r352797, head/tools/tools/controlelf/
Modified:
stable/12/tools/tools/controlelf/controlelf.1
stable/12/tools/tools/controlelf/controlelf.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/tools/tools/controlelf/controlelf.1
==============================================================================
--- head/tools/tools/controlelf/controlelf.1 Fri Sep 27 16:27:52 2019 (r352797)
+++ stable/12/tools/tools/controlelf/controlelf.1 Sun Mar 8 21:02:35 2020 (r358780)
@@ -26,12 +26,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 21, 2019
+.Dd September 27, 2019
.Dt CONTROLELF 1
.Os
.Sh NAME
.Nm controlelf
-.Nd change an ELF binary's control features
+.Nd change an ELF binary's feature control note
.Sh SYNOPSIS
.Nm
.Op Fl h | Fl -help
@@ -41,33 +41,33 @@
.Sh DESCRIPTION
The
.Nm
-utility modifies an ELF binary to change it's control features.
+utility modifies feature flags in the feature control note in an ELF binary.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl h | Fl -help
Print a usage message and exit.
.It Fl l
-Writes the list of all known ELF types to standard output.
+List known ELF feature flags.
.It Fl e Ar featurelist
Edit features from the given comma separated list
.Ar featurelist .
.Ar featurelist
-starts with one of the three modes:
+starts with one of the three operations:
.Dq Li +
to turn on the features,
.Dq Li -
to turn off the features,
.Dq Li =
to only turn on the given features.
-Followed by a comma separated features.
+A comma separated list of feature names follows the operation.
.El
.Pp
If
-.Fl e ,
-option wasn't specified,
+.Fl e
+is not specified
.Nm
-will display the current control features for the files named by the arguments
+displays the status of each feature in the ELF note in each
.Ar .
.Sh EXIT STATUS
Exit status is 0 on success, and 1 if the command
@@ -83,10 +83,12 @@ controlelf file
controlelf -e +aslr file
.Ed
.Sh HISTORY
-The
.Nm
-manual page first appeared in
+first appeared in
.Fx 13.0 .
.Sh AUTHORS
-This manual page was written by
-.An Bora Ozarslan Mt borako.ozarslan at gmail.com .
+.Nm
+was written by
+.An Bora Ozarslan Mt borako.ozarslan at gmail.com
+under sponsorship from the
+.Fx Foundation.
Modified: stable/12/tools/tools/controlelf/controlelf.c
==============================================================================
--- head/tools/tools/controlelf/controlelf.c Fri Sep 27 16:27:52 2019 (r352797)
+++ stable/12/tools/tools/controlelf/controlelf.c Sun Mar 8 21:02:35 2020 (r358780)
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2019 The FreeBSD Foundation.
*
@@ -10,26 +10,27 @@
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
+ * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/elf_common.h>
+#include <sys/endian.h>
#include <sys/stat.h>
#include <err.h>
@@ -47,66 +48,73 @@
__FBSDID("$FreeBSD$");
-static bool convert_to_feature_val(char*, u_int32_t*);
-static bool edit_file_features(Elf *, int, int, char*);
+static bool convert_to_feature_val(char *, u_int32_t *);
+static bool edit_file_features(Elf *, int, int, char *);
static bool get_file_features(Elf *, int, int, u_int32_t *, u_int64_t *);
static void print_features(void);
-static bool print_file_features(Elf *, int, int, char*);
+static bool print_file_features(Elf *, int, int, char *);
static void usage(void);
struct ControlFeatures {
const char *alias;
- unsigned long featureVal;
+ unsigned long value;
const char *desc;
};
static struct ControlFeatures featurelist[] = {
- { "aslr", NT_FREEBSD_FCTL_ASLR_DISABLE, "Disable ASLR" }
+ { "aslr", NT_FREEBSD_FCTL_ASLR_DISABLE, "Disable ASLR" },
+ { "protmax", NT_FREEBSD_FCTL_PROTMAX_DISABLE,
+ "Disable implicit PROT_MAX" },
+ { "stackgap", NT_FREEBSD_FCTL_STKGAP_DISABLE, "Disable stack gap" },
};
-static struct option controlelf_longopts[] = {
- { "help", no_argument, NULL, 'h' },
- { NULL, 0, NULL, 0 }
+static struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { NULL, 0, NULL, 0 }
};
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SUPPORTED_ENDIAN ELFDATA2LSB
+#else
+#define SUPPORTED_ENDIAN ELFDATA2MSB
+#endif
+
int
main(int argc, char **argv)
{
GElf_Ehdr ehdr;
Elf *elf;
Elf_Kind kind;
- int ch, fd, listed, editfeatures, retval;
+ int ch, fd, editfeatures, retval;
char *features;
+ bool lflag;
- listed = 0;
+ lflag = 0;
editfeatures = 0;
retval = 0;
if (elf_version(EV_CURRENT) == EV_NONE)
errx(EXIT_FAILURE, "elf_version error");
- while ((ch = getopt_long(argc, argv, "hle:", controlelf_longopts,
- NULL)) != -1) {
+ while ((ch = getopt_long(argc, argv, "hle:", long_opts, NULL)) != -1) {
switch (ch) {
case 'l':
print_features();
- listed = 1;
+ lflag = true;
break;
case 'e':
features = optarg;
editfeatures = 1;
break;
case 'h':
- usage();
- break;
default:
usage();
}
}
argc -= optind;
argv += optind;
- if (!argc) {
- if (listed)
+ if (argc == 0) {
+ if (lflag)
exit(0);
else {
warnx("no file(s) specified");
@@ -117,8 +125,8 @@ main(int argc, char **argv)
while (argc) {
elf = NULL;
- if ((fd = open(argv[0], editfeatures ? O_RDWR :
- O_RDONLY, 0)) < 0) {
+ if ((fd = open(argv[0],
+ editfeatures ? O_RDWR : O_RDONLY, 0)) < 0) {
warn("error opening file %s", argv[0]);
retval = 1;
goto fail;
@@ -132,10 +140,9 @@ main(int argc, char **argv)
if ((kind = elf_kind(elf)) != ELF_K_ELF) {
if (kind == ELF_K_AR)
- warnx("file '%s' is an archive.", argv[0]);
+ warnx("file '%s' is an archive", argv[0]);
else
- warnx("file '%s' is not an ELF file.",
- argv[0]);
+ warnx("file '%s' is not an ELF file", argv[0]);
retval = 1;
goto fail;
}
@@ -145,13 +152,24 @@ main(int argc, char **argv)
retval = 1;
goto fail;
}
+ /*
+ * XXX need to support cross-endian operation, but for now
+ * exit on error rather than misbehaving.
+ */
+ if (ehdr.e_ident[EI_DATA] != SUPPORTED_ENDIAN) {
+ warnx("file endianness must match host");
+ retval = 1;
+ goto fail;
+ }
if (!editfeatures) {
- if (!print_file_features(elf, ehdr.e_phnum, fd, argv[0])) {
+ if (!print_file_features(elf, ehdr.e_phnum, fd,
+ argv[0])) {
retval = 1;
goto fail;
}
- } else if (!edit_file_features(elf, ehdr.e_phnum, fd, features)) {
+ } else if (!edit_file_features(elf, ehdr.e_phnum, fd,
+ features)) {
retval = 1;
goto fail;
}
@@ -169,7 +187,8 @@ fail:
return (retval);
}
-#define USAGE_MESSAGE "\
+#define USAGE_MESSAGE \
+ "\
Usage: %s [options] file...\n\
Set or display the control features for an ELF object.\n\n\
Supported options are:\n\
@@ -186,47 +205,40 @@ usage(void)
}
static bool
-convert_to_feature_val(char* feature_str, u_int32_t* feature_val)
+convert_to_feature_val(char *feature_str, u_int32_t *feature_val)
{
- char *feature_input, *feature;
+ char *feature;
int i, len;
u_int32_t input;
- bool add, set;
+ char operation;
- add = set = false;
input = 0;
-
- if (feature_str[0] == '+')
- add = true;
- else if (feature_str[0] == '=')
- set = true;
- else if (feature_str[0] != '-') {
- warnx("'%c' is not an operator. Use instead '+', '-', '='.",
- feature_str[0]);
- return (false);
- }
-
- feature_input = feature_str + 1;
+ operation = *feature_str;
+ feature_str++;
len = nitems(featurelist);
- while ((feature = strsep(&feature_input, ",")) != NULL) {
+ while ((feature = strsep(&feature_str, ",")) != NULL) {
for (i = 0; i < len; ++i) {
if (strcmp(featurelist[i].alias, feature) == 0) {
- input |= featurelist[i].featureVal;
+ input |= featurelist[i].value;
break;
}
}
if (i == len) {
- warnx("%s is not a valid feature.", feature);
+ warnx("%s is not a valid feature", feature);
return (false);
}
}
- if (add) {
+ if (operation == '+') {
*feature_val |= input;
- } else if (set) {
+ } else if (operation == '=') {
*feature_val = input;
+ } else if (operation == '-') {
+ *feature_val &= ~input;
} else {
- *feature_val -= (*feature_val) & input;
+ warnx("'%c' not an operator - use '+', '-', '='",
+ feature_str[0]);
+ return (false);
}
return (true);
}
@@ -238,15 +250,19 @@ edit_file_features(Elf *elf, int phcount, int fd, char
u_int64_t off;
if (!get_file_features(elf, phcount, fd, &features, &off)) {
- warnx("No control features note on the file.\n");
+ warnx("NT_FREEBSD_FEATURE_CTL note not found");
return (false);
}
if (!convert_to_feature_val(val, &features))
return (false);
- lseek(fd, off, SEEK_SET);
- write(fd, &features, sizeof(u_int32_t));
+ if (lseek(fd, off, SEEK_SET) == -1 ||
+ write(fd, &features, sizeof(features)) <
+ (ssize_t)sizeof(features)) {
+ warnx("error writing feature value");
+ return (false);
+ }
return (true);
}
@@ -257,12 +273,13 @@ print_features(void)
printf("Known features are:\n");
for (i = 0; i < nitems(featurelist); ++i)
- printf("%s\t\t %s\n", featurelist[i].alias,
+ printf("%-16s%s\n", featurelist[i].alias,
featurelist[i].desc);
}
static bool
-print_file_features(Elf *elf, int phcount, int fd, char *filename) {
+print_file_features(Elf *elf, int phcount, int fd, char *filename)
+{
u_int32_t features;
unsigned long i;
@@ -272,10 +289,10 @@ print_file_features(Elf *elf, int phcount, int fd, cha
printf("File '%s' features:\n", filename);
for (i = 0; i < nitems(featurelist); ++i) {
- printf("%s\t\t'%s' is ", featurelist[i].alias,
+ printf("%-16s'%s' is ", featurelist[i].alias,
featurelist[i].desc);
- if ((featurelist[i].featureVal & features) == 0)
+ if ((featurelist[i].value & features) == 0)
printf("un");
printf("set.\n");
@@ -284,7 +301,8 @@ print_file_features(Elf *elf, int phcount, int fd, cha
}
static bool
-get_file_features(Elf *elf, int phcount, int fd, u_int32_t *features, u_int64_t *off)
+get_file_features(Elf *elf, int phcount, int fd, u_int32_t *features,
+ u_int64_t *off)
{
GElf_Phdr phdr;
Elf_Note note;
@@ -327,7 +345,7 @@ get_file_features(Elf *elf, int phcount, int fd, u_int
namesz = roundup2(note.n_namesz, 4);
name = malloc(namesz);
if (name == NULL) {
- warn("malloc() failed.\n");
+ warn("malloc() failed.");
return (false);
}
descsz = roundup2(note.n_descsz, 4);
@@ -339,7 +357,7 @@ get_file_features(Elf *elf, int phcount, int fd, u_int
note.n_type != NT_FREEBSD_FEATURE_CTL) {
/* Not the right note. Skip the description */
if (lseek(fd, descsz, SEEK_CUR) < 0) {
- warn("lseek() failed.\n");
+ warn("lseek() failed.");
free(name);
return (false);
}
@@ -360,7 +378,7 @@ get_file_features(Elf *elf, int phcount, int fd, u_int
* descriptor. This should respect descsz.
*/
if (note.n_descsz > sizeof(u_int32_t))
- warnx("Feature note is bigger than expected.");
+ warnx("Feature note is bigger than expected");
read(fd, features, sizeof(u_int32_t));
if (off != NULL)
*off = phdr.p_offset + read_total;
@@ -369,6 +387,6 @@ get_file_features(Elf *elf, int phcount, int fd, u_int
}
}
- warnx("Couldn't find a note header with control feature note.");
+ warnx("NT_FREEBSD_FEATURE_CTL note not found");
return (false);
}
More information about the svn-src-stable-12
mailing list