Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add secure mount function #15

Merged
merged 1 commit into from
Nov 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ pub static IMA_ML_STUB: &'static str =
pub static IMA_ML: &'static str =
"/sys/kernel/security/ima/ascii_runtime_measurements";
pub static KEY: &'static str = "secret";
pub static WORK_DIR: &'static str = "/tmp";

/*
* Temporaray location for configuration parameters
*/

// cloud node
pub static SECURE_SIZE: &'static str = "1m";
pub static MOUNT_SECURE: bool = true;

/*
* Input: Response status code
Expand Down Expand Up @@ -99,6 +108,35 @@ pub fn get_restful_parameters(urlstring: &str) -> HashMap<&str, &str> {
parameters
}

/*
* Input: path directory to be changed owner to root
* Return: Result contains execution result
* - directory name for successful execution
* - -1 code for failure execution.
*
* If privilege requirement is met, change the owner of the path to root
* This function is unsafely using libc. Result is returned indicating
* execution result.
*/
pub fn chownroot(path: String) -> Result<String, i32> {
unsafe {
frozencemetery marked this conversation as resolved.
Show resolved Hide resolved
// check privilege
if libc::geteuid() != 0 {
error!("Privilege level unable to change ownership to root for file: {}", path);
return Err(-1);
}

// change directory owner to root
if libc::chown(path.as_bytes().as_ptr() as *const i8, 0, 0) != 0 {
error!("Failed to change file {} owner.", path);
return Err(-1);
}

info!("Changed file {} owner to root.", path);
Ok(path)
}
}

// Unit Testing
#[cfg(test)]
mod tests {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extern crate tempfile;

mod common;
mod crypto;
mod secure_mount;
mod tpm;

use futures::future;
Expand Down
129 changes: 129 additions & 0 deletions src/secure_mount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use super::*;

use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::process::Command;

/*
* Input: secure mount directory
* Return: boolean
* - true if directory is mounted
* - false if not mounted
*
* Check the mount status of the secure mount directory. Same
* implementation as the original python version.
*/
fn check_mount(secure_dir: &str) -> bool {
let output = Command::new("mount")
.output()
.expect("Failed to execute mount command");

let mount_result = String::from_utf8(output.stdout).unwrap();
let lines: Vec<&str> = mount_result.split("\n").collect();

// Check mount list for secure directory
for line in lines {
let tokens: Vec<&str> = line.split('/').collect();

if tokens.len() < 3 {
continue;
}

if tokens[2] == secure_dir {
if &tokens[0] != &"tmpfs" {
error!("secure storage location {} already mounted on wrong file system type: {}. Unmount to continue.", secure_dir, tokens[0]);
debug!(
"secure storage location {} aleady mounted on tmpfs",
secure_dir
);
} else {
return true;
}
}
}
debug!("secure storage location {} not mounted.", secure_dir);
false
}

/*
* Return: Result contains secure mount directory or error code
*
* Mounted the work directory as tmpfs, which is owned by root. Same
* implementation as the original python version, but the chown/geteuid
* functions are unsafe function in Rust to use.
*/
fn mount() -> Result<String, i32> {
// use /tmpfs-dev directory if MOUNT_SECURE flag is setm, which doesn't
// mount to the system. This is for developement envrionment.
if !common::MOUNT_SECURE {
let secure_dir = format!("{}{}", common::WORK_DIR, "/tmpfs-dev");
let secure_dir_path = Path::new(secure_dir.as_str());
if !secure_dir_path.exists() {
match fs::create_dir(secure_dir_path) {
Ok(()) => {
return Ok(secure_dir_path.to_str().unwrap().to_string())
}
Err(e) => {
error!("Failed to create directory, error {}", e);
return Err(-1);
}
}
}
}

let secure_dir = format!("{}{}", common::WORK_DIR, "/secure");

// if the directory is not mount to file system, mount the directory to
// file system
if !check_mount(&secure_dir) {
let secure_dir_clone = secure_dir.clone();
let secure_dir_path = Path::new(secure_dir_clone.as_str());

// create directory if the directory is not exist
if !secure_dir_path.exists() {
match fs::create_dir(secure_dir_path) {
Ok(()) => {
let metadata = fs::metadata(secure_dir_path).unwrap();
let mut perm = metadata.permissions();

// This function support unix only
perm.set_mode(448);
}

Err(e) => {
error!("Failed to create directory, error {}", e);
return Err(-1);
}
}
}

info!(
"Mounting secure storage location {} on tmpfs.",
secure_dir_path.to_str().unwrap()
);

// change the secure path directory owner to root
match common::chownroot(secure_dir_path.to_str().unwrap().to_string())
{
Ok(path) => info!("Changed path {} owner to root.", path),
Err(e) => {
error!("Failed to path owner with error code {}.", e);
return Err(-1);
}
}

// mount tmpfs with secure directory
tpm::run(
format!(
"mount -t tmpfs -o size={},mode=0700 tmpfs {}",
common::SECURE_SIZE,
secure_dir_path.to_str().unwrap()
),
tpm::EXIT_SUCCESS,
true,
false,
String::new(),
);
}
Ok(secure_dir)
}
5 changes: 2 additions & 3 deletions src/tpm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const MAX_TRY: usize = 10;
const RETRY_SLEEP: Duration = Duration::from_millis(50);
const TPM_IO_ERROR: i32 = 5;
const RETRY: usize = 4;
const EXIT_SUCCESS: i32 = 0;
pub const EXIT_SUCCESS: i32 = 0;

static EMPTYMASK: &'static str = "1";

Expand Down Expand Up @@ -319,7 +319,6 @@ pub fn check_mask(ima_mask: String, ima_pcr: usize) -> bool {
* Check the quote string, if it is deep quote string, return true, otherwise,
* return false. Same as the original python version.
*/
#[allow(dead_code)]
pub fn is_deep_quote(quote: String) -> bool {
let first_char = &quote[0..1];
match first_char {
Expand Down Expand Up @@ -356,7 +355,7 @@ Following are function from tpm_exec.py program
* result in a tuple. Implement as original python version. Haven't
* implemented tpm stubbing and metric.
*/
fn run<'a>(
pub fn run<'a>(
command: String,
except_code: i32,
raise_on_error: bool,
Expand Down