PT_GNU_STACK is a entry in the elf file format which contains the access rights (read, write, execute) of the stack,
it is always generated now. By default stack is not executable in this implementation.
-z execstack can be used to make executable.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
Is the logic implemented in this patch correct?
The stack is executable if and only if all object files contain .note.GNU-stack section. The logic implemented in this patch seems to make the stack executable at least one of input files contains .note.GNU-stack section.
It makes it executable only if this one .note.GNU-stack section marked as "x".
I think stack is executable always by default. When the linker performs linking, it marks the stack as executable based on the lowest common demoninator. For example, if everything is marked non-executable except one .o file, the entire library would get marked for an executable stack
Logic implemented makes PT_GNU_STACK header to be generated if at least one of input files contains .note.GNU-stack section. Will it be executable depends on flags of .note.GNU-stack section then. If at least one is executable then stack is marked as executable.
What is incorrect in this patch (just noticed) that if for example we have two .o files and one has ".section .note.GNU-stack,"",@progbits" (non executable) but second does not have .note.GNU-stack section at all then stack should be marked executable, but this patch does not makes it to be so. I`ll fix that in updated diff.
I would also suggest to think about changing the default logic from "stack is always executable by default" to opposite one. At least for some targets.
I dont think there are many apps that uses executable stacks. But having it executable is huge security hole.
We can implement -z execstack/-z noexecstack to control that for those who heeds executable one.
Below is the link to gold source comment about how stack stuff works.
https://android.googlesource.com/toolchain/binutils/+/53b6ed3bceea971857c996b6dcb96de96b99335f/binutils-2.19/gold/layout.cc#1942
I think that's a good suggestion, but that made me think of this: we may want to force users to specify -z execstack if they really want to make the stack executable. To me, controlling the stack executable-ness using .note.GNU-stack section is too subtle and fragile. If you have thousands of object files, and only one file >lacks .note.GNU-stack, the entire program's stack will be executable. It's unlikely to be an intended behavior, and if it is actually intended, I believe it is reasonable to tell so to the linker using the -z flag.
So I guess my point is
- ignore .note.GNU-stack sections at all,
- make stack non-executable by default,
- and implement -z execstack
What do you think?
For me sounds good.
I can update the patch to handle -z exectack instead of looking at .note.GNU-stack flags tomorrow.
PT_GNU_STACK header is always created (stack is readonly by default).
Lots of test were updated because of above.
-z execstack implemented.
ELF/Writer.cpp | ||
---|---|---|
545–546 ↗ | (On Diff #40211) | Do you mean ignore them in initializeSections ? Something like next ? switch (Sec.sh_type) { ... default: if (NameOrErr == ".note.GNU-stack") Sections[I] = &InputSection<ELFT>::Discarded; |
Yes.
2015/11/14 6:59 "George Rimar" <grimar@accesssoftek.com>:
grimar added inline comments.
Comment at: ELF/Writer.cpp:545-546
@@ -538,2 +544,4 @@continue;+ if (!shouldOutputSection(C))
+ continue;const Elf_Shdr *H = C->getSectionHdr();
ruiu wrote:
We don't use input files' .note.GNU-stack sections at all. Maybe we
should ignore them in .note.GNU-stack?
Do you mean ignore them in initializeSections ? Something like next ?switch (Sec.sh_type) { ... default: if (NameOrErr == ".note.GNU-stack") Sections[I] = &InputSection<ELFT>::Discarded;
test/elf2/gnustack.s | ||
---|---|---|
16 ↗ | (On Diff #40212) | This is checking way more than it needs. Check just the contents of PT_GNU_STACK and that we eat the section. |
Review comments addressed.
test/elf2/gnustack.s | ||
---|---|---|
16 ↗ | (On Diff #40212) | Ok. My way also checked that PT_GNU_STACK header is the last one but thats really probably not needed. |
This is breaking compatibility with legacy ELF loaders :( It should really be possible to create binaries without this stupid mess.
That needs the build systems patched. IMHO it would be better to be compatible with bfd & gold here and default to execstack.
ismail
On the other side almost no apps really needs stack to be executable and having it is a security issue in most cases.
Returning to the problem itself, do really many loaders does not support PT_GNU_STACK ? It seems to be old enough feature (I can see mails of 2007 year in main archive of the binutils@sourceware.org).
For FreeBSD we added support in January 2011, r217153. Because the issue was raised by @joerg I'd guess NetBSD's rtld doesn't support it.
Do we have a list of the ELF systems we desire to support in lld?
What do you mean by legacy? An old loader will just ignore this
program header, no?
Sorry, just read that that was not the case.
OK, I think we are all in agreement on the objective: non executable
stacks by default.
The problem them is that how to do it is dependent on the dynamic
linker, and we don't have a reliable way saying which dynamic linker
will be used.
How about
- -z execstack: add the program header marking the stack exectuable.
- -z noexecstack: add the program header marking the stack non exectuable.
- If neither, mark the stack non executable if we ever see
.note.GNU-stack. I.E., use it as an indication that the dynamic linker
uses that segment.
Cheers,
Rafael