Add support for various calibration strategies.

The generic channel can now be told to calibrate using a AV model (a Attacker and Victim socket model is stubbed but not implemented).
This commit is contained in:
Guillume DIDIER 2021-10-13 13:52:38 +02:00
parent e3ef141792
commit 6f32c1b469
2 changed files with 304 additions and 163 deletions

View File

@ -1,4 +1,3 @@
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
// TODO // TODO
@ -21,10 +20,11 @@ use cache_side_channel::{
}; };
use cache_utils::calibration::{ use cache_utils::calibration::{
accumulate, calibrate_fixed_freq_2_thread, calibration_result_to_ASVP, accumulate, calibrate_fixed_freq_2_thread, calibration_result_to_ASVP,
get_cache_attack_slicing, get_vpn, only_flush, only_reload, CalibrateOperation2T, get_cache_attack_slicing, get_vpn, map_values, only_flush, only_reload, CalibrateOperation2T,
CalibrationOptions, ErrorPrediction, ErrorPredictions, HashMap, HistParams, HistogramCumSum, CalibrationOptions, ErrorPrediction, ErrorPredictions, HashMap, HistParams, HistogramCumSum,
PotentialThresholds, Slice, Threshold, ThresholdError, Verbosity, ASVP, AV, PotentialThresholds, Slice, Threshold, ThresholdError, Verbosity, ASVP, AV,
CFLUSH_BUCKET_NUMBER, CFLUSH_BUCKET_SIZE, CFLUSH_NUM_ITER, PAGE_LEN, SP, VPN, CFLUSH_BUCKET_NUMBER, CFLUSH_BUCKET_SIZE, CFLUSH_NUM_ITER, CLFLUSH_NUM_ITERATION_AV, PAGE_LEN,
SP, VPN,
}; };
use cache_utils::complex_addressing::{CacheAttackSlicing, CacheSlicing}; use cache_utils::complex_addressing::{CacheAttackSlicing, CacheSlicing};
use cache_utils::mmap::MMappedMemory; use cache_utils::mmap::MMappedMemory;
@ -71,26 +71,48 @@ pub enum TopologyAwareError {
NeedRecalibration, NeedRecalibration,
} }
#[derive(Debug, Copy, Clone)]
pub enum CalibrationStrategy {
ASVP,
AV,
AVSockets,
}
#[derive(Debug)]
enum ThresholdStrat {
ASVP(HashMap<SP, ThresholdError>),
AV(ThresholdError),
AVSockets(ThresholdError),
}
pub struct TopologyAwareTimingChannel<T: TimingChannelPrimitives> { pub struct TopologyAwareTimingChannel<T: TimingChannelPrimitives> {
// TODO slicing: CacheAttackSlicing,
slicing: CacheAttackSlicing, // TODO : include fallback option (with per address thresholds ?) main_core: usize, // aka attacker
main_core: usize, // aka attacker helper_core: usize, // aka victim
helper_core: usize, // aka victim
t: T, t: T,
thresholds: HashMap<SP, ThresholdError>, thresholds: ThresholdStrat,
addresses: HashSet<*const u8>, addresses: HashSet<*const u8>,
preferred_address: HashMap<VPN, *const u8>, preferred_address: HashMap<VPN, *const u8>,
calibration_epoch: usize, calibration_epoch: usize,
calibration_strategy: CalibrationStrategy,
} }
unsafe impl<T: TimingChannelPrimitives + Send> Send for TopologyAwareTimingChannel<T> {} unsafe impl<T: TimingChannelPrimitives + Send> Send for TopologyAwareTimingChannel<T> {}
unsafe impl<T: TimingChannelPrimitives + Sync> Sync for TopologyAwareTimingChannel<T> {} unsafe impl<T: TimingChannelPrimitives + Sync> Sync for TopologyAwareTimingChannel<T> {}
impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> { impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
pub fn new(main_core: usize, helper_core: usize) -> Result<Self, TopologyAwareError> { pub fn new(
main_core: usize,
helper_core: usize,
strat: CalibrationStrategy,
) -> Result<Self, TopologyAwareError> {
if let Some(slicing) = get_cache_attack_slicing(find_core_per_socket(), CACHE_LINE_LENGTH) { if let Some(slicing) = get_cache_attack_slicing(find_core_per_socket(), CACHE_LINE_LENGTH) {
let ret = Self { let ret = Self {
thresholds: Default::default(), thresholds: match strat {
CalibrationStrategy::ASVP => ThresholdStrat::ASVP(Default::default()),
CalibrationStrategy::AV => ThresholdStrat::AV(Default::default()),
CalibrationStrategy::AVSockets => ThresholdStrat::AVSockets(Default::default()),
},
addresses: Default::default(), addresses: Default::default(),
slicing, slicing,
main_core, main_core,
@ -98,6 +120,7 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
preferred_address: Default::default(), preferred_address: Default::default(),
t: Default::default(), t: Default::default(),
calibration_epoch: 0, calibration_epoch: 0,
calibration_strategy: strat,
}; };
Ok(ret) Ok(ret)
} else { } else {
@ -112,8 +135,8 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
t: &T, t: &T,
core_pairs: impl Iterator<Item = (usize, usize)> + Clone, core_pairs: impl Iterator<Item = (usize, usize)> + Clone,
pages: impl Iterator<Item = &'a [u8]>, pages: impl Iterator<Item = &'a [u8]>,
) -> Result<HashMap<AV, (ErrorPrediction, HashMap<SP, ThresholdError>)>, TopologyAwareError> strat: CalibrationStrategy,
{ ) -> Result<HashMap<AV, (ErrorPrediction, ThresholdStrat)>, TopologyAwareError> {
let core_per_socket = find_core_per_socket(); let core_per_socket = find_core_per_socket();
let operations = [ let operations = [
@ -158,7 +181,11 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
hist_params: HistParams { hist_params: HistParams {
bucket_number: CFLUSH_BUCKET_NUMBER, bucket_number: CFLUSH_BUCKET_NUMBER,
bucket_size: CFLUSH_BUCKET_SIZE, bucket_size: CFLUSH_BUCKET_SIZE,
iterations: CFLUSH_NUM_ITER, iterations: match strat {
CalibrationStrategy::ASVP => CFLUSH_NUM_ITER,
CalibrationStrategy::AV => CLFLUSH_NUM_ITERATION_AV,
CalibrationStrategy::AVSockets => CLFLUSH_NUM_ITERATION_AV >> 1,
},
}, },
verbosity: Verbosity::NoOutput, verbosity: Verbosity::NoOutput,
optimised_addresses: true, optimised_addresses: true,
@ -168,54 +195,120 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
}; };
calibrate_results2t_vec.append(&mut r); calibrate_results2t_vec.append(&mut r);
} }
let analysis: HashMap<ASVP, ThresholdError> = calibration_result_to_ASVP( // FIXME analysis for various strategies
calibrate_results2t_vec,
|cal_1t_res| {
let e = ErrorPredictions::predict_errors(HistogramCumSum::from_calibrate(
cal_1t_res, HIT_INDEX, MISS_INDEX,
));
PotentialThresholds::minimizing_total_error(e)
.median()
.unwrap()
},
&h,
)
.map_err(|e| TopologyAwareError::Nix(e))?;
let asvp_best_av_errors: HashMap<AV, (ErrorPrediction, HashMap<SP, ThresholdError>)> = match strat {
accumulate( CalibrationStrategy::ASVP => {
analysis, let analysis: HashMap<ASVP, ThresholdError> = calibration_result_to_ASVP(
|asvp: ASVP| AV { calibrate_results2t_vec,
attacker: asvp.attacker, |cal_1t_res| {
victim: asvp.victim, let e = ErrorPredictions::predict_errors(HistogramCumSum::from_calibrate(
}, cal_1t_res, HIT_INDEX, MISS_INDEX,
|| (ErrorPrediction::default(), HashMap::new()), ));
|acc: &mut (ErrorPrediction, HashMap<SP, ThresholdError>), PotentialThresholds::minimizing_total_error(e)
threshold_error, .median()
asvp: ASVP, .unwrap()
av| { },
assert_eq!(av.attacker, asvp.attacker); &h,
assert_eq!(av.victim, asvp.victim); )
let sp = SP { .map_err(|e| TopologyAwareError::Nix(e))?;
slice: asvp.slice, let asvp_best_av_errors: HashMap<AV, (ErrorPrediction, ThresholdStrat)> =
page: asvp.page, accumulate(
}; analysis,
acc.0 += threshold_error.error; |asvp: ASVP| AV {
acc.1.insert(sp, threshold_error); attacker: asvp.attacker,
}, victim: asvp.victim,
); },
Ok(asvp_best_av_errors) || {
(
ErrorPrediction::default(),
ThresholdStrat::ASVP(HashMap::new()),
)
},
|acc: &mut (ErrorPrediction, ThresholdStrat),
threshold_error,
asvp: ASVP,
av: AV| {
assert_eq!(av.attacker, asvp.attacker);
assert_eq!(av.victim, asvp.victim);
let sp = SP {
slice: asvp.slice,
page: asvp.page,
};
acc.0 += threshold_error.error;
if let ThresholdStrat::ASVP(hashmap) = &mut acc.1 {
hashmap.insert(sp, threshold_error);
}
},
);
Ok(asvp_best_av_errors)
}
CalibrationStrategy::AV => {
let analysis: HashMap<ASVP, ErrorPredictions> = calibration_result_to_ASVP(
calibrate_results2t_vec,
|cal_1t_res| {
let e = ErrorPredictions::predict_errors(HistogramCumSum::from_calibrate(
cal_1t_res, HIT_INDEX, MISS_INDEX,
));
e
},
&h,
)
.map_err(|e| TopologyAwareError::Nix(e))?;
let av_analysis = accumulate(
analysis,
|asvp: ASVP| AV {
attacker: asvp.attacker,
victim: asvp.victim,
},
|| ErrorPredictions::empty(CFLUSH_BUCKET_NUMBER),
|accumulator: &mut ErrorPredictions,
error_preds: ErrorPredictions,
_key,
_rkey| {
*accumulator += error_preds;
},
);
let av_threshold_errors: HashMap<AV, (ErrorPrediction, ThresholdStrat)> =
map_values(av_analysis, |error_predictions: ErrorPredictions, _| {
let threshold_error =
PotentialThresholds::minimizing_total_error(error_predictions)
.median()
.unwrap();
(threshold_error.error, ThresholdStrat::AV(threshold_error))
});
Ok(av_threshold_errors)
// Now consolidate over all slices.
// The accumulator is ErrorPredictions ? (Check if it can be summed, otherwise revert to histograms, accumulate and then predict errors)
// For each AV : build the generic Threshold + error, (using max ?) then determine the best core.
}
CalibrationStrategy::AVSockets => {
let analysis: HashMap<ASVP, ErrorPredictions> = calibration_result_to_ASVP(
calibrate_results2t_vec,
|cal_1t_res| {
let e = ErrorPredictions::predict_errors(HistogramCumSum::from_calibrate(
cal_1t_res, HIT_INDEX, MISS_INDEX,
));
e
},
&h,
)
.map_err(|e| TopologyAwareError::Nix(e))?;
unimplemented!("Requires socket identification support") // Will stay unimplemented for now (10/10/2021)
}
}
} }
pub fn new_with_core_pairs( pub fn new_with_core_pairs(
core_pairs: impl Iterator<Item = (usize, usize)> + Clone, core_pairs: impl Iterator<Item = (usize, usize)> + Clone,
strat: CalibrationStrategy,
) -> Result<(Self, usize, usize), TopologyAwareError> { ) -> Result<(Self, usize, usize), TopologyAwareError> {
let m = MMappedMemory::new(PAGE_LEN, false, |i| i as u8); let m = MMappedMemory::new(PAGE_LEN, false, |i| i as u8);
let array: &[u8] = m.slice(); let array: &[u8] = m.slice();
let t = Default::default(); let t = Default::default();
let mut res = Self::calibration_for_core_pairs(&t, core_pairs, vec![array].into_iter())?; let res = Self::calibration_for_core_pairs(&t, core_pairs, vec![array].into_iter(), strat)?;
let mut best_error_rate = 1.0; let mut best_error_rate = 1.0;
let mut best_av = Default::default(); let mut best_av = Default::default();
@ -228,7 +321,7 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
best_error_rate = global_error_pred.error_rate(); best_error_rate = global_error_pred.error_rate();
} }
} }
Self::new(best_av.attacker, best_av.victim) Self::new(best_av.attacker, best_av.victim, strat)
.map(|this| (this, best_av.attacker, best_av.victim)) .map(|this| (this, best_av.attacker, best_av.victim))
// Set no threshold as calibrated on local array that will get dropped. // Set no threshold as calibrated on local array that will get dropped.
@ -251,14 +344,17 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
// Call out to private constructor that takes a core pair list, determines best and makes the choice. // Call out to private constructor that takes a core pair list, determines best and makes the choice.
// The private constructor will set the correct affinity for main (attacker thread) // The private constructor will set the correct affinity for main (attacker thread)
Self::new_with_core_pairs(core_pairs.into_iter()).map(|(channel, attacker, victim)| { Self::new_with_core_pairs(core_pairs.into_iter(), CalibrationStrategy::ASVP).map(
assert_eq!(attacker, victim); |(channel, attacker, victim)| {
(channel, old, attacker) assert_eq!(attacker, victim);
}) (channel, old, attacker)
},
)
} }
pub fn new_any_two_core( pub fn new_any_two_core(
distinct: bool, distinct: bool,
strat: CalibrationStrategy,
) -> Result<(Self, CpuSet, usize, usize), TopologyAwareError> { ) -> Result<(Self, CpuSet, usize, usize), TopologyAwareError> {
let old = sched_getaffinity(Pid::from_raw(0)).unwrap(); let old = sched_getaffinity(Pid::from_raw(0)).unwrap();
@ -276,12 +372,14 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
} }
} }
Self::new_with_core_pairs(core_pairs.into_iter()).map(|(channel, attacker, victim)| { Self::new_with_core_pairs(core_pairs.into_iter(), strat).map(
if distinct { |(channel, attacker, victim)| {
assert_ne!(attacker, victim); if distinct {
} assert_ne!(attacker, victim);
(channel, old, attacker, victim) }
}) (channel, old, attacker, victim)
},
)
} }
fn get_slice(&self, addr: *const u8) -> Slice { fn get_slice(&self, addr: *const u8) -> Slice {
@ -296,13 +394,7 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
self.main_core = main; self.main_core = main;
self.helper_core = helper; self.helper_core = helper;
let pages: Vec<VPN> = self match self.recalibrate(self.calibration_strategy) {
.thresholds
.keys()
.map(|sp: &SP| sp.page)
//.copied()
.collect();
match self.recalibrate(pages) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
Err(e) => { Err(e) => {
self.main_core = old_main; self.main_core = old_main;
@ -312,28 +404,47 @@ impl<T: TimingChannelPrimitives> TopologyAwareTimingChannel<T> {
} }
} }
fn recalibrate( fn recalibrate(&mut self, strat: CalibrationStrategy) -> Result<(), TopologyAwareError> {
&mut self,
pages: impl IntoIterator<Item = VPN>,
) -> Result<(), TopologyAwareError> {
// unset readiness status. // unset readiness status.
// Call calibration with core pairs with a single core pair // Call calibration with core pairs with a single core pair
// Use results \o/ (or error out) // Use results \o/ (or error out)
self.addresses.clear(); self.addresses.clear();
// Fixme refactor in depth core pairs to make explicit main vs helper.
let core_pairs = vec![(self.main_core, self.helper_core)]; let core_pairs = vec![(self.main_core, self.helper_core)];
let pages: HashSet<&[u8]> = self let mut res = match &self.thresholds {
.thresholds ThresholdStrat::ASVP(thresholds_asvp) => {
.keys() let pages: HashSet<&[u8]> = thresholds_asvp
.map(|sp: &SP| unsafe { &*slice_from_raw_parts(sp.page as *const u8, PAGE_LEN) }) .keys()
.collect(); .map(|sp: &SP| unsafe {
&*slice_from_raw_parts(sp.page as *const u8, PAGE_LEN)
})
.collect();
Self::calibration_for_core_pairs(
&self.t,
core_pairs.into_iter(),
pages.into_iter(),
strat,
)?
}
ThresholdStrat::AV(_) | ThresholdStrat::AVSockets(_) => {
let m = MMappedMemory::new(PAGE_LEN, false, |i| i as u8);
let array: &[u8] = m.slice();
let mut hashset = HashSet::new();
hashset.insert(array);
let pages = hashset;
Self::calibration_for_core_pairs(
&self.t,
core_pairs.into_iter(),
pages.into_iter(),
strat,
)?
}
}; // TODO add the ability to switch calibration strategy.
// This allows selecting core using non SP strategies, and switching to better strategies later on.
let mut res = self.calibration_strategy = strat;
Self::calibration_for_core_pairs(&self.t, core_pairs.into_iter(), pages.into_iter())?;
assert_eq!(res.keys().count(), 1);
self.thresholds = res self.thresholds = res
.remove(&AV { .remove(&AV {
attacker: self.main_core, attacker: self.main_core,
@ -450,13 +561,13 @@ impl<T: TimingChannelPrimitives> Debug for TopologyAwareTimingChannel<T> {
impl<T: TimingChannelPrimitives> CoreSpec for TopologyAwareTimingChannel<T> { impl<T: TimingChannelPrimitives> CoreSpec for TopologyAwareTimingChannel<T> {
fn main_core(&self) -> CpuSet { fn main_core(&self) -> CpuSet {
let mut main = CpuSet::new(); let mut main = CpuSet::new();
main.set(self.main_core); main.set(self.main_core).unwrap();
main main
} }
fn helper_core(&self) -> CpuSet { fn helper_core(&self) -> CpuSet {
let mut helper = CpuSet::new(); let mut helper = CpuSet::new();
helper.set(self.helper_core); helper.set(self.helper_core).unwrap();
helper helper
} }
} }
@ -498,50 +609,65 @@ impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for TopologyAwareT
) -> Result<Vec<Self::Handle>, ChannelFatalError> { ) -> Result<Vec<Self::Handle>, ChannelFatalError> {
let core_pair = vec![(self.main_core, self.helper_core)]; let core_pair = vec![(self.main_core, self.helper_core)];
let pages = addresses match &mut self.thresholds {
.clone() ThresholdStrat::ASVP(thresholds_asvp) => {
.into_iter() let pages = addresses
.map(|addr: *const u8| unsafe { .clone()
let p = get_vpn(addr) as *const u8; .into_iter()
let ret = &*slice_from_raw_parts(p, PAGE_LEN); .map(|addr: *const u8| unsafe {
(p, ret) let p = get_vpn(addr) as *const u8;
}) let ret = &*slice_from_raw_parts(p, PAGE_LEN);
.collect::<HashMap<*const u8, &[u8]>>(); (p, ret)
let mut res = match Self::calibration_for_core_pairs( })
&self.t, .collect::<HashMap<*const u8, &[u8]>>();
core_pair.into_iter(), let mut res = match Self::calibration_for_core_pairs(
pages.into_iter().map(|(k, v)| v), &self.t,
) { core_pair.into_iter(),
Err(e) => { pages.into_iter().map(|(k, v)| v),
return Err(ChannelFatalError::Oops); self.calibration_strategy,
) {
Err(e) => {
return Err(ChannelFatalError::Oops);
}
Ok(r) => r,
};
assert_eq!(res.keys().count(), 1);
let t = match res
.remove(&AV {
attacker: self.main_core,
victim: self.helper_core,
})
.unwrap()
.1
{
ThresholdStrat::ASVP(t) => t,
_ => {
unreachable!()
}
};
for (sp, threshold) in t {
thresholds_asvp.insert(sp, threshold);
}
} }
Ok(r) => r, ThresholdStrat::AV(_) | ThresholdStrat::AVSockets(_) => {}
};
assert_eq!(res.keys().count(), 1);
let t = res
.remove(&AV {
attacker: self.main_core,
victim: self.helper_core,
})
.unwrap()
.1;
for (sp, threshold) in t {
self.thresholds.insert(sp, threshold);
} }
let mut result = vec![]; let mut result = vec![];
for addr in addresses { for addr in addresses {
let vpn = get_vpn(addr); let vpn = get_vpn(addr);
let slice = self.slicing.hash(addr as usize); let slice = self.slicing.hash(addr as usize);
let handle = TopologyAwareTimingChannelHandle { let handle = TopologyAwareTimingChannelHandle {
threshold: self threshold: match &self.thresholds {
.thresholds ThresholdStrat::ASVP(thresholds_asvp) => {
.get(&SP { slice, page: vpn }) thresholds_asvp
.unwrap() .get(&SP { slice, page: vpn })
.threshold, .unwrap()
.threshold
}
ThresholdStrat::AV(te) | ThresholdStrat::AVSockets(te) => te.threshold,
},
vpn, vpn,
addr, addr,
ready: false, ready: false,
@ -618,44 +744,65 @@ impl<T: TimingChannelPrimitives> CovertChannel for TopologyAwareTimingChannel<T>
if let Some(preferred) = self.preferred_address.get(&vpn) { if let Some(preferred) = self.preferred_address.get(&vpn) {
return Err(()); return Err(());
} }
if self.thresholds.iter().filter(|kv| kv.0.page == vpn).count() == 0 {
// ensure calibration
let core_pair = vec![(self.main_core, self.helper_core)];
let as_slice = unsafe { &*slice_from_raw_parts(vpn as *const u8, PAGE_LEN) }; let (best_slice, te) = match &mut self.thresholds {
let pages = vec![as_slice]; ThresholdStrat::ASVP(thresholds_asvp) => {
let mut res = match Self::calibration_for_core_pairs( if thresholds_asvp.iter().filter(|kv| kv.0.page == vpn).count() == 0 {
&self.t, // ensure calibration
core_pair.into_iter(), let core_pair = vec![(self.main_core, self.helper_core)];
pages.into_iter(),
) { let as_slice = unsafe { &*slice_from_raw_parts(vpn as *const u8, PAGE_LEN) };
Err(e) => { let pages = vec![as_slice];
return Err(()); let mut res = match Self::calibration_for_core_pairs(
&self.t,
core_pair.into_iter(),
pages.into_iter(),
self.calibration_strategy,
) {
Err(e) => {
return Err(());
}
Ok(r) => r,
};
assert_eq!(res.keys().count(), 1);
let t = match res
.remove(&AV {
attacker: self.main_core,
victim: self.helper_core,
})
.unwrap()
.1
{
ThresholdStrat::ASVP(t) => t,
_ => {
unreachable!()
}
};
for (sp, threshold) in t {
thresholds_asvp.insert(sp, threshold);
}
} }
Ok(r) => r, let mut best_slice = 0;
}; let mut te = None;
assert_eq!(res.keys().count(), 1); //self.thresholds = ThresholdStrat::ASVP(thresholds_asvp);
let mut best_error_rate = 1.0;
let t = res for (sp, threshold_error) in thresholds_asvp.iter().filter(|kv| kv.0.page == vpn) {
.remove(&AV { if threshold_error.error.error_rate() < best_error_rate {
attacker: self.main_core, best_error_rate = threshold_error.error.error_rate();
victim: self.helper_core, best_slice = sp.slice;
}) te = Some(threshold_error)
.unwrap() }
.1; }
(best_slice, te.unwrap().clone())
for (sp, threshold) in t {
self.thresholds.insert(sp, threshold);
} }
} ThresholdStrat::AV(te) | ThresholdStrat::AVSockets(te) => {
let mut best_error_rate = 1.0; let te = te.clone();
let mut best_slice = 0; (self.get_slice(page), te)
for (sp, threshold_error) in self.thresholds.iter().filter(|kv| kv.0.page == vpn) {
if threshold_error.error.error_rate() < best_error_rate {
best_error_rate = threshold_error.error.error_rate();
best_slice = sp.slice;
} }
} };
for i in 0..PAGE_LEN { for i in 0..PAGE_LEN {
let addr = unsafe { page.offset(i as isize) }; let addr = unsafe { page.offset(i as isize) };
if self.get_slice(addr) == best_slice { if self.get_slice(addr) == best_slice {
@ -663,14 +810,7 @@ impl<T: TimingChannelPrimitives> CovertChannel for TopologyAwareTimingChannel<T>
// Create the right handle // Create the right handle
let mut handle = Self::CovertChannelHandle { let mut handle = Self::CovertChannelHandle {
0: TopologyAwareTimingChannelHandle { 0: TopologyAwareTimingChannelHandle {
threshold: self threshold: te.threshold,
.thresholds
.get(&SP {
slice: best_slice,
page: vpn,
})
.unwrap()
.threshold,
vpn, vpn,
addr, addr,
ready: false, ready: false,

View File

@ -200,7 +200,8 @@ pub fn calibrate_access(array: &[u8; 4096]) -> u64 {
pub const CFLUSH_BUCKET_SIZE: usize = 1; pub const CFLUSH_BUCKET_SIZE: usize = 1;
pub const CFLUSH_BUCKET_NUMBER: usize = 500; pub const CFLUSH_BUCKET_NUMBER: usize = 500;
pub const CFLUSH_NUM_ITER: u32 = 1 << 11; pub const CFLUSH_NUM_ITER: u32 = 1 << 10;
pub const CLFLUSH_NUM_ITERATION_AV: u32 = 1 << 8;
pub fn calibrate_flush( pub fn calibrate_flush(
array: &[u8], array: &[u8],