summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Kashkarov <m.kashkarov@partner.samsung.com>2019-04-15 14:15:49 +0300
committerSlava Barinov <v.barinov@samsung.com>2019-12-16 15:28:16 +0300
commit793d9e3fde1a643df92c4bb8c52415844921a2e9 (patch)
treeae0749c19724720ab14621336b06bc50c7f80996
parent3ba82f954de75b2236040c068470aa4331983f3b (diff)
downloadbinutils-793d9e3fde1a643df92c4bb8c52415844921a2e9.tar.gz
binutils-793d9e3fde1a643df92c4bb8c52415844921a2e9.tar.bz2
binutils-793d9e3fde1a643df92c4bb8c52415844921a2e9.zip
Add .note.gnu.property runtime verification and merge support
- Define annobin .note.gnu.property bits for sanitization/CxxABI checks - New configure option --enable-annobin-verification=warn|strict to enable runtime verification support for gnu property notes. - Add merging support for compilation flags annobin gnu notes. - Add readelf section text for compiler properties. Change-Id: I452029baca753f6a97ef4b7297ef9a8905a7b79c
-rw-r--r--bfd/config.in6
-rwxr-xr-xbfd/configure33
-rw-r--r--bfd/configure.ac21
-rw-r--r--bfd/elf-bfd.h1
-rw-r--r--bfd/elf-properties.c166
-rw-r--r--binutils/readelf.c26
-rw-r--r--include/elf/common.h11
-rw-r--r--packaging/binutils-aarch64.spec2
-rw-r--r--packaging/binutils-armv7hl.spec2
-rw-r--r--packaging/binutils-armv7l.spec2
-rw-r--r--packaging/binutils.spec2
11 files changed, 270 insertions, 2 deletions
diff --git a/bfd/config.in b/bfd/config.in
index be572969fc0..01c38b7c4c1 100644
--- a/bfd/config.in
+++ b/bfd/config.in
@@ -13,6 +13,12 @@
/* Define to 1 if you want to enable -z separate-code in ELF linker by
default. */
#undef DEFAULT_LD_Z_SEPARATE_CODE
+/* Define to enable annobin runtime checks for static linker (warnings only)
+ */
+#undef ENABLE_ANNOBIN_VERIFICATION
+
+/* Define to enable annobin runtime strict checks (error mode) */
+#undef ENABLE_ANNOBIN_VERIFICATION_STRICT
/* Define to 1 if translation of program messages to the user's native
language is requested. */
diff --git a/bfd/configure b/bfd/configure
index a292a2ed280..50e4bd35196 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -832,6 +832,7 @@ with_mmap
enable_secureplt
enable_separate_code
enable_leading_mingw64_underscores
+enable_annobin_verification
with_separate_debug_dir
with_pkgversion
with_bugurl
@@ -1490,6 +1491,9 @@ Optional Features:
--enable-separate-code enable -z separate-code in ELF linker by default
--enable-leading-mingw64-underscores
Enable leading underscores on 64 bit mingw targets
+ --enable-annobin-verification[=warn|strict]
+ enable runtime checks with dynamic notes generated
+ by annobin plugin
--enable-werror treat compile warnings as errors
--enable-build-warnings enable build-time compiler warnings
--enable-maintainer-mode
@@ -11728,7 +11732,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11731 "configure"
+#line 11735 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11834,7 +11838,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11837 "configure"
+#line 11841 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12507,6 +12511,31 @@ $as_echo "#define USE_MINGW64_LEADING_UNDERSCORES 1" >>confdefs.h
fi
+# Check whether --enable-annobin_verification was given.
+if test "${enable_annobin_verification+set}" = set; then :
+ enableval=$enable_annobin_verification; case "${enableval}" in
+ yes | warn | "" ) annobin_verification=warn ;;
+ strict ) annobin_verification=strict ;;
+ no) annobin_verification=no ;;
+ *) annobin_verification=no ;;
+ esac
+else
+ annobin_verification=no
+fi
+
+if test "$annobin_verification" = "yes" ||
+ test "$annobin_verification" = "warn" ||
+ test "$annobin_verification" = "strict"; then
+
+$as_echo "#define ENABLE_ANNOBIN_VERIFICATION 1" >>confdefs.h
+
+ if test "$annobin_verification" = "strict"; then
+
+$as_echo "#define ENABLE_ANNOBIN_VERIFICATION_STRICT 1" >>confdefs.h
+
+ fi
+fi
+
DEBUGDIR=${libdir}/debug
# Check whether --with-separate-debug-dir was given.
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 39702ce1315..a492b262c63 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -126,6 +126,27 @@ AS_IF([ test x"$enable_leading_mingw64_underscores" = xyes ],
[AC_DEFINE(USE_MINGW64_LEADING_UNDERSCORES, 1,
[Define if we should use leading underscore on 64 bit mingw targets])])
+AC_ARG_ENABLE(annobin_verification,
+[AS_HELP_STRING([[--enable-annobin-verification[=warn|strict]]],
+[enable runtime checks with dynamic notes generated by annobin plugin])],
+[case "${enableval}" in
+ yes | warn | "" ) annobin_verification=warn ;;
+ strict ) annobin_verification=strict ;;
+ no) annobin_verification=no ;;
+ *) annobin_verification=no ;;
+ esac],
+[annobin_verification=no])
+if test "$annobin_verification" = "yes" ||
+ test "$annobin_verification" = "warn" ||
+ test "$annobin_verification" = "strict"; then
+ AC_DEFINE(ENABLE_ANNOBIN_VERIFICATION, 1,
+ [Define to enable annobin runtime checks for static linker (warnings only)])
+ if test "$annobin_verification" = "strict"; then
+ AC_DEFINE(ENABLE_ANNOBIN_VERIFICATION_STRICT, 1,
+ [Define to enable annobin runtime strict checks (error mode)])
+ fi
+fi
+
DEBUGDIR=${libdir}/debug
AC_ARG_WITH(separate-debug-dir,
AS_HELP_STRING([--with-separate-debug-dir=DIR],
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 521d35debb0..7905b37c5ee 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -831,6 +831,7 @@ typedef struct elf_property
/* Add a new one if elf_property_kind is updated. */
} u;
enum elf_property_kind pr_kind;
+ const char *filename;
} elf_property;
typedef struct elf_property_list
diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c
index 198eece0843..b510b21fc02 100644
--- a/bfd/elf-properties.c
+++ b/bfd/elf-properties.c
@@ -69,6 +69,7 @@ _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
memset (p, 0, sizeof (*p));
p->property.pr_type = type;
p->property.pr_datasz = datasz;
+ p->property.filename = abfd->filename;
p->next = *lastp;
*lastp = p;
return &p->property;
@@ -177,6 +178,26 @@ bad_size:
prop->pr_kind = property_number;
goto next;
+ case GNU_PROPERTY_COMPILER_FLAGS:
+ /* Note that annobin uses 4-byte alignment even on 64-bit targets. */
+ if (!((datasz == 4) || (datasz == 8)))
+ {
+ _bfd_error_handler
+ (_("warning: %B: corrupt compiler flags: 0x%x\n"),
+ abfd, datasz);
+ /* Clear all properties. */
+ elf_properties (abfd) = NULL;
+ return FALSE;
+ }
+ prop = _bfd_elf_get_property (abfd, type, datasz);
+ if (datasz == 8)
+ prop->u.number = bfd_h_get_64 (abfd, ptr);
+ else
+ prop->u.number = bfd_h_get_32 (abfd, ptr);
+
+ prop->pr_kind = property_number;
+ goto next;
+
default:
break;
}
@@ -193,6 +214,110 @@ next:
return TRUE;
}
+/* If validation bits are set - compare bit flags for equality. */
+inline static bfd_boolean
+elf_gnu_property_validate_flag (bfd_vma anum,
+ bfd_vma bnum,
+ bfd_vma validation_bit_flag,
+ bfd_vma validation_bit)
+{
+ if ((anum & validation_bit_flag) && (bnum & validation_bit_flag)
+ && ((anum & validation_bit) != (bnum & validation_bit)))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bfd_boolean
+elf_validate_compiler_flags_properties (elf_property *aprop,
+ elf_property *bprop)
+{
+ bfd_boolean is_flag_set;
+
+ /* Sanity check to verify correct usage. */
+ BFD_ASSERT(aprop);
+ BFD_ASSERT(bprop);
+
+ if (aprop->pr_type != bprop->pr_type)
+ return TRUE;
+
+ BFD_ASSERT(aprop->pr_type == GNU_PROPERTY_COMPILER_FLAGS);
+
+ /* Return TRUE if compiler flags are identical (likely?). */
+ if (aprop->u.number == bprop->u.number)
+ return TRUE;
+
+ if (!elf_gnu_property_validate_flag(aprop->u.number,
+ bprop->u.number,
+ GNU_PROPERTY_SANITIZE_VALIDATION,
+ GNU_PROPERTY_SANITIZE_ADDRESS))
+ {
+ is_flag_set = bprop->u.number & GNU_PROPERTY_SANITIZE_ADDRESS;
+ _bfd_error_handler
+ (_("%s: ERROR: Validation failed, linking %s object with previous %s"),
+ bprop->filename, is_flag_set ? "sanitized" : "unsanitized",
+ !is_flag_set ? "sanitized" : "unsanitized");
+ return FALSE;
+ }
+
+ if (!elf_gnu_property_validate_flag(aprop->u.number,
+ bprop->u.number,
+ GNU_PROPERTY_USECXX_VALIDATION,
+ GNU_PROPERTY_USECXX11_ABI))
+ {
+ is_flag_set = bprop->u.number & GNU_PROPERTY_USECXX11_ABI;
+ _bfd_error_handler
+ (_("ERROR: Validation failed, linking %s ABI object with %s ABI"),
+ bprop->filename, is_flag_set ? "pre-cxx11" : "cxx11",
+ !is_flag_set ? "pre-cxx11" : "cxx11");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* Merge bprop into aprop according compiler-flags properties, return TRUE if */
+/* aprop is updated. */
+static bfd_boolean
+elf_merge_gnu_properties_compiler_flags (elf_property *aprop,
+ elf_property *bprop)
+{
+ bfd_boolean is_updated = FALSE;
+ /* Likely that objects have the same properties. */
+ if (aprop->u.number == bprop->u.number) {
+ return FALSE;
+ }
+
+ /* Validation bit + no-validation bit = validation bit. */
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_VALIDATION)
+ {
+ aprop->u.number |= GNU_PROPERTY_SANITIZE_VALIDATION;
+ is_updated = TRUE;
+ }
+ /* Sanitized object + unsanitized results = sanitized final object. */
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_ADDRESS)
+ {
+ aprop->u.number |= GNU_PROPERTY_SANITIZE_ADDRESS;
+ is_updated = TRUE;
+ }
+
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX_VALIDATION)
+ {
+ aprop->u.number |= GNU_PROPERTY_USECXX_VALIDATION;
+ is_updated = TRUE;
+ }
+
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX11_ABI)
+ {
+ aprop->u.number |= GNU_PROPERTY_USECXX11_ABI;
+ is_updated = TRUE;
+ }
+
+ return is_updated;
+}
+
/* Merge GNU property BPROP with APROP. If APROP isn't NULL, return TRUE
if APROP is updated. Otherwise, return TRUE if BPROP should be merged
with ABFD. */
@@ -227,6 +352,44 @@ elf_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, bfd *bbfd,
/* Return TRUE if APROP is NULL to indicate that BPROP should
be added to ABFD. */
return aprop == NULL;
+ /* FALLTHROUGH */
+
+ case GNU_PROPERTY_COMPILER_FLAGS:
+ {
+ bfd_boolean is_updated;
+ if (aprop != NULL && bprop != NULL)
+ {
+#ifdef ENABLE_ANNOBIN_VERIFICATION
+ if (!elf_validate_compiler_flags_properties (aprop, bprop))
+ {
+ _bfd_error_handler(_("ERROR: Linking failed due to incompatible "
+ "compilation flags used to generate objects\n"));
+ /* Strict mode, abort. */
+#ifdef ENABLE_ANNOBIN_VERIFICATION_STRICT
+ _exit (EXIT_FAILURE);
+#endif
+ }
+#endif
+ is_updated = elf_merge_gnu_properties_compiler_flags (aprop, bprop);
+ }
+ else
+ {
+ is_updated = FALSE;
+ /* aprop or bprop is NULL, warn for missing GNU_PROPERTY_COMPILER_FLAGS.
+
+ This is too noisy since glibc's crt{i,n}.o are compiled with
+ predefined flags (without annobin support), so we'll have at
+ least 2x of the following warning for every linking. May be
+ enabled after we verified crt* compilation with plugins. */
+ /* if (bprop == NULL)
+ _bfd_error_handler
+ (_("WARNING: not found (generated by annobin gcc plugin), "
+ "runtime verification may be incomplete"),
+ NOTE_GNU_PROPERTY_SECTION_NAME); */
+ }
+ return is_updated;
+ }
+ /* FALLTHROUGH */
default:
/* Never should happen. */
@@ -601,6 +764,9 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
NOTE_GNU_PROPERTY_SECTION_NAME);
BFD_ASSERT (sec != NULL);
+ if (!sec)
+ return;
+
/* Update stack size in .note.gnu.property with -z stack-size=N
if N > 0. */
if (info->stacksize > 0)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 0962877ad8f..7f22c58dbe5 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -17750,6 +17750,20 @@ decode_aarch64_feature_1_and (unsigned int bitmask)
}
static void
+decode_compiler_flags_notes (unsigned long bitmask)
+{
+ printf("%#lx [", bitmask);
+
+ printf("%c%ccxx11, ", bitmask & GNU_PROPERTY_USECXX_VALIDATION ? '=' : '~',
+ bitmask & GNU_PROPERTY_USECXX11_ABI ? '+' : '!');
+
+ printf("%c%casan", bitmask & GNU_PROPERTY_SANITIZE_VALIDATION ? '=' : '~',
+ bitmask & GNU_PROPERTY_SANITIZE_ADDRESS ? '+' : '!');
+
+ printf("]");
+}
+
+static void
print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
{
unsigned char * ptr = (unsigned char *) pnote->descdata;
@@ -17914,6 +17928,18 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
printf (_("<corrupt length: %#x> "), datasz);
goto next;
+ case GNU_PROPERTY_COMPILER_FLAGS:
+ printf ("compilations flags: ");
+ if ((datasz != 4) && (datasz != 8))
+ printf (_("<corrupt length: %#x> "), datasz);
+ else
+ {
+ unsigned long bitmask_flags;
+ bitmask_flags = (unsigned long) byte_get (ptr, size);
+ decode_compiler_flags_notes (bitmask_flags);
+ }
+ goto next;
+
default:
break;
}
diff --git a/include/elf/common.h b/include/elf/common.h
index 75c4fb7e9d7..182818eb865 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -741,6 +741,17 @@
/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
#define GNU_PROPERTY_STACK_SIZE 1
#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
+#define GNU_PROPERTY_COMPILER_FLAGS 32
+
+/* Bit masks for compiler flags: */
+/* Pre/post cxx11 ABI. */
+#define GNU_PROPERTY_USECXX_VALIDATION (1U << 0)
+#define GNU_PROPERTY_USECXX11_ABI (1U << 1)
+/* Sanitizer flags. */
+#define GNU_PROPERTY_SANITIZE_VALIDATION (1U << 2)
+#define GNU_PROPERTY_SANITIZE_ADDRESS (1U << 3)
+#define GNU_PROPERTY_SANITIZE_UNDEFINED (1U << 4)
+#define GNU_PROPERTY_SANITIZE_THREAD (1U << 5)
/* Processor-specific semantics, lo */
#define GNU_PROPERTY_LOPROC 0xc0000000
diff --git a/packaging/binutils-aarch64.spec b/packaging/binutils-aarch64.spec
index 4c3e55f33a4..3460085f172 100644
--- a/packaging/binutils-aarch64.spec
+++ b/packaging/binutils-aarch64.spec
@@ -104,6 +104,8 @@ cd build-dir
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \
diff --git a/packaging/binutils-armv7hl.spec b/packaging/binutils-armv7hl.spec
index c1b09e30a3a..ecdde918eff 100644
--- a/packaging/binutils-armv7hl.spec
+++ b/packaging/binutils-armv7hl.spec
@@ -104,6 +104,8 @@ cd build-dir
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \
diff --git a/packaging/binutils-armv7l.spec b/packaging/binutils-armv7l.spec
index 422c4536229..bedf7a15abb 100644
--- a/packaging/binutils-armv7l.spec
+++ b/packaging/binutils-armv7l.spec
@@ -104,6 +104,8 @@ cd build-dir
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \
diff --git a/packaging/binutils.spec b/packaging/binutils.spec
index 7f2479d63cd..f98fd941720 100644
--- a/packaging/binutils.spec
+++ b/packaging/binutils.spec
@@ -101,6 +101,8 @@ cd build-dir
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \