@@ -1890,6 +1890,104 @@ 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_Addr firstPage = 0 ;
1950
+ for (const auto & phdr : phdrs) {
1951
+ if (rdi (phdr.p_type ) == PT_PHDR) {
1952
+ firstPage = rdi (phdr.p_vaddr ) - rdi (phdr.p_offset );
1953
+ break ;
1954
+ }
1955
+ }
1956
+
1957
+ Elf_Phdr new_phdr;
1958
+ wri (new_phdr.p_type , PT_GNU_STACK);
1959
+ wri (new_phdr.p_offset , 0 );
1960
+ wri (new_phdr.p_vaddr , 0 );
1961
+ wri (new_phdr.p_paddr , 0 );
1962
+ wri (new_phdr.p_filesz , 0 );
1963
+ wri (new_phdr.p_memsz , 0 );
1964
+ wri (new_phdr.p_flags , PF_R | PF_W | (op == ExecstackMode::set ? PF_X : 0 ));
1965
+ wri (new_phdr.p_align , getPageSize ());
1966
+ phdrs.push_back (new_phdr);
1967
+
1968
+ wri (hdr ()->e_phnum , rdi (hdr ()->e_phnum ) + 1 );
1969
+
1970
+ changed = true ;
1971
+ rewriteHeaders (firstPage + rdi (hdr ()->e_phoff ));
1972
+ return ;
1973
+ }
1974
+
1975
+ char result = ' ?' ;
1976
+
1977
+ for (const auto & header : phdrs) {
1978
+ if (rdi (header.p_type ) != PT_GNU_STACK)
1979
+ continue ;
1980
+
1981
+ if ((rdi (header.p_flags ) & PF_X) == PF_X)
1982
+ result = ' X' ;
1983
+ else
1984
+ result = ' -' ;
1985
+ break ;
1986
+ }
1987
+
1988
+ printf (" execstack: %c\n " , result);
1989
+ }
1990
+
1893
1991
static bool printInterpreter = false ;
1894
1992
static bool printOsAbi = false ;
1895
1993
static bool setOsAbi = false ;
@@ -1912,6 +2010,9 @@ static std::set<std::string> neededLibsToAdd;
1912
2010
static std::set<std::string> symbolsToClearVersion;
1913
2011
static bool printNeeded = false ;
1914
2012
static bool noDefaultLib = false ;
2013
+ static bool printExecstack = false ;
2014
+ static bool clearExecstack = false ;
2015
+ static bool setExecstack = false ;
1915
2016
1916
2017
template <class ElfFile >
1917
2018
static void patchElf2 (ElfFile && elfFile, const FileContents & fileContents, const std::string & fileName)
@@ -1937,6 +2038,13 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
1937
2038
if (printRPath)
1938
2039
elfFile.modifyRPath (elfFile.rpPrint , {}, " " );
1939
2040
2041
+ if (printExecstack)
2042
+ elfFile.modifyExecstack (ElfFile::ExecstackMode::print);
2043
+ else if (clearExecstack)
2044
+ elfFile.modifyExecstack (ElfFile::ExecstackMode::clear);
2045
+ else if (setExecstack)
2046
+ elfFile.modifyExecstack (ElfFile::ExecstackMode::set);
2047
+
1940
2048
if (shrinkRPath)
1941
2049
elfFile.modifyRPath (elfFile.rpShrink , allowedRpathPrefixes, " " );
1942
2050
else if (removeRPath)
@@ -2019,6 +2127,9 @@ void showHelp(const std::string & progName)
2019
2127
[--no-sort]\t\t Do not sort program+section headers; useful for debugging patchelf.\n \
2020
2128
[--clear-symbol-version SYMBOL]\n \
2021
2129
[--add-debug-tag]\n \
2130
+ [--print-execstack]\t\t Prints whether the object requests an executable stack\n \
2131
+ [--clear-execstack]\n \
2132
+ [--set-execstack]\n \
2022
2133
[--output FILE]\n \
2023
2134
[--debug]\n \
2024
2135
[--version]\n \
@@ -2127,6 +2238,15 @@ int mainWrapped(int argc, char * * argv)
2127
2238
if (++i == argc) error (" missing argument" );
2128
2239
symbolsToClearVersion.insert (resolveArgument (argv[i]));
2129
2240
}
2241
+ else if (arg == " --print-execstack" ) {
2242
+ printExecstack = true ;
2243
+ }
2244
+ else if (arg == " --clear-execstack" ) {
2245
+ clearExecstack = true ;
2246
+ }
2247
+ else if (arg == " --set-execstack" ) {
2248
+ setExecstack = true ;
2249
+ }
2130
2250
else if (arg == " --output" ) {
2131
2251
if (++i == argc) error (" missing argument" );
2132
2252
outputFileName = resolveArgument (argv[i]);
0 commit comments