@@ -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,96 @@ 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
+
1913
+ * ((Elf_Phdr *) (fileContents->data () + rdi (hdr ()->e_phoff )) + i) = header;
1914
+ changed = true ;
1915
+ } else if (op == ExecstackMode::set && (rdi (header.p_flags ) & PF_X) != PF_X) {
1916
+ debug (" simple execstack set of header %zu\n " , i);
1917
+
1918
+ wri (header.p_flags , rdi (header.p_flags ) | PF_X);
1919
+
1920
+ * ((Elf_Phdr *) (fileContents->data () + rdi (hdr ()->e_phoff )) + i) = header;
1921
+ changed = true ;
1922
+ } else {
1923
+ debug (" execstack already in requested state\n " );
1924
+ }
1925
+
1926
+ return ;
1927
+ }
1928
+
1929
+ if (nullhdr != (size_t )-1 ) {
1930
+ debug (" replacement execstack of header %zu\n " , nullhdr);
1931
+
1932
+ auto & header = phdrs[nullhdr];
1933
+ wri (header.p_type , PT_GNU_STACK);
1934
+ wri (header.p_offset , 0 );
1935
+ wri (header.p_vaddr , 0 );
1936
+ wri (header.p_paddr , 0 );
1937
+ wri (header.p_filesz , 0 );
1938
+ wri (header.p_memsz , 0 );
1939
+ wri (header.p_flags , PF_R | PF_W | (op == ExecstackMode::set ? PF_X : 0 ));
1940
+ wri (header.p_align , getPageSize ());
1941
+
1942
+ * ((Elf_Phdr *) (fileContents->data () + rdi (hdr ()->e_phoff )) + nullhdr) = header;
1943
+ changed = true ;
1944
+ return ;
1945
+ }
1946
+
1947
+ debug (" header addition for execstack\n " );
1948
+
1949
+ Elf_Phdr new_phdr;
1950
+ wri (new_phdr.p_type , PT_GNU_STACK);
1951
+ wri (new_phdr.p_offset , 0 );
1952
+ wri (new_phdr.p_vaddr , 0 );
1953
+ wri (new_phdr.p_paddr , 0 );
1954
+ wri (new_phdr.p_filesz , 0 );
1955
+ wri (new_phdr.p_memsz , 0 );
1956
+ wri (new_phdr.p_flags , PF_R | PF_W | (op == ExecstackMode::set ? PF_X : 0 ));
1957
+ wri (new_phdr.p_align , getPageSize ());
1958
+ phdrs.push_back (new_phdr);
1959
+
1960
+ wri (hdr ()->e_phnum , rdi (hdr ()->e_phnum ) + 1 );
1961
+
1962
+ changed = true ;
1963
+ rewriteSections (true );
1964
+ return ;
1965
+ }
1966
+
1967
+ char result = ' ?' ;
1968
+
1969
+ for (const auto & header : phdrs) {
1970
+ if (rdi (header.p_type ) != PT_GNU_STACK)
1971
+ continue ;
1972
+
1973
+ if ((rdi (header.p_flags ) & PF_X) == PF_X)
1974
+ result = ' X' ;
1975
+ else
1976
+ result = ' -' ;
1977
+ break ;
1978
+ }
1979
+
1980
+ printf (" execstack: %c\n " , result);
1981
+ }
1982
+
1893
1983
static bool printInterpreter = false ;
1894
1984
static bool printOsAbi = false ;
1895
1985
static bool setOsAbi = false ;
@@ -1912,6 +2002,9 @@ static std::set<std::string> neededLibsToAdd;
1912
2002
static std::set<std::string> symbolsToClearVersion;
1913
2003
static bool printNeeded = false ;
1914
2004
static bool noDefaultLib = false ;
2005
+ static bool printExecstack = false ;
2006
+ static bool clearExecstack = false ;
2007
+ static bool setExecstack = false ;
1915
2008
1916
2009
template <class ElfFile >
1917
2010
static void patchElf2 (ElfFile && elfFile, const FileContents & fileContents, const std::string & fileName)
@@ -1937,6 +2030,13 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
1937
2030
if (printRPath)
1938
2031
elfFile.modifyRPath (elfFile.rpPrint , {}, " " );
1939
2032
2033
+ if (printExecstack)
2034
+ elfFile.modifyExecstack (ElfFile::ExecstackMode::print);
2035
+ else if (clearExecstack)
2036
+ elfFile.modifyExecstack (ElfFile::ExecstackMode::clear);
2037
+ else if (setExecstack)
2038
+ elfFile.modifyExecstack (ElfFile::ExecstackMode::set);
2039
+
1940
2040
if (shrinkRPath)
1941
2041
elfFile.modifyRPath (elfFile.rpShrink , allowedRpathPrefixes, " " );
1942
2042
else if (removeRPath)
@@ -2019,6 +2119,9 @@ void showHelp(const std::string & progName)
2019
2119
[--no-sort]\t\t Do not sort program+section headers; useful for debugging patchelf.\n \
2020
2120
[--clear-symbol-version SYMBOL]\n \
2021
2121
[--add-debug-tag]\n \
2122
+ [--print-execstack]\t\t Prints whether the object requests an executable stack\n \
2123
+ [--clear-execstack]\n \
2124
+ [--set-execstack]\n \
2022
2125
[--output FILE]\n \
2023
2126
[--debug]\n \
2024
2127
[--version]\n \
@@ -2127,6 +2230,15 @@ int mainWrapped(int argc, char * * argv)
2127
2230
if (++i == argc) error (" missing argument" );
2128
2231
symbolsToClearVersion.insert (resolveArgument (argv[i]));
2129
2232
}
2233
+ else if (arg == " --print-execstack" ) {
2234
+ printExecstack = true ;
2235
+ }
2236
+ else if (arg == " --clear-execstack" ) {
2237
+ clearExecstack = true ;
2238
+ }
2239
+ else if (arg == " --set-execstack" ) {
2240
+ setExecstack = true ;
2241
+ }
2130
2242
else if (arg == " --output" ) {
2131
2243
if (++i == argc) error (" missing argument" );
2132
2244
outputFileName = resolveArgument (argv[i]);
0 commit comments