Skip to content

Commit

Permalink
ima-emulator: Implement graceful shutdown
Browse files Browse the repository at this point in the history
This adds signal-hook as a dependency for the IMA emulator.  The
strategy is similar to what is done on the keylime agent: a dedicated
thread is spawned to stop the main task on Ctrl + C (SIGINT).

Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
  • Loading branch information
ansasaki committed Feb 20, 2023
1 parent 4700faa commit 70b1a72
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 18 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions keylime-ima-emulator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ hex = "0.4"
keylime = { path = "../keylime" }
log = "0.4"
openssl = "0.10.15"
signal-hook = "0.3.15"
thiserror = "1.0"
tss-esapi = {version = "7.2.0", features = ["generate-bindings"]}
68 changes: 50 additions & 18 deletions keylime-ima-emulator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ use openssl::hash::{hash, MessageDigest};
use log::*;

use clap::Parser;
use signal_hook::{consts::SIGINT, iterator::Signals};
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::thread;

use thiserror::Error;

Expand Down Expand Up @@ -209,25 +215,51 @@ fn main() -> std::result::Result<(), ImaEmulatorError> {
}
}

println!("Monitoring {}", args.ima_log.display());
let shutdown_marker = Arc::new(AtomicBool::new(false));
let marker_clone = shutdown_marker.clone();

loop {
for (pcr_hash_alg, position) in positions.iter_mut() {
*position = ml_extend(
&mut context,
&args.ima_log,
*position,
ima_hash_alg,
*pcr_hash_alg,
None,
)?;
let emulator_thread = thread::spawn(move || {
println!("Monitoring {}", args.ima_log.display());
loop {
// Stop if marked to shutdown
if marker_clone.load(Ordering::SeqCst) {
break;
}
for (pcr_hash_alg, position) in positions.iter_mut() {
*position = ml_extend(
&mut context,
&args.ima_log,
*position,
ima_hash_alg,
*pcr_hash_alg,
None,
).expect("Error extending position {position} on PCR bank {pcr_hash_alg}");
}

// FIXME: We could poll IMA_ML as in the python implementation, though
// the file is not pollable:
// https://github.com/torvalds/linux/blob/master/security/integrity/ima/ima_fs.c#L267
// Better idea might be to check the "runtime_measurements_count" file.
let duration = std::time::Duration::from_millis(200);
std::thread::sleep(duration);
}
println!("Shutting down keylime IMA emulator");
});

// FIXME: We could poll IMA_ML as in the python implementation, though
// the file is not pollable:
// https://github.com/torvalds/linux/blob/master/security/integrity/ima/ima_fs.c#L267
// Better idea might be to check the "runtime_measurements_count" file.
let duration = std::time::Duration::from_millis(200);
std::thread::sleep(duration);
}
let mut signals = Signals::new([SIGINT])?;
let shutdown_thread = thread::spawn(move || {
if let Some(sig) = signals.forever().next() {
println!("Received signal {sig:?}");
shutdown_marker.store(true, Ordering::SeqCst);
}
});

emulator_thread
.join()
.expect("Failed to join emulator thread");
shutdown_thread
.join()
.expect("Failed to join shutdown thread");

Ok(())
}

0 comments on commit 70b1a72

Please sign in to comment.