Skip to content

Commit

Permalink
Rollup merge of #110304 - cchiw:master, r=davidtwco
Browse files Browse the repository at this point in the history
Add GNU Property Note

Fix #103001

Generates the missing property note:
```
Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_PROPERTY_TYPE_0	      Properties: x86 feature: IBT
```
  • Loading branch information
Dylan-DPC authored May 9, 2023
2 parents 33a01e2 + 37f3e2f commit 02a85bd
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
50 changes: 50 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -93,6 +94,54 @@ 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,
endianness: Endianness,
) {
// 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<u8> = 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 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(),
})
});
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,
_ => unreachable!(),
};
let pr_datasz: u32 = 4; //size of the pr_data field
let pr_data: u32 = 3; //program property descriptor
let pr_padding: u32 = 0;
let property_values = [pr_type, pr_datasz, pr_data, pr_padding];
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);
}

pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
let endianness = match sess.target.options.endian {
Endian::Little => Endianness::Little,
Expand Down Expand Up @@ -205,6 +254,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
_ => elf::ELFOSABI_NONE,
};
let abi_version = 0;
add_gnu_property_note(&mut file, architecture, binary_format, endianness);
file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
Some(file)
}
Expand Down
15 changes: 15 additions & 0 deletions tests/run-make/branch-protection-check-IBT/Makefile
Original file line number Diff line number Diff line change
@@ -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

3 changes: 3 additions & 0 deletions tests/run-make/branch-protection-check-IBT/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("hello world");
}

0 comments on commit 02a85bd

Please sign in to comment.