From cb4f8153d8285ac2bf2145c569c09014f3ba317d Mon Sep 17 00:00:00 2001 From: Charisee Date: Sat, 22 Apr 2023 01:00:36 +0000 Subject: [PATCH 1/4] Add GNU Property Note --- .../rustc_codegen_ssa/src/back/metadata.rs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index d5d843702c003..baf674cf9eba6 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -12,6 +12,7 @@ use object::{ use snap::write::FrameEncoder; +use object::elf::NT_GNU_PROPERTY_TYPE_0; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owned_slice::try_slice_owned; use rustc_data_structures::sync::MetadataRef; @@ -93,6 +94,46 @@ pub(super) fn search_for_section<'a>( .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e)) } +fn add_gnu_property_note( + file: &mut write::Object<'static>, + architecture: Architecture, + binary_format: BinaryFormat, +) { + // check bti protection + if binary_format != BinaryFormat::Elf + || !matches!(architecture, Architecture::X86_64 | Architecture::Aarch64) + { + return; + } + + let section = file.add_section( + file.segment_name(StandardSegment::Data).to_vec(), + b".note.gnu.property".to_vec(), + SectionKind::Note, + ); + let mut data: Vec = Vec::new(); + let n_namsz: u32 = 4; // Size of the n_name field + let n_descsz: u32 = 16; // Size of the n_desc field + let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor + let values = [n_namsz, n_descsz, n_type]; + values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))); + data.push(b'G'); // Owner of the program property note + data.push(b'N'); + data.push(b'U'); + data.push(0); + let pr_type: u32 = match architecture { + Architecture::X86_64 => 0xc0000002, + Architecture::Aarch64 => 0xc0000000, + _ => unreachable!(), + }; + let pr_datasz: u32 = 4; //size of the pr_data field + let pr_data: u32 = 3; //program property descriptor + let pr_padding: u32 = 3; + let values = [pr_type, pr_datasz, pr_data, pr_padding]; + values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))); + file.append_section_data(section, &data, 4); +} + pub(crate) fn create_object_file(sess: &Session) -> Option> { let endianness = match sess.target.options.endian { Endian::Little => Endianness::Little, @@ -205,6 +246,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option elf::ELFOSABI_NONE, }; let abi_version = 0; + add_gnu_property_note(&mut file, architecture, binary_format); file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; Some(file) } From 68a5bb4de153565d93e084904154439777ad5c31 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 5 May 2023 18:32:20 +0000 Subject: [PATCH 2/4] Add GNU Property Note --- .../rustc_codegen_ssa/src/back/metadata.rs | 26 +++++++++++-------- .../branch-protection-check-IBT/Makefile | 15 +++++++++++ .../branch-protection-check-IBT/main.rs | 3 +++ 3 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 tests/run-make/branch-protection-check-IBT/Makefile create mode 100644 tests/run-make/branch-protection-check-IBT/main.rs diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index baf674cf9eba6..d4515a794ee5f 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -98,6 +98,7 @@ fn add_gnu_property_note( file: &mut write::Object<'static>, architecture: Architecture, binary_format: BinaryFormat, + endianness: Endianness, ) { // check bti protection if binary_format != BinaryFormat::Elf @@ -115,12 +116,12 @@ fn add_gnu_property_note( let n_namsz: u32 = 4; // Size of the n_name field let n_descsz: u32 = 16; // Size of the n_desc field let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor - let values = [n_namsz, n_descsz, n_type]; - values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))); - data.push(b'G'); // Owner of the program property note - data.push(b'N'); - data.push(b'U'); - data.push(0); + let header_values = [n_namsz, n_descsz, n_type]; + match endianness { + Endianness::Little => header_values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))), + Endianness::Big => header_values.map(|v| data.extend_from_slice(&(v.to_be_bytes()))), + }; + data.extend_from_slice(b"GNU\0"); // Owner of the program property note let pr_type: u32 = match architecture { Architecture::X86_64 => 0xc0000002, Architecture::Aarch64 => 0xc0000000, @@ -128,10 +129,13 @@ fn add_gnu_property_note( }; let pr_datasz: u32 = 4; //size of the pr_data field let pr_data: u32 = 3; //program property descriptor - let pr_padding: u32 = 3; - let values = [pr_type, pr_datasz, pr_data, pr_padding]; - values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))); - file.append_section_data(section, &data, 4); + let pr_padding: u32 = 0; + let property_values = [pr_type, pr_datasz, pr_data, pr_padding]; + match endianness { + Endianness::Little => property_values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))), + Endianness::Big => property_values.map(|v| data.extend_from_slice(&(v.to_be_bytes()))), + }; + file.append_section_data(section, &data, 8); } pub(crate) fn create_object_file(sess: &Session) -> Option> { @@ -246,7 +250,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option elf::ELFOSABI_NONE, }; let abi_version = 0; - add_gnu_property_note(&mut file, architecture, binary_format); + add_gnu_property_note(&mut file, architecture, binary_format, endianness); file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; Some(file) } diff --git a/tests/run-make/branch-protection-check-IBT/Makefile b/tests/run-make/branch-protection-check-IBT/Makefile new file mode 100644 index 0000000000000..cabe951e1c5cb --- /dev/null +++ b/tests/run-make/branch-protection-check-IBT/Makefile @@ -0,0 +1,15 @@ +# Check for GNU Property Note + +include ../tools.mk + +# How to run this +# python3 x.py test --target x86_64-unknown-linux-gnu tests/run-make/branch-protection-check-IBT/ + +# only-x86_64 + +all: +ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86_64) + $(RUSTC) --target x86_64-unknown-linux-gnu -Z cf-protection=branch -L$(TMPDIR) -C link-args='-nostartfiles' -C save-temps ./main.rs -o $(TMPDIR)/rsmain + readelf -nW $(TMPDIR)/rsmain | $(CGREP) -e ".note.gnu.property" +endif + diff --git a/tests/run-make/branch-protection-check-IBT/main.rs b/tests/run-make/branch-protection-check-IBT/main.rs new file mode 100644 index 0000000000000..ad379d6ea4373 --- /dev/null +++ b/tests/run-make/branch-protection-check-IBT/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("hello world"); +} From 1fc0442f7e6eaf0848ceb7230df9fe03d4e6630d Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 5 May 2023 19:06:14 +0000 Subject: [PATCH 3/4] rewriting match on endianness --- compiler/rustc_codegen_ssa/src/back/metadata.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index d4515a794ee5f..ab805089be5f7 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -117,10 +117,17 @@ fn add_gnu_property_note( let n_descsz: u32 = 16; // Size of the n_desc field let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor let header_values = [n_namsz, n_descsz, n_type]; + header_values.iter().for_each(|v| { + data.extend_from_slice(&match endianness { + Endianness::Little => v.to_le_bytes(), + Endianness::Big => v.to_be_bytes(), + }) + }); + /* match endianness { Endianness::Little => header_values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))), Endianness::Big => header_values.map(|v| data.extend_from_slice(&(v.to_be_bytes()))), - }; + };*/ data.extend_from_slice(b"GNU\0"); // Owner of the program property note let pr_type: u32 = match architecture { Architecture::X86_64 => 0xc0000002, From 37f3e2f4b115b166518a208950ecaaef1434830b Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 5 May 2023 19:47:00 +0000 Subject: [PATCH 4/4] rewriting match on endianness --- compiler/rustc_codegen_ssa/src/back/metadata.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ab805089be5f7..8968133bac5ba 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -123,11 +123,6 @@ fn add_gnu_property_note( Endianness::Big => v.to_be_bytes(), }) }); - /* - match endianness { - Endianness::Little => header_values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))), - Endianness::Big => header_values.map(|v| data.extend_from_slice(&(v.to_be_bytes()))), - };*/ data.extend_from_slice(b"GNU\0"); // Owner of the program property note let pr_type: u32 = match architecture { Architecture::X86_64 => 0xc0000002, @@ -138,10 +133,12 @@ fn add_gnu_property_note( let pr_data: u32 = 3; //program property descriptor let pr_padding: u32 = 0; let property_values = [pr_type, pr_datasz, pr_data, pr_padding]; - match endianness { - Endianness::Little => property_values.map(|v| data.extend_from_slice(&(v.to_le_bytes()))), - Endianness::Big => property_values.map(|v| data.extend_from_slice(&(v.to_be_bytes()))), - }; + property_values.iter().for_each(|v| { + data.extend_from_slice(&match endianness { + Endianness::Little => v.to_le_bytes(), + Endianness::Big => v.to_be_bytes(), + }) + }); file.append_section_data(section, &data, 8); }