[lld] [lld/ELF] Add --override-section-flags flag (PR #109454)
Peter Smith via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 27 05:37:01 PDT 2024
smithp35 wrote:
Apologies for taking so long to reply, I didn't catch the github notification.
> > To make sure I understand, the desire is to have an area of the program that is mapped read-only by the dynamic-linker, ideally aligned on page boundaries.
>
> Right.
>
> > The application, presumably using some kind of linker generated _start and _stop will dynamically alter the permission to write to the section.
>
> When the code wants to write to a variable in such protected memory, it does something like:
>
> ```
> void* p = round_to_page_boundary(&my_variable);
> mprotect(p, READWRITE);
> my_variable = 42;
> mprotect(p, READONLY);
> ```
>
> > This sounds like it is almost exactly what you want
>
> Kinda? We want to be able to write to the variable at any time during the program's execution.
>
> The idea is for variables in this section to be regular variables, but since pages in this section are readonly most of the time, they're protected from heap spraying attacks (…most of the time).
>
My thought was that extending `.data.rel.ro` may be a better starting point for you. The compiler and assembler can still use RW. The static linker's section ordering will place the sections with the other RW and not in the RO (if section flags are overridden from RW to RO). The sections can still contain dynamic relocations. What I think we're missing is enough isolation from the other RELRO sections (page boundaries) so that the data can be temporarily mapped as RW without giving access to the other RELRO sections.
Possibly some subset of `.data.rel.ro` say `.data.rel.ro.mostlyro.*` that LLD would treat as .relro but would page align and would have the size padded out to a page boundary.
> > What flags are supported by the option
>
> Currently 'a', 'w', 'x' as described in the help text :)
>
> > If you support overwrite, what about modify? F
>
> Might be nice for a follow-up.
>
> > How does it interact with a PHDRS command that changes the flags like your example above?
>
> You mean in a linker script? Or is it possible to change PHDRS without a linker script? (If not, I'd say just error out when seeing both this flag and a linker script, at least for starters.)
>
Yes I mean PHDRS as a linker script.
> > If a section is marked read-only should the linker forbid dynamic relocations? I would expect so.
>
> Can you say more about this?
The linker will only permit dynamic relocations in writeable segments, at least not without `-z text` which is frowned upon as it permits dynamic relocations in code-sections. The .data.rel.ro sections can contain dynamic relocations as they are writeable.
If the data in these sections are just constants then they won't need dynamic relocations. However if any of them are initialised to an address, this will need a dynamic relocation if the address is imported from a shared object, or if the program is position independent.
>
> In general, I'm trying to go for "simplest thing that could work" here. If there's desire to make this work in more cases in the future to address additional use cases, we can always tweak it later :) (…and make it restrictive enough in this first version to not paint ourselves in a corner)
I think that the option could work for this use case. My concern is that the option is so general that I can see people finding it, picking it up and thinking that's just what I need, then finding that it either crashes the linker or doesn't do what they want it to do, which then provokes questions/issues etc.
Anyway this is just my opinion. Maybe worth asking MaskRay for his thoughts?
https://github.com/llvm/llvm-project/pull/109454
More information about the llvm-commits
mailing list