mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm] Mark ELF libraries produced directly by the VM as not requiring an executable stack.
Even if the main program disables executable stacks, dlopen'ing a library that doesn't itself disable executable stack will switch the stack to executable. (Presumably in the name of compatability with GNU nested functions.) Dart does not need executable stacks, and executable stacks are an additional attack surface. TEST=readelf Bug: b/229648756 Change-Id: Ia8c234ebc6178a26528d37b1359a10dd42039a9b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241540 Reviewed-by: Tess Strickland <sstrickl@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
d2eb2197a3
commit
32715d1d5b
|
@ -41,6 +41,7 @@ enum class ProgramHeaderType : uint32_t {
|
|||
PT_DYNAMIC = 2,
|
||||
PT_NOTE = 4,
|
||||
PT_PHDR = 6,
|
||||
PT_GNU_STACK = 0x6474e551,
|
||||
};
|
||||
|
||||
struct ProgramHeader {
|
||||
|
|
|
@ -229,12 +229,10 @@ class Section : public ZoneAllocated {
|
|||
|
||||
private:
|
||||
static intptr_t EncodeFlags(bool allocate, bool executable, bool writable) {
|
||||
// Executable and writable only make sense if this is an allocated section.
|
||||
ASSERT(allocate || (!executable && !writable));
|
||||
if (!allocate) return 0;
|
||||
intptr_t flags = elf::SHF_ALLOC;
|
||||
// We currently don't allow sections that are both executable and writable.
|
||||
ASSERT(!executable || !writable);
|
||||
intptr_t flags = 0;
|
||||
if (allocate) flags |= elf::SHF_ALLOC;
|
||||
if (executable) flags |= elf::SHF_EXECINSTR;
|
||||
if (writable) flags |= elf::SHF_WRITE;
|
||||
return flags;
|
||||
|
@ -265,7 +263,6 @@ class Segment : public ZoneAllocated {
|
|||
ASSERT(segment_type != elf::ProgramHeaderType::PT_NULL);
|
||||
// All segments should have at least one section.
|
||||
ASSERT(initial_section != nullptr);
|
||||
ASSERT(initial_section->IsAllocated());
|
||||
sections_.Add(initial_section);
|
||||
}
|
||||
|
||||
|
@ -282,6 +279,8 @@ class Segment : public ZoneAllocated {
|
|||
return compiler::target::kWordSize;
|
||||
case elf::ProgramHeaderType::PT_NOTE:
|
||||
return kNoteAlignment;
|
||||
case elf::ProgramHeaderType::PT_GNU_STACK:
|
||||
return 1;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
|
@ -379,6 +378,21 @@ class ReservedSection : public Section {
|
|||
intptr_t FileSize() const { return 0; }
|
||||
};
|
||||
|
||||
// Specifies the permissions used for the stack, notably whether the stack
|
||||
// should be executable. If absent, the stack will be executable.
|
||||
class GnuStackSection : public Section {
|
||||
public:
|
||||
GnuStackSection()
|
||||
: Section(elf::SectionHeaderType::SHT_NULL,
|
||||
/*allocate=*/false,
|
||||
/*executable=*/false,
|
||||
/*writable=*/true) {
|
||||
set_file_offset(0);
|
||||
}
|
||||
|
||||
intptr_t FileSize() const { return 0; }
|
||||
};
|
||||
|
||||
class StringTable : public Section {
|
||||
public:
|
||||
explicit StringTable(Zone* zone, bool allocate)
|
||||
|
@ -1658,6 +1672,12 @@ ProgramTable* SectionTable::CreateProgramTable(SymbolTable* symtab) {
|
|||
program_table->Add(
|
||||
new (zone_) Segment(zone_, dynamic, elf::ProgramHeaderType::PT_DYNAMIC));
|
||||
|
||||
// Add a PT_GNU_STACK segment to prevent the loading of our snapshot from
|
||||
// switch the stack to be executable.
|
||||
auto* const gnu_stack = new (zone_) GnuStackSection();
|
||||
program_table->Add(new (zone_) Segment(zone_, gnu_stack,
|
||||
elf::ProgramHeaderType::PT_GNU_STACK));
|
||||
|
||||
return program_table;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue