swage_core/
mem_check.rs

1use crate::memory::{BitFlip, Checkable, ConsecBlocks, DataPattern, Initializable};
2use crate::victim::VictimOrchestrator;
3use log::debug;
4use serde::Serialize;
5use std::arch::x86_64::_mm_clflush;
6
7use crate::victim::{HammerVictimError, VictimResult};
8
9/// List of page addresses to exclude from initialization.
10///
11/// Used to prevent writing victim pages when initializing memory, which potentially causes
12/// segmentation faults.
13#[derive(Clone)]
14pub struct ExcludeFromInit(Vec<*const u8>);
15
16/// Memory-checking victim implementation.
17///
18/// Checks memory for bit flips by comparing against an expected data pattern.
19/// Implements [`VictimOrchestrator`] to integrate with the Swage framework.
20#[derive(Serialize)]
21pub struct MemCheck {
22    #[serde(skip_serializing)]
23    memory: ConsecBlocks,
24    /// The expected data pattern to check against
25    pub pattern: DataPattern,
26    #[serde(skip_serializing)]
27    excluding: ExcludeFromInit,
28}
29
30impl MemCheck {
31    /// Creates a new memory-checking victim.
32    ///
33    /// # Arguments
34    ///
35    /// * `memory` - The memory region to monitor
36    /// * `pattern` - Expected data pattern
37    /// * `excluding` - Pages to exclude from initialization
38    pub fn new(memory: ConsecBlocks, pattern: DataPattern, excluding: ExcludeFromInit) -> Self {
39        Self {
40            memory,
41            pattern,
42            excluding,
43        }
44    }
45}
46
47impl VictimOrchestrator for MemCheck {
48    fn start(&mut self) -> Result<(), HammerVictimError> {
49        Ok(())
50    }
51
52    fn init(&mut self) {
53        debug!("initialize victim");
54        self.memory
55            .initialize_excluding(self.pattern.clone(), &self.excluding.0);
56    }
57
58    fn check(&mut self) -> Result<VictimResult, HammerVictimError> {
59        debug!("check victim");
60        let flips = self
61            .memory
62            .check_excluding(self.pattern.clone(), &self.excluding.0);
63        if !flips.is_empty() {
64            Ok(VictimResult::BitFlips(flips.clone()))
65        } else {
66            Err(HammerVictimError::NoFlips)
67        }
68    }
69
70    fn stop(&mut self) {}
71}
72
73/// Target-specific bit flip checker.
74///
75/// Verifies that specific target bit flips occur at expected locations.
76/// Useful for validating attack precision.
77#[derive(Serialize)]
78pub struct HammerVictimTargetCheck {
79    #[serde(skip_serializing)]
80    memory: ConsecBlocks,
81    pattern: DataPattern,
82    targets: Vec<BitFlip>,
83}
84
85impl HammerVictimTargetCheck {
86    /// Creates a new target-checking victim.
87    ///
88    /// # Arguments
89    ///
90    /// * `memory` - The memory region containing targets
91    /// * `pattern` - Expected data pattern
92    /// * `targets` - Specific bit flips expected to occur
93    pub fn new(memory: ConsecBlocks, pattern: DataPattern, targets: Vec<BitFlip>) -> Self {
94        HammerVictimTargetCheck {
95            memory,
96            pattern,
97            targets,
98        }
99    }
100}
101
102impl VictimOrchestrator for HammerVictimTargetCheck {
103    fn start(&mut self) -> Result<(), HammerVictimError> {
104        Ok(())
105    }
106
107    fn init(&mut self) {
108        debug!("initialize victim");
109        self.memory.initialize(self.pattern.clone());
110    }
111
112    fn check(&mut self) -> Result<VictimResult, HammerVictimError> {
113        debug!("check victim");
114        let mut flips = vec![];
115        for target in &self.targets {
116            let value = unsafe {
117                _mm_clflush(target.addr as *const u8);
118                std::ptr::read_volatile(target.addr as *const u8)
119            };
120            if value != target.data {
121                let bitmask = target.data ^ value;
122                flips.push(BitFlip::new(target.addr as *const u8, bitmask, target.data))
123            }
124        }
125        if !flips.is_empty() {
126            Ok(VictimResult::BitFlips(flips))
127        } else {
128            Err(HammerVictimError::NoFlips)
129        }
130    }
131
132    fn stop(&mut self) {}
133}
134
135impl From<Vec<*const u8>> for ExcludeFromInit {
136    fn from(value: Vec<*const u8>) -> Self {
137        ExcludeFromInit(value)
138    }
139}