@@ -1010,10 +1010,10 @@ void ElfFile<ElfFileParamNames>::normalizeNoteSegments()
1010
1010
1011
1011
1012
1012
template <ElfFileParams>
1013
- void ElfFile<ElfFileParamNames>::rewriteSections()
1013
+ void ElfFile<ElfFileParamNames>::rewriteSections(bool force )
1014
1014
{
1015
1015
1016
- if (replacedSections.empty ()) return ;
1016
+ if (!force && replacedSections.empty ()) return ;
1017
1017
1018
1018
for (auto & i : replacedSections)
1019
1019
debug (" replacing section '%s' with size %d\n " ,
@@ -1890,6 +1890,85 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
1890
1890
this ->rewriteSections ();
1891
1891
}
1892
1892
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
+
1893
1972
static bool printInterpreter = false ;
1894
1973
static bool printOsAbi = false ;
1895
1974
static bool setOsAbi = false ;
@@ -1912,6 +1991,9 @@ static std::set<std::string> neededLibsToAdd;
1912
1991
static std::set<std::string> symbolsToClearVersion;
1913
1992
static bool printNeeded = false ;
1914
1993
static bool noDefaultLib = false ;
1994
+ static bool printExecstack = false ;
1995
+ static bool clearExecstack = false ;
1996
+ static bool setExecstack = false ;
1915
1997
1916
1998
template <class ElfFile >
1917
1999
static void patchElf2 (ElfFile && elfFile, const FileContents & fileContents, const std::string & fileName)
@@ -1937,6 +2019,13 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
1937
2019
if (printRPath)
1938
2020
elfFile.modifyRPath (elfFile.rpPrint , {}, " " );
1939
2021
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
+
1940
2029
if (shrinkRPath)
1941
2030
elfFile.modifyRPath (elfFile.rpShrink , allowedRpathPrefixes, " " );
1942
2031
else if (removeRPath)
@@ -2019,6 +2108,9 @@ void showHelp(const std::string & progName)
2019
2108
[--no-sort]\t\t Do not sort program+section headers; useful for debugging patchelf.\n \
2020
2109
[--clear-symbol-version SYMBOL]\n \
2021
2110
[--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 \
2022
2114
[--output FILE]\n \
2023
2115
[--debug]\n \
2024
2116
[--version]\n \
@@ -2127,6 +2219,15 @@ int mainWrapped(int argc, char * * argv)
2127
2219
if (++i == argc) error (" missing argument" );
2128
2220
symbolsToClearVersion.insert (resolveArgument (argv[i]));
2129
2221
}
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
+ }
2130
2231
else if (arg == " --output" ) {
2131
2232
if (++i == argc) error (" missing argument" );
2132
2233
outputFileName = resolveArgument (argv[i]);
0 commit comments