@@ -10,12 +10,12 @@ use {
1010 object:: {
1111 Architecture , Endianness , FileKind , Object , SectionIndex , SymbolScope ,
1212 elf:: {
13- ET_DYN , ET_EXEC , FileHeader32 , FileHeader64 , SHN_UNDEF , STB_GLOBAL , STB_WEAK ,
14- STV_DEFAULT , STV_HIDDEN ,
13+ ET_DYN , ET_EXEC , FileHeader32 , FileHeader64 , PF_X , PT_GNU_STACK , SHN_UNDEF , STB_GLOBAL ,
14+ STB_WEAK , STV_DEFAULT , STV_HIDDEN ,
1515 } ,
1616 macho:: { LC_CODE_SIGNATURE , MH_OBJECT , MH_TWOLEVEL , MachHeader32 , MachHeader64 } ,
1717 read:: {
18- elf:: { Dyn , FileHeader , SectionHeader , Sym } ,
18+ elf:: { Dyn , FileHeader , ProgramHeader , SectionHeader , Sym } ,
1919 macho:: { LoadCommandVariant , MachHeader , Nlist , Section , Segment } ,
2020 pe:: { ImageNtHeaders , PeFile , PeFile32 , PeFile64 } ,
2121 } ,
@@ -1161,6 +1161,39 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
11611161 }
11621162 }
11631163
1164+ // Verify that objects are not requesting an executable stack. For backwards compatibility,
1165+ // Linux (the kernel when loading an executable, and glibc when loading a shared library)
1166+ // assumes you need an executable stack unless you request otherwise. In linked outputs
1167+ // (executables and shared libraries) this is in the program header: the flags of a
1168+ // PT_GNU_STACK entry specify stack permissions, and the default if unspecified is RWX. In
1169+ // intermediate objects (.o files) this is conveyed via the presence of an empty-length
1170+ // .note.GNU-stack, which is marked as an executable section (SHF_EXECINSTR) if the object
1171+ // needs an executable stack.
1172+ //
1173+ // For now we only check binaries because of an LLVM bug that causes .o files to be missing a
1174+ // .note.GNU-stack section, which we are overriding with -Wl,-z,noexecstack.
1175+
1176+ if matches ! ( elf. e_type( endian) , ET_EXEC | ET_DYN ) {
1177+ let mut found_pt_gnu_stack = false ;
1178+ for phdr in elf. program_headers ( endian, data) ? {
1179+ if phdr. p_type ( endian) != PT_GNU_STACK {
1180+ continue ;
1181+ }
1182+ found_pt_gnu_stack = true ;
1183+ if ( phdr. p_flags ( endian) & PF_X ) != 0 {
1184+ context
1185+ . errors
1186+ . push ( format ! ( "{} requests executable stack" , path. display( ) ) ) ;
1187+ }
1188+ }
1189+ if !found_pt_gnu_stack {
1190+ context. errors . push ( format ! (
1191+ "{} missing PT_GNU_STACK header (defaults to executable stack)" ,
1192+ path. display( ) ,
1193+ ) ) ;
1194+ }
1195+ }
1196+
11641197 Ok ( ( ) )
11651198}
11661199
0 commit comments