-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[ELF] --no-rosegment: don't mark read-only PT_LOAD segments executable #81223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2353,17 +2353,12 @@ static bool needsPtLoad(OutputSection *sec) { | |
return true; | ||
} | ||
|
||
// Linker scripts are responsible for aligning addresses. Unfortunately, most | ||
// linker scripts are designed for creating two PT_LOADs only, one RX and one | ||
// RW. This means that there is no alignment in the RO to RX transition and we | ||
// cannot create a PT_LOAD there. | ||
// Adjust phdr flags according to certain options. | ||
static uint64_t computeFlags(uint64_t flags) { | ||
if (config->omagic) | ||
return PF_R | PF_W | PF_X; | ||
if (config->executeOnly && (flags & PF_X)) | ||
return flags & ~PF_R; | ||
if (config->singleRoRx && !(flags & PF_W)) | ||
return flags | PF_X; | ||
return flags; | ||
} | ||
|
||
|
@@ -2451,7 +2446,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) { | |
// Segments are contiguous memory regions that has the same attributes | ||
// (e.g. executable or writable). There is one phdr for each segment. | ||
// Therefore, we need to create a new phdr when the next section has | ||
// different flags or is loaded at a discontiguous address or memory region | ||
// compatible flags or is loaded at a discontiguous address or memory region | ||
// using AT or AT> linker script command, respectively. | ||
// | ||
// As an exception, we don't create a separate load segment for the ELF | ||
|
@@ -2465,13 +2460,22 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) { | |
// so when hasSectionsCommand, since we cannot introduce the extra alignment | ||
// needed to create a new LOAD) | ||
uint64_t newFlags = computeFlags(sec->getPhdrFlags()); | ||
// When --no-rosegment is specified, RO and RX sections are compatible. | ||
uint32_t diff = flags ^ newFlags; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could be worth calling diff
Not got a strong opinion, could go with either. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renamed |
||
if (config->singleRoRx && !(newFlags & PF_W)) | ||
diff &= ~PF_X; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's an interesting conflict here between singleRoRx and execute-only, could be worth making these options incompatible in Driver.cpp as singleRoRx breaks execute-only. This isn't a regression caused by this patch though so could be done in a different patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The initial It also has this error |
||
if (diff) | ||
load = nullptr; | ||
|
||
bool sameLMARegion = | ||
load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion; | ||
if (!(load && newFlags == flags && sec != relroEnd && | ||
sec->memRegion == load->firstSec->memRegion && | ||
(sameLMARegion || load->lastSec == Out::programHeaders) && | ||
(script->hasSectionsCommand || sec->type == SHT_NOBITS || | ||
load->lastSec->type != SHT_NOBITS))) { | ||
if (load && sec != relroEnd && | ||
sec->memRegion == load->firstSec->memRegion && | ||
(sameLMARegion || load->lastSec == Out::programHeaders) && | ||
(script->hasSectionsCommand || sec->type == SHT_NOBITS || | ||
load->lastSec->type != SHT_NOBITS)) { | ||
load->p_flags |= newFlags; | ||
} else { | ||
load = addHdr(PT_LOAD, newFlags); | ||
flags = newFlags; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean "create a new phdr when the next section has incompatible flags"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the catch. Fixed the typo