mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-07 13:39:43 +08:00
elf: Add GNU_PROPERTY_MEMORY_SEAL gnu property
The GNU_PROPERTY_MEMORY_SEAL gnu property is a way to mark binaries to be memory sealed by the loader, to avoid further changes of PT_LOAD segments (such as unmapping or change permission flags). This is done along with Linux kernel (the mseal syscall [1]), and C runtime supports to instruct the kernel on the correct time during program startup (for instance, after RELRO handling). This support is added along the glibc support to handle the new gnu property [2]. This is a opt-in security features, like other security hardening ones like NX-stack or RELRO. The new property is ignored if present on ET_REL objects, and only added on ET_EXEC/ET_DYN if the linker option is used. A gnu property is used instead of DT_FLAGS_1 flag to allow memory sealing to work with ET_EXEC without PT_DYNAMIC support (at least on glibc some ports still do no support static-pie). [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8be7258aad44b5e25977a98db136f677fa6f4370 [2] https://sourceware.org/pipermail/libc-alpha/2024-September/160291.html Change-Id: Id47fadabecd24be0e83cff45653f7ce9a900ecf4
This commit is contained in:
parent
9f99abe9c0
commit
4d890484df
@ -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;
|
||||
|
@ -4892,7 +4892,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)
|
||||
|
@ -21477,6 +21477,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;
|
||||
|
@ -891,6 +891,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. */
|
||||
|
3
ld/NEWS
3
ld/NEWS
@ -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
|
||||
|
@ -1602,6 +1602,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
|
||||
|
16
ld/testsuite/ld-elf/property-seal-1.d
Normal file
16
ld/testsuite/ld-elf/property-seal-1.d
Normal file
@ -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
|
11
ld/testsuite/ld-elf/property-seal-1.s
Normal file
11
ld/testsuite/ld-elf/property-seal-1.s
Normal file
@ -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:
|
17
ld/testsuite/ld-elf/property-seal-2.d
Normal file
17
ld/testsuite/ld-elf/property-seal-2.d
Normal file
@ -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
|
16
ld/testsuite/ld-elf/property-seal-3.d
Normal file
16
ld/testsuite/ld-elf/property-seal-3.d
Normal file
@ -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
|
16
ld/testsuite/ld-elf/property-seal-4.d
Normal file
16
ld/testsuite/ld-elf/property-seal-4.d
Normal file
@ -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
|
15
ld/testsuite/ld-elf/property-seal-5.d
Normal file
15
ld/testsuite/ld-elf/property-seal-5.d
Normal file
@ -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
|
16
ld/testsuite/ld-elf/property-seal-6.d
Normal file
16
ld/testsuite/ld-elf/property-seal-6.d
Normal file
@ -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
|
14
ld/testsuite/ld-elf/property-seal-7.d
Normal file
14
ld/testsuite/ld-elf/property-seal-7.d
Normal file
@ -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
|
15
ld/testsuite/ld-elf/property-seal-8.d
Normal file
15
ld/testsuite/ld-elf/property-seal-8.d
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user