@@ -1010,10 +1010,10 @@ void ElfFile<ElfFileParamNames>::normalizeNoteSegments()
10101010
10111011
10121012template <ElfFileParams>
1013- void ElfFile<ElfFileParamNames>::rewriteSections()
1013+ void ElfFile<ElfFileParamNames>::rewriteSections(bool force )
10141014{
10151015
1016- if (replacedSections.empty ()) return ;
1016+ if (!force && replacedSections.empty ()) return ;
10171017
10181018 for (auto & i : replacedSections)
10191019 debug (" replacing section '%s' with size %d\n " ,
@@ -1890,6 +1890,85 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
18901890 this ->rewriteSections ();
18911891}
18921892
1893+ template <ElfFileParams>
1894+ void ElfFile<ElfFileParamNames>::modifyExecstack(ExecstackMode op)
1895+ {
1896+ if (op == ExecstackMode::clear || op == ExecstackMode::set) {
1897+ size_t nullhdr = (size_t )-1 ;
1898+
1899+ for (size_t i = 0 ; i < phdrs.size (); i++) {
1900+ auto & header = phdrs[i];
1901+ const auto type = rdi (header.p_type );
1902+ if (type != PT_GNU_STACK) {
1903+ if (!nullhdr && type == PT_NULL)
1904+ nullhdr = i;
1905+ continue ;
1906+ }
1907+
1908+ if (op == ExecstackMode::clear && (rdi (header.p_flags ) & PF_X) == PF_X) {
1909+ debug (" simple execstack clear of header %zu\n " , i);
1910+
1911+ wri (header.p_flags , rdi (header.p_flags ) & ~PF_X);
1912+ * ((Elf_Phdr *) (fileContents->data () + rdi (hdr ()->e_phoff )) + i) = header;
1913+ changed = true ;
1914+ } else if (op == ExecstackMode::set && (rdi (header.p_flags ) & PF_X) != PF_X) {
1915+ debug (" simple execstack set of header %zu\n " , i);
1916+
1917+ wri (header.p_flags , rdi (header.p_flags ) | PF_X);
1918+ * ((Elf_Phdr *) (fileContents->data () + rdi (hdr ()->e_phoff )) + i) = header;
1919+ changed = true ;
1920+ } else {
1921+ debug (" execstack already in requested state\n " );
1922+ }
1923+
1924+ return ;
1925+ }
1926+
1927+ if (nullhdr != (size_t )-1 ) {
1928+ debug (" replacement execstack of header %zu\n " , nullhdr);
1929+
1930+ auto & header = phdrs[nullhdr];
1931+ header = {};
1932+ wri (header.p_type , PT_GNU_STACK);
1933+ wri (header.p_flags , PF_R | PF_W | (op == ExecstackMode::set ? PF_X : 0 ));
1934+ wri (header.p_align , 0x1 );
1935+
1936+ * ((Elf_Phdr *) (fileContents->data () + rdi (hdr ()->e_phoff )) + nullhdr) = header;
1937+ changed = true ;
1938+ return ;
1939+ }
1940+
1941+ debug (" header addition for execstack\n " );
1942+
1943+ Elf_Phdr new_phdr = {};
1944+ wri (new_phdr.p_type , PT_GNU_STACK);
1945+ wri (new_phdr.p_flags , PF_R | PF_W | (op == ExecstackMode::set ? PF_X : 0 ));
1946+ wri (new_phdr.p_align , 0x1 );
1947+ phdrs.push_back (new_phdr);
1948+
1949+ wri (hdr ()->e_phnum , rdi (hdr ()->e_phnum ) + 1 );
1950+
1951+ changed = true ;
1952+ rewriteSections (true );
1953+ return ;
1954+ }
1955+
1956+ char result = ' ?' ;
1957+
1958+ for (const auto & header : phdrs) {
1959+ if (rdi (header.p_type ) != PT_GNU_STACK)
1960+ continue ;
1961+
1962+ if ((rdi (header.p_flags ) & PF_X) == PF_X)
1963+ result = ' X' ;
1964+ else
1965+ result = ' -' ;
1966+ break ;
1967+ }
1968+
1969+ printf (" execstack: %c\n " , result);
1970+ }
1971+
18931972static bool printInterpreter = false ;
18941973static bool printOsAbi = false ;
18951974static bool setOsAbi = false ;
@@ -1912,6 +1991,9 @@ static std::set<std::string> neededLibsToAdd;
19121991static std::set<std::string> symbolsToClearVersion;
19131992static bool printNeeded = false ;
19141993static bool noDefaultLib = false ;
1994+ static bool printExecstack = false ;
1995+ static bool clearExecstack = false ;
1996+ static bool setExecstack = false ;
19151997
19161998template <class ElfFile >
19171999static void patchElf2 (ElfFile && elfFile, const FileContents & fileContents, const std::string & fileName)
@@ -1937,6 +2019,13 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
19372019 if (printRPath)
19382020 elfFile.modifyRPath (elfFile.rpPrint , {}, " " );
19392021
2022+ if (printExecstack)
2023+ elfFile.modifyExecstack (ElfFile::ExecstackMode::print);
2024+ else if (clearExecstack)
2025+ elfFile.modifyExecstack (ElfFile::ExecstackMode::clear);
2026+ else if (setExecstack)
2027+ elfFile.modifyExecstack (ElfFile::ExecstackMode::set);
2028+
19402029 if (shrinkRPath)
19412030 elfFile.modifyRPath (elfFile.rpShrink , allowedRpathPrefixes, " " );
19422031 else if (removeRPath)
@@ -2019,6 +2108,9 @@ void showHelp(const std::string & progName)
20192108 [--no-sort]\t\t Do not sort program+section headers; useful for debugging patchelf.\n \
20202109 [--clear-symbol-version SYMBOL]\n \
20212110 [--add-debug-tag]\n \
2111+ [--print-execstack]\t\t Prints whether the object requests an executable stack\n \
2112+ [--clear-execstack]\n \
2113+ [--set-execstack]\n \
20222114 [--output FILE]\n \
20232115 [--debug]\n \
20242116 [--version]\n \
@@ -2127,6 +2219,15 @@ int mainWrapped(int argc, char * * argv)
21272219 if (++i == argc) error (" missing argument" );
21282220 symbolsToClearVersion.insert (resolveArgument (argv[i]));
21292221 }
2222+ else if (arg == " --print-execstack" ) {
2223+ printExecstack = true ;
2224+ }
2225+ else if (arg == " --clear-execstack" ) {
2226+ clearExecstack = true ;
2227+ }
2228+ else if (arg == " --set-execstack" ) {
2229+ setExecstack = true ;
2230+ }
21302231 else if (arg == " --output" ) {
21312232 if (++i == argc) error (" missing argument" );
21322233 outputFileName = resolveArgument (argv[i]);
0 commit comments