llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lld-elf Author: Peter Collingbourne (pcc) <details> <summary>Changes</summary> The -z glibc-228-compat flag is intended to be used for binaries utilizing IFUNCs which need to be compatible with glibc versions containing a bug that was fixed in commit b5c45e83753b27dc538dff2d55d4410c385cf3a4 which was released in version 2.29. The bug causes glibc to mprotect the .text section as RW while calling ifunc resolvers in binaries linked with -z notext, leading to a SIGSEGV at startup time. By setting the W flag on the executable section we work around the bug by avoiding the code path that does the mprotect. It is recommended that binaries linked with this flag contain startup code (e.g. in .init_array) that remaps the executable section as non-writable. TODO: - Add tests. - Possibly decide on another mechanism for enabling this besides the -z flag (e.g. examine symbol version data on libc.so.6). --- Full diff: https://github.com/llvm/llvm-project/pull/133532.diff 3 Files Affected: - (modified) lld/ELF/Config.h (+1) - (modified) lld/ELF/Driver.cpp (+1) - (modified) lld/ELF/Writer.cpp (+13) ``````````diff diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 03b3cd4771f49..e611e5059dc19 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -366,6 +366,7 @@ struct Config { bool zCopyreloc; bool zForceBti; bool zForceIbt; + bool zGlibc228Compat; bool zGlobal; bool zHazardplt; bool zIfuncNoplt; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 4555a85a4d216..5a173565e478f 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1559,6 +1559,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) { ctx.arg.zForceBti = hasZOption(args, "force-bti"); ctx.arg.zForceIbt = hasZOption(args, "force-ibt"); ctx.arg.zGcs = getZGcs(ctx, args); + ctx.arg.zGlibc228Compat = hasZOption(args, "glibc-228-compat"); ctx.arg.zGlobal = hasZOption(args, "global"); ctx.arg.zGnustack = getZGnuStack(args); ctx.arg.zHazardplt = hasZOption(args, "hazardplt"); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 2cea6a44b391a..c266aff3a5153 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2277,6 +2277,19 @@ static uint64_t computeFlags(Ctx &ctx, uint64_t flags) { return PF_R | PF_W | PF_X; if (ctx.arg.executeOnly && (flags & PF_X)) return flags & ~PF_R; + + // The -z glibc-228-compat flag is used for binaries utilizing IFUNCs which + // need to be compatible with glibc versions containing a bug that was fixed + // in commit b5c45e83753b27dc538dff2d55d4410c385cf3a4 which was released in + // version 2.29. The bug causes glibc to mprotect the .text section as RW + // while calling ifunc resolvers in binaries linked with -z notext, leading to + // a SIGSEGV at startup time. By setting the W flag on the executable section + // we work around the bug by avoiding the code path that does the mprotect. It + // is recommended that binaries linked with this flag contain startup code + // (e.g. in .init_array) that remaps the executable section as non-writable. + if (ctx.arg.zGlibc228Compat && !ctx.arg.zText && (flags & PF_X)) + return flags | PF_W; + return flags; } `````````` </details> https://github.com/llvm/llvm-project/pull/133532 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits