Skip to content
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

binutils: Add security patches #22272

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

lhmouse
Copy link
Contributor

@lhmouse lhmouse commented Oct 23, 2024

Before this commit, the .CRT section (which contains pointers to image TLS callbacks) and the .idata section (which contains __imp_ pointers to dllimport functions) that had been created by the GNU linker were writeable.

As these function pointers are essential for programs to be functional, they could be exploited to inject malicious code, like the well-known IFUNC backdoor in XZ Utils. The Microsoft linker does not create these sections as writeable; instead, they seem to be merged into .rdata and are not modifiable, unless unprotected.

LLD also does the same, suggesting these sections be merged into .rdata: https://github.com/llvm/llvm-project/blob/ebeb56af5f8f1ff9da8f5a7e98348f460d223de1/lld/COFF/Driver.cpp#L2034-L2048

This commit includes the following countermeasures:

  1. Patch 3005 ensures the final .CRT and .idata sections (if any) will not be writeable in the final image.
  2. Patch 3006 merges known sub-sections of .CRT, as well as .ctors and .dtors (which were merged into .text instead), into .rdata. Merging .idata into .rdata seems to prevent dllimport from working, so there's still an .idata section in the final image. See also: https://stackoverflow.com/questions/22651433/pe-idata-section

Reference: https://sourceware.org/bugzilla/show_bug.cgi?id=32264

@lhmouse
Copy link
Contributor Author

lhmouse commented Oct 23, 2024

I have rebuilt binutils, CRT, GCC and binutils again in MINGW32, MINGW64 and UCRT64, and no error has been observed.

Please examine this carefully.

@lhmouse lhmouse force-pushed the binutils-pkg branch 2 times, most recently from 9531b24 to 51247e1 Compare October 23, 2024 13:41
Before this commit, the `.CRT` section (which contains pointers to image TLS
callbacks) and the `.idata` section (which contains `__imp_` pointers to
dllimport functions) that had been created by the GNU linker were writeable.

As these functions to pointers are essential for programs to be functional,
they could be exploited to inject malicious code, like the well-known IFUNC
backdoor in XZ Utils. The Microsoft linker does not create these sections as
writeable; instead, they seem to be merged into `.rdata` and are not
modifiable, unless unprotected.

LLD also does the same, suggesting these sections be merged into `.rdata`:
https://github.com/llvm/llvm-project/blob/ebeb56af5f8f1ff9da8f5a7e98348f460d223de1/lld/COFF/Driver.cpp#L2034-L2048

This commit includes the following countermeasures:

1. Patch 3005 ensures the final `.CRT` and `.idata` sections (if any) will
   not be writeable in the final image.
2. Patch 3006 merges known sub-sections of `.CRT`, as well as `.ctors` and
   `.dtors` (which were merged into `.text` instead), into `.rdata`.
   Merging `.idata` into `.rdata` seems to prevent dllimport from working,
   so there's still an `.idata` section in the final image.
   See also: https://stackoverflow.com/questions/22651433/pe-idata-section

Reference: https://sourceware.org/bugzilla/show_bug.cgi?id=32264
Signed-off-by: LIU Hao <[email protected]>
@lhmouse
Copy link
Contributor Author

lhmouse commented Nov 2, 2024

Previous patch broke pseudo relocation, as __RUNTIME_PSEUDO_RELOC_LIST_END__ was defined to be the immediate end of .rdata (and why was it not just __rt_psrelocs_end):

51247e1#diff-a641beeafacd689f0c4ac5f1141e724abbce202d57be6339df410b00401971f8R121-R131

@lhmouse
Copy link
Contributor Author

lhmouse commented Nov 2, 2024

Also note that the pseudo relocator code which unprotects read-only memory was added in 2009, much later than the relocator itself: mingw-w64/mingw-w64@e209778

This might explain why those sections were required to be writeable. They no longer are.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant