ELF: Reserve space for copy relocations of read-only symbols in relro.
When reserving copy relocation space for a shared symbol, scan the DSO's
program headers to see if the symbol is in a read-only segment. If so,
reserve space for that symbol in a new synthetic section named .bss.rel.ro
which will be covered by the relro program header.
This fixes the security issue disclosed on the binutils mailing list at:
https://sourceware.org/ml/libc-alpha/2016-12/msg00914.html
Differential Revision: https://reviews.llvm.org/D28272
llvm-svn: 291524
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1d0cb7c..bddc42e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -250,6 +250,8 @@
// Create singleton output sections.
Out<ELFT>::Bss =
make<OutputSection<ELFT>>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
+ Out<ELFT>::BssRelRo = make<OutputSection<ELFT>>(".bss.rel.ro", SHT_NOBITS,
+ SHF_ALLOC | SHF_WRITE);
In<ELFT>::DynStrTab = make<StringTableSection<ELFT>>(".dynstr", true);
In<ELFT>::Dynamic = make<DynamicSection<ELFT>>();
Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>();
@@ -498,6 +500,8 @@
return true;
if (In<ELFT>::MipsGot && Sec == In<ELFT>::MipsGot->OutSec)
return true;
+ if (Sec == Out<ELFT>::BssRelRo)
+ return true;
StringRef S = Sec->getName();
return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
S == ".eh_frame" || S == ".openbsd.randomdata";
@@ -1079,6 +1083,8 @@
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
if (Out<ELFT>::Bss->Size > 0)
OutputSections.push_back(Out<ELFT>::Bss);
+ if (Out<ELFT>::BssRelRo->Size > 0)
+ OutputSections.push_back(Out<ELFT>::BssRelRo);
auto OS = dyn_cast_or_null<OutputSection<ELFT>>(findSection(".ARM.exidx"));
if (OS && !OS->Sections.empty() && !Config->Relocatable)