@@ -177,6 +177,20 @@ _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
prop->pr_kind = property_number;
goto next;
+ case GNU_PROPERTY_MEMORY_SEAL:
+ if (datasz != 0)
+ {
+ _bfd_error_handler
+ (_("warning: %pB: corrupt memory sealing size: 0x%x"),
+ abfd, datasz);
+ /* Clear all properties. */
+ elf_properties (abfd) = NULL;
+ return false;
+ }
+ prop = _bfd_elf_get_property (abfd, type, datasz);
+ prop->pr_kind = property_number;
+ goto next;
+
default:
if ((type >= GNU_PROPERTY_UINT32_AND_LO
&& type <= GNU_PROPERTY_UINT32_AND_HI)
@@ -254,6 +268,7 @@ elf_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, bfd *bbfd,
/* FALLTHROUGH */
case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+ case GNU_PROPERTY_MEMORY_SEAL:
/* Return TRUE if APROP is NULL to indicate that BPROP should
be added to ABFD. */
return aprop == NULL;
@@ -607,6 +622,33 @@ elf_write_gnu_properties (struct bfd_link_info *info,
}
}
+static asection *
+_bfd_elf_link_create_gnu_property_sec (struct bfd_link_info *info, bfd *elf_bfd,
+ unsigned int elfclass)
+{
+ asection *sec;
+
+ sec = bfd_make_section_with_flags (elf_bfd,
+ NOTE_GNU_PROPERTY_SECTION_NAME,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_HAS_CONTENTS
+ | SEC_DATA));
+ if (sec == NULL)
+ info->callbacks->einfo (_("%F%P: failed to create GNU property section\n"));
+
+ if (!bfd_set_section_alignment (sec,
+ elfclass == ELFCLASS64 ? 3 : 2))
+ info->callbacks->einfo (_("%F%pA: failed to align section\n"),
+ sec);
+
+ elf_section_type (sec) = SHT_NOTE;
+ return sec;
+}
+
+
/* Set up GNU properties. Return the first relocatable ELF input with
GNU properties if found. Otherwise, return NULL. */
@@ -656,23 +698,7 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
/* Support -z indirect-extern-access. */
if (first_pbfd == NULL)
{
- sec = bfd_make_section_with_flags (elf_bfd,
- NOTE_GNU_PROPERTY_SECTION_NAME,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_HAS_CONTENTS
- | SEC_DATA));
- if (sec == NULL)
- info->callbacks->einfo (_("%F%P: failed to create GNU property section\n"));
-
- if (!bfd_set_section_alignment (sec,
- elfclass == ELFCLASS64 ? 3 : 2))
- info->callbacks->einfo (_("%F%pA: failed to align section\n"),
- sec);
-
- elf_section_type (sec) = SHT_NOTE;
+ sec = _bfd_elf_link_create_gnu_property_sec (info, elf_bfd, elfclass);
first_pbfd = elf_bfd;
has_properties = true;
}
@@ -690,6 +716,31 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
|= GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS;
}
+ if (elf_bfd != NULL)
+ {
+ if (info->memory_seal)
+ {
+ /* Support -z no-memory-seal. */
+ if (first_pbfd == NULL)
+ {
+ sec = _bfd_elf_link_create_gnu_property_sec (info, elf_bfd, elfclass);
+ first_pbfd = elf_bfd;
+ has_properties = true;
+ }
+
+ p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_MEMORY_SEAL, 0);
+ if (p->pr_kind == property_unknown)
+ {
+ /* Create GNU_PROPERTY_NO_MEMORY_SEAL. */
+ p->u.number = GNU_PROPERTY_MEMORY_SEAL;
+ p->pr_kind = property_number;
+ }
+ }
+ else
+ elf_find_and_remove_property (&elf_properties (elf_bfd),
+ GNU_PROPERTY_MEMORY_SEAL, true);
+ }
+
/* Do nothing if there is no .note.gnu.property section. */
if (!has_properties)
return NULL;
@@ -4896,7 +4896,8 @@ _bfd_x86_elf_link_fixup_gnu_properties
for (p = *listp; p; p = p->next)
{
unsigned int type = p->property.pr_type;
- if (type == GNU_PROPERTY_X86_COMPAT_ISA_1_USED
+ if (type == GNU_PROPERTY_MEMORY_SEAL
+ || type == GNU_PROPERTY_X86_COMPAT_ISA_1_USED
|| type == GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED
|| (type >= GNU_PROPERTY_X86_UINT32_AND_LO
&& type <= GNU_PROPERTY_X86_UINT32_AND_HI)
@@ -21457,6 +21457,12 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
printf (_("<corrupt length: %#x> "), datasz);
goto next;
+ case GNU_PROPERTY_MEMORY_SEAL:
+ printf ("memory seal ");
+ if (datasz)
+ printf (_("<corrupt length: %#x> "), datasz);
+ goto next;
+
default:
if ((type >= GNU_PROPERTY_UINT32_AND_LO
&& type <= GNU_PROPERTY_UINT32_AND_HI)
@@ -429,6 +429,9 @@ struct bfd_link_info
/* TRUE if only one read-only, non-code segment should be created. */
unsigned int one_rosegment: 1;
+ /* TRUE if GNU_PROPERTY_MEMORY_SEAL should be generated. */
+ unsigned int memory_seal: 1;
+
/* Nonzero if .eh_frame_hdr section and PT_GNU_EH_FRAME ELF segment
should be created. 1 for DWARF2 tables, 2 for compact tables. */
unsigned int eh_frame_hdr_type: 2;
@@ -890,6 +890,7 @@
/* 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_MEMORY_SEAL 3
/* A 4-byte unsigned integer property: A bit is set if it is set in all
relocatable inputs. */
@@ -33,6 +33,9 @@ Changes in 2.43:
* Add -plugin-save-temps to store plugin intermediate files permanently.
+* Add -z memory-seal/-z nomemory-seal options to ELF linker to mark the
+ object to memory sealed.
+
Changes in 2.42:
* Add -z mark-plt/-z nomark-plt options to x86-64 ELF linker to mark PLT
@@ -1083,6 +1083,10 @@ fragment <<EOF
link_info.combreloc = false;
else if (strcmp (optarg, "nocopyreloc") == 0)
link_info.nocopyreloc = true;
+ else if (strcmp (optarg, "memory-seal") == 0)
+ link_info.memory_seal = true;
+ else if (strcmp (optarg, "nomemory-seal") == 0)
+ link_info.memory_seal = false;
EOF
if test -n "$COMMONPAGESIZE"; then
fragment <<EOF
@@ -1590,6 +1590,14 @@ Disable relocation overflow check. This can be used to disable
relocation overflow check if there will be no dynamic relocation
overflow at run-time. Supported for x86_64.
+@item memory-seal
+@item nomemory-seal
+Instruct the executable or shared library that the all PT_LOAD segments
+should be sealed to avoid further manipulation (such as changing the
+protection flags, the segment size, or remove the mapping).
+This is a security hardening that requires system support. This
+generates GNU_PROPERTY_MEMORY_SEAL in .note.gnu.property section
+
@item now
When generating an executable or shared library, mark it to tell the
dynamic linker to resolve all symbols when the program is started, or
@@ -2265,6 +2265,10 @@ elf_shlib_list_options (FILE *file)
fprintf (file, _("\
-z textoff Don't treat DT_TEXTREL in output as error\n"));
}
+ fprintf (file, _("\
+ -z memory-seal Mark object be memory sealed\n"));
+ fprintf (file, _("\
+ -z nomemory-seal Don't mark oject to be memory sealed (default)\n"));
}
static void
new file mode 100644
@@ -0,0 +1,16 @@
+# Check if a GNU_PROPERTY_MEMORY_SEAL on a ET_REL is not replicated on
+# ET_DYN.
+#source: property-seal-1.s
+#as: --generate-missing-build-notes=no
+#ld: -shared
+#readelf: -n
+#xfail: ![check_shared_lib_support]
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#failif
+#...
+Displaying notes found in: .note.gnu.property
+#pass
new file mode 100644
@@ -0,0 +1,11 @@
+ .section ".note.gnu.property", "a"
+ .p2align ALIGN
+ .long 1f - 0f /* name length */
+ .long 3f - 2f /* data length */
+ .long 5 /* note type */
+0: .asciz "GNU" /* vendor name */
+1:
+ .p2align ALIGN
+2: .long 3 /* pr_type. */
+ .long 0 /* pr_datasz. */
+3:
new file mode 100644
@@ -0,0 +1,17 @@
+# Check if a GNU_PROPERTY_MEMORY_SEAL on a ET_REL is not replicated on
+# ET_DYN.
+#source: empty.s
+#source: property-seal-1.s
+#as: --generate-missing-build-notes=no
+#ld: -shared
+#readelf: -n
+#xfail: ![check_shared_lib_support]
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#failif
+#...
+Displaying notes found in: .note.gnu.property
+#pass
new file mode 100644
@@ -0,0 +1,16 @@
+# Check if a GNU_PROPERTY_MEMORY_SEAL on a ET_REL is not replicated on
+# ET_EXEC.
+#source: property-seal-1.s
+#as: --generate-missing-build-notes=no
+#ld: -e _start
+#warning: .*: warning: cannot find entry symbol .*
+#readelf: -n
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#failif
+#...
+Displaying notes found in: .note.gnu.property
+#pass
new file mode 100644
@@ -0,0 +1,16 @@
+# Check if a GNU_PROPERTY_MEMORY_SEAL on a ET_REL is not replicated on
+# ET_EXEC.
+#source: empty.s
+#source: property-seal-1.s
+#as: --generate-missing-build-notes=no
+#ld: -e _start
+#readelf: -n
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#failif
+#...
+Displaying notes found in: .note.gnu.property
+#pass
new file mode 100644
@@ -0,0 +1,15 @@
+#source: empty.s
+#ld: -shared -z memory-seal
+#readelf: -n
+#xfail: ![check_shared_lib_support]
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: memory seal
+#pass
new file mode 100644
@@ -0,0 +1,16 @@
+#source: empty.s
+#source: property-seal-1.s
+#ld: -shared -z memory-seal
+#readelf: -n
+#xfail: ![check_shared_lib_support]
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: memory seal
+#pass
new file mode 100644
@@ -0,0 +1,14 @@
+#source: empty.s
+#ld: -z memory-seal
+#readelf: -n
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: memory seal
+#pass
new file mode 100644
@@ -0,0 +1,15 @@
+#source: empty.s
+#source: property-seal-1.s
+#ld: -z memory-seal
+#readelf: -n
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: memory seal
+#pass