-
-
Save huonw/be05427dc80e44f1a594 to your computer and use it in GitHub Desktop.
Syntax extension to randomise the order of struct fields, e.g. for security, like Grsecurity http://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options#Randomize_layout_of_sensitive_kernel_structures
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(phase, macro_rules, struct_variant)] | |
// compile with `--pretty expanded` to see the order of the fields/variants change | |
#[phase(syntax)] extern crate random_layout; | |
#[random_layout] | |
struct Foo { | |
x: uint, | |
y: u8, | |
z: f64, | |
w: i8, | |
t: StrBuf | |
} | |
#[random_layout] | |
enum Bar { | |
A, | |
// this order doesn't change: | |
B(uint, u8, f64, i8), | |
C { x: uint, y: u8, z: f64 } | |
} | |
// Errors: | |
// #[random_layout] struct Baz(u8, uint); | |
// #[random_layout] enum Qux { X = 1, Y, Z } | |
// #[random_layout] trait Wat {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![crate_id = "random_layout"] | |
#![crate_type = "dylib"] | |
#![experimental] | |
#![feature(macro_registrar, macro_rules, managed_boxes)] | |
//! Randomises the ordering of enum variants and named struct fields | |
//! (including struct variant fields). | |
//! | |
//! This cannot (and does not) touch enums with any defined | |
//! discriminants (e.g. enum Foo { A = 1, B, C }) or the ordering of | |
//! fields without names (tuple structs and normal enum variants). | |
extern crate syntax; | |
extern crate rand; | |
use rand::{TaskRng, Rng}; | |
use syntax::ast; | |
use syntax::codemap; | |
use syntax::ext::base::{SyntaxExtension, ExtCtxt, ItemModifier}; | |
use syntax::parse::token; | |
#[macro_registrar] | |
#[doc(hidden)] | |
pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) { | |
register(token::intern("random_layout"), | |
ItemModifier(random_layout)); | |
} | |
fn random_layout(cx: &mut ExtCtxt, sp: codemap::Span, | |
_attr: @ast::MetaItem, item: @ast::Item) -> @ast::Item { | |
let mut rng = rand::task_rng(); | |
let node = match item.node { | |
ast::ItemStruct(sd, ref gen) => { | |
if sd.ctor_id.is_some() { | |
cx.span_err(sp, "cannot randomize layout of tuple struct"); | |
return item | |
} | |
ast::ItemStruct(@randomise_struct_def(&mut rng, sd), gen.clone()) | |
} | |
ast::ItemEnum(ref ed, ref gen) => { | |
for v in ed.variants.iter() { | |
if v.node.disr_expr.is_some() { | |
cx.span_err(sp, | |
"cannot randomize layout of enum with defined discriminants"); | |
return item | |
} | |
} | |
let mut variants = ed.variants.iter().map(|v| { | |
let kind = match v.node.kind { | |
// need names to randomise | |
ref k @ ast::TupleVariantKind(_) => k.clone(), | |
ast::StructVariantKind(sd) => { | |
ast::StructVariantKind(@randomise_struct_def(&mut rng, sd)) | |
} | |
}; | |
@codemap::respan(v.span, | |
ast::Variant_ { | |
kind: kind, | |
attrs: v.node.attrs.clone(), | |
.. v.node | |
}) | |
}).collect::<Vec<_>>(); | |
// randomise the order of the variants (i.e. randomise | |
// their discriminants) | |
rng.shuffle(variants.as_mut_slice()); | |
ast::ItemEnum(ast::EnumDef { variants: variants }, gen.clone()) | |
} | |
_ => { | |
cx.span_err(sp, | |
"`#[random_layout]` can only be used on enum and struct definitions"); | |
return item | |
} | |
}; | |
@ast::Item { | |
node: node, | |
attrs: item.attrs.clone(), | |
.. *item | |
} | |
} | |
fn randomise_struct_def(rng: &mut TaskRng, sd: &ast::StructDef) -> ast::StructDef { | |
assert!(sd.ctor_id.is_none()); | |
let mut fields = sd.fields.clone(); | |
rng.shuffle(fields.as_mut_slice()); | |
ast::StructDef { | |
fields: fields, | |
.. *sd | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment