mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-08-01 21:59:41 +00:00
Merge "Add StorageManager skeleton."
GitOrigin-RevId: e776e3c357ca54ad3b74212176da8a4ebc16b372
This commit is contained in:
parent
66c03e7858
commit
bf19c88ccf
@ -67,6 +67,18 @@ DeclareCAmkESComponent(SecurityCoordinator
|
||||
INCLUDES interfaces
|
||||
)
|
||||
|
||||
RustAddLibrary(
|
||||
kata_storage_manager
|
||||
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/components/StorageManager
|
||||
TARGET "riscv32imc-unknown-none-elf"
|
||||
LIB_FILENAME libkata_storage_manager.a
|
||||
)
|
||||
|
||||
DeclareCAmkESComponent(StorageManager
|
||||
LIBS kata_storage_manager
|
||||
INCLUDES interfaces
|
||||
)
|
||||
|
||||
DeclareCAmkESComponent(LogFibonacci
|
||||
SOURCES
|
||||
components/LogFibonacci/src/main.c
|
||||
|
@ -4,6 +4,7 @@ import <PackageManagementInterface.camkes>;
|
||||
import <MlCoordinatorInterface.camkes>;
|
||||
import <SecurityCoordinatorInterface.camkes>;
|
||||
import <SeL4DebugInterface.camkes>;
|
||||
import <StorageInterface.camkes>;
|
||||
|
||||
component DebugConsole {
|
||||
control;
|
||||
@ -19,8 +20,10 @@ component DebugConsole {
|
||||
provides LoggerInterface logger;
|
||||
uses ProcessControlInterface proc_ctrl;
|
||||
uses PackageManagementInterface pkg_mgmt;
|
||||
// TODO(sleffler): for debugging
|
||||
// TODO(b/200707300): for debugging
|
||||
uses SecurityCoordinatorInterface security;
|
||||
// TODO(b/200707300): for debugging
|
||||
uses StorageInterface storage;
|
||||
uses SeL4DebugInterface sel4debug;
|
||||
uses MlCoordinatorInterface mlcoord;
|
||||
}
|
||||
|
@ -10,5 +10,6 @@ kata-io = { path = "../kata-io" }
|
||||
kata-line-reader = { path = "../kata-line-reader" }
|
||||
kata-proc-common = { path = "../../ProcessManager/kata-proc-common" }
|
||||
kata-security-common = { path = "../../SecurityCoordinator/kata-security-common" }
|
||||
kata-storage-interface = { path = "../../StorageManager/kata-storage-interface" }
|
||||
log = "0.4"
|
||||
postcard = { version = "0.7", features = ["alloc"] }
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use core::fmt::Write;
|
||||
use cstr_core::CString;
|
||||
@ -10,6 +11,9 @@ use postcard;
|
||||
use kata_io as io;
|
||||
use kata_line_reader::LineReader;
|
||||
use kata_proc_common::{BundleIdArray, ProcessManagerError, RAW_BUNDLE_ID_DATA_SIZE};
|
||||
use kata_storage_interface::kata_storage_delete;
|
||||
use kata_storage_interface::kata_storage_read;
|
||||
use kata_storage_interface::kata_storage_write;
|
||||
|
||||
/// Error type indicating why a command line is not runnable.
|
||||
enum CommandError {
|
||||
@ -79,6 +83,9 @@ fn dispatch_command(cmdline: &str, output: &mut dyn io::Write) {
|
||||
"echo" => echo_command(cmdline, output),
|
||||
"clear" => clear_command(output),
|
||||
"bundles" => bundles_command(output),
|
||||
"kvdelete" => kvdelete_command(&mut args, output),
|
||||
"kvread" => kvread_command(&mut args, output),
|
||||
"kvwrite" => kvwrite_command(&mut args, output),
|
||||
"install" => install_command(&mut args, output),
|
||||
"loglevel" => loglevel_command(&mut args, output),
|
||||
"ps" => ps_command(),
|
||||
@ -123,14 +130,7 @@ fn scecho_command(cmdline: &str, output: &mut dyn io::Write) -> Result<(), Comma
|
||||
use kata_security_common::*;
|
||||
let (_, request) = cmdline.split_at(7); // 'scecho'
|
||||
let reply = &mut [0u8; SECURITY_REPLY_DATA_SIZE];
|
||||
match unsafe {
|
||||
security_request(
|
||||
SecurityRequest::SrEcho,
|
||||
request.len() as u32,
|
||||
request.as_ptr(),
|
||||
reply as *mut _,
|
||||
)
|
||||
} {
|
||||
match kata_security_request(SecurityRequest::SrEcho, request.as_bytes(), reply) {
|
||||
SecurityRequestError::SreSuccess => {
|
||||
writeln!(
|
||||
output,
|
||||
@ -331,11 +331,69 @@ fn stop_command(
|
||||
}
|
||||
}
|
||||
|
||||
fn kvdelete_command(
|
||||
args: &mut dyn Iterator<Item = &str>,
|
||||
output: &mut dyn io::Write,
|
||||
) -> Result<(), CommandError> {
|
||||
if let Some(key) = args.nth(0) {
|
||||
match kata_storage_delete(key) {
|
||||
Ok(_) => {
|
||||
writeln!(output, "Delete key \"{}\".", key)?;
|
||||
}
|
||||
Err(status) => {
|
||||
writeln!(output, "Delete key \"{}\" failed: {:?}", key, status)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CommandError::BadArgs)
|
||||
}
|
||||
}
|
||||
|
||||
fn kvread_command(
|
||||
args: &mut dyn Iterator<Item = &str>,
|
||||
output: &mut dyn io::Write,
|
||||
) -> Result<(), CommandError> {
|
||||
if let Some(key) = args.nth(0) {
|
||||
match kata_storage_read(key) {
|
||||
Ok(value) => {
|
||||
writeln!(output, "Read key \"{}\" = {:?}.", key, value)?;
|
||||
}
|
||||
Err(status) => {
|
||||
writeln!(output, "Read key \"{}\" failed: {:?}", key, status)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CommandError::BadArgs)
|
||||
}
|
||||
}
|
||||
|
||||
fn kvwrite_command(
|
||||
args: &mut dyn Iterator<Item = &str>,
|
||||
output: &mut dyn io::Write,
|
||||
) -> Result<(), CommandError> {
|
||||
if let Some(key) = args.nth(0) {
|
||||
let value = args.collect::<Vec<&str>>().join(" ");
|
||||
match kata_storage_write(key, value.as_bytes()) {
|
||||
Ok(_) => {
|
||||
writeln!(output, "Write key \"{}\" = {:?}.", key, value)?;
|
||||
}
|
||||
Err(status) => {
|
||||
writeln!(output, "Write key \"{}\" failed: {:?}", key, status)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CommandError::BadArgs)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements a command that tests facilities that use the global allocator.
|
||||
/// Shamelessly cribbed from https://os.phil-opp.com/heap-allocation/
|
||||
fn test_alloc_command(output: &mut dyn io::Write) -> Result<(), CommandError> {
|
||||
extern crate alloc;
|
||||
use alloc::{boxed::Box, rc::Rc, vec, vec::Vec};
|
||||
use alloc::{boxed::Box, rc::Rc, vec};
|
||||
|
||||
// allocate a number on the heap
|
||||
let heap_value = Box::new(41);
|
||||
@ -370,9 +428,6 @@ fn test_alloc_command(output: &mut dyn io::Write) -> Result<(), CommandError> {
|
||||
|
||||
/// Implements a command that tests the global allocator error handling.
|
||||
fn test_alloc_error_command(output: &mut dyn io::Write) -> Result<(), CommandError> {
|
||||
extern crate alloc;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
// Default heap holds 16KB.
|
||||
let mut vec = Vec::with_capacity(16384);
|
||||
for i in 0..16348 {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use core::slice;
|
||||
use kata_proc_common::*;
|
||||
use kata_security_common::*;
|
||||
use log::trace;
|
||||
@ -89,14 +90,11 @@ impl ProcessManagerInterface for KataManagerInterface {
|
||||
|
||||
// This is handled by the SecurityCoordinator.
|
||||
let reply = &mut [0u8; SECURITY_REPLY_DATA_SIZE];
|
||||
match unsafe {
|
||||
security_request(
|
||||
SecurityRequest::SrInstall,
|
||||
pkg_buffer_size,
|
||||
pkg_buffer,
|
||||
reply as *mut _,
|
||||
)
|
||||
} {
|
||||
match kata_security_request(
|
||||
SecurityRequest::SrInstall,
|
||||
unsafe { slice::from_raw_parts(pkg_buffer, pkg_buffer_size as usize) },
|
||||
reply,
|
||||
) {
|
||||
SecurityRequestError::SreSuccess => {
|
||||
fn deserialize_failure(e: postcard::Error) -> ProcessManagerError {
|
||||
trace!("install failed: deserialize {:?}", e);
|
||||
@ -123,14 +121,7 @@ impl ProcessManagerInterface for KataManagerInterface {
|
||||
let mut request_data = [0u8; SECURITY_REQUEST_DATA_SIZE];
|
||||
let _ = postcard::to_slice(&bundle_id, &mut request_data).map_err(serialize_failure)?;
|
||||
let reply = &mut [0u8; SECURITY_REPLY_DATA_SIZE];
|
||||
match unsafe {
|
||||
security_request(
|
||||
SecurityRequest::SrUninstall,
|
||||
request_data.len() as u32,
|
||||
request_data.as_ptr(),
|
||||
reply as *mut _,
|
||||
)
|
||||
} {
|
||||
match kata_security_request(SecurityRequest::SrUninstall, &request_data, reply) {
|
||||
SecurityRequestError::SreSuccess => Ok(()),
|
||||
status => {
|
||||
trace!("uninstall failed: {:?}", status);
|
||||
@ -139,7 +130,7 @@ impl ProcessManagerInterface for KataManagerInterface {
|
||||
}
|
||||
}
|
||||
fn start(&mut self, _bundle: &Bundle) -> Result<(), ProcessManagerError> {
|
||||
// 1. Ask security core for application footprint with SizeBuffer
|
||||
// 1. Ask security core for application footprint with SizeBuffer
|
||||
// 2. Ask security core for manifest (maybe piggyback on SizeBuffer)
|
||||
// and parse for necessary info (e.g. whether kv Storage is
|
||||
// required, other privileges/capabilities)
|
||||
|
@ -45,6 +45,8 @@ mod mut_ptr_helper {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(sleffler): convert String to &str
|
||||
|
||||
// NB: SecurityRequestInstall is handled specially.
|
||||
|
||||
// SecurityRequestUninstall
|
||||
@ -145,8 +147,8 @@ pub enum SecurityRequest {
|
||||
SrInstall, // Install package [pkg_buffer] -> bundle_id
|
||||
SrUninstall, // Uninstall package [bundle_id]
|
||||
|
||||
SrSizeBuffer, // Size application image [bundle_id] -> u32
|
||||
SrGetManifest, // Return application manifest [bundle_id] -> String
|
||||
SrSizeBuffer, // Size application image [bundle_id] -> u32
|
||||
SrGetManifest, // Return application manifest [bundle_id] -> String
|
||||
SrLoadApplication, // Load application [bundle_id]
|
||||
// TODO(sleffler): define <tag>?
|
||||
SrLoadModel, // Load ML model [bundle_id, <tag>]
|
||||
@ -166,14 +168,29 @@ pub trait SecurityCoordinatorInterface {
|
||||
) -> Result<(), SecurityRequestError>;
|
||||
}
|
||||
|
||||
// Camkes-generated rpc api.
|
||||
// NB: this requires the SecurityCoordinator component be named "security".
|
||||
// TODO(sleffler): try kata_security_request<T> to lower serde work
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
extern "C" {
|
||||
pub fn security_request(
|
||||
c_request: SecurityRequest,
|
||||
c_request_buffer_len: u32,
|
||||
c_request_buffer: *const u8,
|
||||
c_reply_buffer: *mut SecurityReplyData,
|
||||
) -> SecurityRequestError;
|
||||
pub fn kata_security_request(
|
||||
request: SecurityRequest,
|
||||
request_buffer: &[u8],
|
||||
reply_buffer: &mut SecurityReplyData,
|
||||
) -> SecurityRequestError {
|
||||
// NB: this assumes the SecurityCoordinator component is named "security".
|
||||
extern "C" {
|
||||
pub fn security_request(
|
||||
c_request: SecurityRequest,
|
||||
c_request_buffer_len: u32,
|
||||
c_request_buffer: *const u8,
|
||||
c_reply_buffer: *mut SecurityReplyData,
|
||||
) -> SecurityRequestError;
|
||||
}
|
||||
unsafe {
|
||||
security_request(
|
||||
request,
|
||||
request_buffer.len() as u32,
|
||||
request_buffer.as_ptr(),
|
||||
reply_buffer as *mut _,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ fake = []
|
||||
sel4 = []
|
||||
|
||||
[dependencies]
|
||||
hashbrown = { version = "0.11", features = ["ahash-compile-time-rng"] }
|
||||
kata-security-common = { path = "../kata-security-common" }
|
||||
kata-storage-interface = { path = "../../StorageManager/kata-storage-interface" }
|
||||
log = "0.4"
|
||||
postcard = "0.7"
|
||||
|
@ -1,22 +1,69 @@
|
||||
//! Kata OS security coordinator fake support
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::string::ToString;
|
||||
use alloc::string::{String, ToString};
|
||||
use hashbrown::HashMap;
|
||||
use kata_security_common::*;
|
||||
use kata_storage_interface::{KeyValueData, KEY_VALUE_DATA_SIZE};
|
||||
use log::trace;
|
||||
use postcard;
|
||||
|
||||
pub struct FakeSecurityCoordinatorInterface {
|
||||
// TODO(sleffler): mailbox ipc state
|
||||
struct BundleData {
|
||||
pkg_size: usize,
|
||||
manifest: String,
|
||||
keys: HashMap<String, KeyValueData>,
|
||||
}
|
||||
impl FakeSecurityCoordinatorInterface {
|
||||
pub fn new() -> Self {
|
||||
FakeSecurityCoordinatorInterface {}
|
||||
impl BundleData {
|
||||
fn new(pkg_size: usize) -> Self {
|
||||
BundleData {
|
||||
pkg_size: pkg_size,
|
||||
manifest: String::from(
|
||||
"# Comments like this
|
||||
[Manifest]
|
||||
BundleId=com.google.cerebra.hw.HelloWorld
|
||||
|
||||
[Binaries]
|
||||
App=HelloWorldBin
|
||||
Model=NeuralNetworkName
|
||||
|
||||
[Storage]
|
||||
Required=1
|
||||
",
|
||||
),
|
||||
keys: HashMap::with_capacity(2),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub type KataSecurityCoordinatorInterface = FakeSecurityCoordinatorInterface;
|
||||
|
||||
impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
pub struct FakeSecurityCoordinator {
|
||||
bundles: HashMap<String, BundleData>,
|
||||
}
|
||||
impl FakeSecurityCoordinator {
|
||||
pub fn new() -> Self {
|
||||
FakeSecurityCoordinator {
|
||||
bundles: HashMap::with_capacity(2),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bundle(&self, bundle_id: &str) -> Result<&BundleData, SecurityRequestError> {
|
||||
self.bundles
|
||||
.get(bundle_id)
|
||||
.map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), |v| Ok(v))
|
||||
}
|
||||
fn get_bundle_mut(&mut self, bundle_id: &str) -> Result<&mut BundleData, SecurityRequestError> {
|
||||
self.bundles
|
||||
.get_mut(bundle_id)
|
||||
.map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), |v| Ok(v))
|
||||
}
|
||||
fn remove_bundle(&mut self, bundle_id: &str) -> Result<(), SecurityRequestError> {
|
||||
self.bundles
|
||||
.remove(bundle_id)
|
||||
.map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), |_v| Ok(()))
|
||||
}
|
||||
}
|
||||
pub type KataSecurityCoordinatorInterface = FakeSecurityCoordinator;
|
||||
|
||||
impl SecurityCoordinatorInterface for FakeSecurityCoordinator {
|
||||
fn request(
|
||||
&mut self,
|
||||
request_id: SecurityRequest,
|
||||
@ -47,25 +94,29 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
request_buffer.as_ptr(),
|
||||
request_buffer.len()
|
||||
);
|
||||
let _ = postcard::to_slice(
|
||||
&(request_buffer.as_ptr() as usize).to_string(),
|
||||
reply_buffer,
|
||||
)
|
||||
.map_err(serialize_failure)?;
|
||||
// let bundle_id = (request_buffer.as_ptr() as usize).to_string();
|
||||
// TODO(sleffler): used by kata-storage-component for kvops
|
||||
let bundle_id = "fubar".to_string();
|
||||
let _ = postcard::to_slice(&bundle_id, reply_buffer).map_err(serialize_failure)?;
|
||||
assert!(self
|
||||
.bundles
|
||||
.insert(bundle_id, BundleData::new(request_buffer.len()))
|
||||
.is_none());
|
||||
Ok(())
|
||||
}
|
||||
SecurityRequest::SrUninstall => {
|
||||
let request = postcard::from_bytes::<UninstallRequest>(&request_buffer[..])
|
||||
.map_err(deserialize_failure)?;
|
||||
trace!("UNINSTALL {}", request.bundle_id);
|
||||
Ok(())
|
||||
self.remove_bundle(&request.bundle_id)
|
||||
}
|
||||
SecurityRequest::SrSizeBuffer => {
|
||||
let request = postcard::from_bytes::<SizeBufferRequest>(&request_buffer[..])
|
||||
.map_err(deserialize_failure)?;
|
||||
trace!("SIZE BUFFER bundle_id {}", request.bundle_id);
|
||||
let bundle = self.get_bundle(&request.bundle_id)?;
|
||||
let _ = postcard::to_slice(
|
||||
&0u32, // TODO(sleffler): fill-in
|
||||
&bundle.pkg_size, // TODO(sleffler): do better
|
||||
reply_buffer,
|
||||
)
|
||||
.map_err(serialize_failure)?;
|
||||
@ -75,21 +126,9 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
let request = postcard::from_bytes::<SizeBufferRequest>(&request_buffer[..])
|
||||
.map_err(deserialize_failure)?;
|
||||
trace!("GET MANIFEST bundle_id {}", request.bundle_id);
|
||||
let _ = postcard::to_slice(
|
||||
"# Comments like this
|
||||
[Manifest]
|
||||
BundleId=com.google.cerebra.hw.HelloWorld
|
||||
|
||||
[Binaries]
|
||||
App=HelloWorldBin
|
||||
Model=NeuralNetworkName
|
||||
|
||||
[Storage]
|
||||
Required=1
|
||||
", // TODO(sleffler): fill-in
|
||||
reply_buffer,
|
||||
)
|
||||
.map_err(serialize_failure)?;
|
||||
let bundle = self.get_bundle(&request.bundle_id)?;
|
||||
let _ = postcard::to_slice(&bundle.manifest, reply_buffer)
|
||||
.map_err(serialize_failure)?;
|
||||
Ok(())
|
||||
}
|
||||
SecurityRequest::SrLoadApplication => {
|
||||
@ -100,6 +139,7 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
request.bundle_id,
|
||||
request.app_binary
|
||||
);
|
||||
let _ = self.get_bundle(&request.bundle_id)?;
|
||||
Ok(())
|
||||
}
|
||||
SecurityRequest::SrLoadModel => {
|
||||
@ -111,6 +151,8 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
request.model_id,
|
||||
request.model_binary
|
||||
);
|
||||
// TODO(sleffler): check model id
|
||||
let _ = self.get_bundle(&request.bundle_id)?;
|
||||
Ok(())
|
||||
}
|
||||
SecurityRequest::SrReadKey => {
|
||||
@ -121,8 +163,15 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
request.bundle_id,
|
||||
request.key,
|
||||
);
|
||||
// TODO(sleffler): fill-in
|
||||
Err(SreReadFailed)
|
||||
let bundle = self.get_bundle(&request.bundle_id)?;
|
||||
match bundle.keys.get(&request.key) {
|
||||
Some(value) => {
|
||||
// TODO(sleffler): return values are fixed size unless we serialize
|
||||
reply_buffer[..value.len()].copy_from_slice(&value[..]);
|
||||
Ok(())
|
||||
}
|
||||
None => Err(SreKeyNotFound),
|
||||
}
|
||||
}
|
||||
SecurityRequest::SrWriteKey => {
|
||||
let request = postcard::from_bytes::<WriteKeyRequest>(&request_buffer[..])
|
||||
@ -133,8 +182,12 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
request.key,
|
||||
request.value,
|
||||
);
|
||||
// TODO(sleffler): fill-in
|
||||
Err(SreWriteFailed)
|
||||
let bundle = self.get_bundle_mut(&request.bundle_id)?;
|
||||
// TODO(sleffler): optimnize with entry
|
||||
let mut value = [0u8; KEY_VALUE_DATA_SIZE];
|
||||
value[..request.value.len()].copy_from_slice(request.value);
|
||||
let _ = bundle.keys.insert(request.key, value);
|
||||
Ok(())
|
||||
}
|
||||
SecurityRequest::SrDeleteKey => {
|
||||
let request = postcard::from_bytes::<DeleteKeyRequest>(&request_buffer[..])
|
||||
@ -144,8 +197,10 @@ impl SecurityCoordinatorInterface for FakeSecurityCoordinatorInterface {
|
||||
request.bundle_id,
|
||||
request.key,
|
||||
);
|
||||
// TODO(sleffler): fill-in
|
||||
Err(SreDeleteFailed)
|
||||
let bundle = self.get_bundle_mut(&request.bundle_id)?;
|
||||
// TODO(sleffler): error if no entry?
|
||||
let _ = bundle.keys.remove(&request.key);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,17 +5,17 @@ use kata_security_common::*;
|
||||
use log::trace;
|
||||
use postcard;
|
||||
|
||||
pub struct SeL4SecurityCoordinatorInterface {
|
||||
pub struct SeL4SecurityCoordinator {
|
||||
// TODO(sleffler): mailbox ipc state
|
||||
}
|
||||
impl SeL4SecurityCoordinatorInterface {
|
||||
impl SeL4SecurityCoordinator {
|
||||
pub fn new() -> Self {
|
||||
SeL4SecurityCoordinatorInterface {}
|
||||
SeL4SecurityCoordinator {}
|
||||
}
|
||||
}
|
||||
pub type KataSecurityCoordinatorInterface = SeL4SecurityCoordinatorInterface;
|
||||
pub type KataSecurityCoordinatorInterface = SeL4SecurityCoordinator;
|
||||
|
||||
impl SecurityCoordinatorInterface for SeL4SecurityCoordinatorInterface {
|
||||
impl SecurityCoordinatorInterface for SeL4SecurityCoordinator {
|
||||
fn request(
|
||||
&mut self,
|
||||
request_id: SecurityRequest,
|
||||
|
23
apps/system/components/StorageManager/Cargo.toml
Normal file
23
apps/system/components/StorageManager/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"kata-storage-component",
|
||||
"kata-storage-interface",
|
||||
"kata-storage-manager",
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 0
|
||||
debug = true
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
split-debuginfo = "unpacked"
|
||||
|
||||
[profile.release.build-override]
|
||||
opt-level = "z"
|
||||
codegen-units = 1
|
12
apps/system/components/StorageManager/StorageManager.camkes
Normal file
12
apps/system/components/StorageManager/StorageManager.camkes
Normal file
@ -0,0 +1,12 @@
|
||||
// Kata OS StorageManager services.
|
||||
|
||||
import <LoggerInterface.camkes>;
|
||||
import <SecurityCoordinatorInterface.camkes>;
|
||||
import <StorageInterface.camkes>;
|
||||
|
||||
component StorageManager {
|
||||
provides StorageInterface storage;
|
||||
|
||||
uses LoggerInterface logger;
|
||||
uses SecurityCoordinatorInterface security;
|
||||
}
|
7
apps/system/components/StorageManager/cbindgen.toml
Normal file
7
apps/system/components/StorageManager/cbindgen.toml
Normal file
@ -0,0 +1,7 @@
|
||||
language = "C"
|
||||
include_guard = "__STORAGE_MANAGER_BINDINGS_H__"
|
||||
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
|
||||
no_includes = true
|
||||
|
||||
[export]
|
||||
include = ["KeyValueData", "StorageManagerError"]
|
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "kata-storage-component"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cstr_core = { version = "0.2.3", default-features = false }
|
||||
kata-allocator = { path = "../../DebugConsole/kata-allocator" }
|
||||
kata-logger = { path = "../../DebugConsole/kata-logger" }
|
||||
kata-panic = { path = "../../DebugConsole/kata-panic" }
|
||||
kata-storage-interface = { path = "../kata-storage-interface" }
|
||||
kata-storage-manager = { path = "../kata-storage-manager" }
|
||||
log = "0.4"
|
||||
postcard = "0.7"
|
||||
|
||||
[lib]
|
||||
name = "kata_storage_manager"
|
||||
path = "src/run.rs"
|
||||
crate-type = ["staticlib"]
|
@ -0,0 +1,120 @@
|
||||
//! Kata OS StorageManager component support.
|
||||
|
||||
// Code here binds the camkes component to the rust code.
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
use core::slice;
|
||||
use cstr_core::CStr;
|
||||
extern crate kata_panic;
|
||||
use kata_allocator;
|
||||
use kata_logger::KataLogger;
|
||||
use kata_storage_interface::KeyValueData;
|
||||
use kata_storage_interface::StorageError;
|
||||
use kata_storage_interface::StorageManagerInterface;
|
||||
use kata_storage_interface::StorageManagerError;
|
||||
use kata_storage_manager::KATA_STORAGE;
|
||||
use log::trace;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn pre_init() {
|
||||
static KATA_LOGGER: KataLogger = KataLogger;
|
||||
log::set_logger(&KATA_LOGGER).unwrap();
|
||||
// NB: set to max; the LoggerInterface will filter
|
||||
log::set_max_level(log::LevelFilter::Trace);
|
||||
|
||||
// TODO(sleffler): temp until we integrate with seL4
|
||||
static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024];
|
||||
unsafe {
|
||||
kata_allocator::ALLOCATOR.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_MEMORY.len());
|
||||
trace!(
|
||||
"setup heap: start_addr {:p} size {}",
|
||||
HEAP_MEMORY.as_ptr(),
|
||||
HEAP_MEMORY.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn map_storage_error(se: StorageError, def: StorageManagerError) -> StorageManagerError {
|
||||
match se {
|
||||
StorageError::Success => StorageManagerError::SmeSuccess,
|
||||
StorageError::BundleNotFound => StorageManagerError::SmeBundleNotFound,
|
||||
StorageError::KeyNotFound => StorageManagerError::SmeKeyNotFound,
|
||||
StorageError::KeyInvalid => StorageManagerError::SmeKeyInvalid,
|
||||
StorageError::ValueInvalid => StorageManagerError::SmeValueInvalid,
|
||||
_ => def,
|
||||
}
|
||||
}
|
||||
|
||||
// StorageInterface glue stubs.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn storage_read(
|
||||
c_key: *const cstr_core::c_char,
|
||||
c_raw_value: *mut KeyValueData,
|
||||
) -> StorageManagerError {
|
||||
unsafe {
|
||||
match CStr::from_ptr(c_key).to_str() {
|
||||
Ok(key) => {
|
||||
// TODO(sleffler): de-badge reply cap to get bundle_id
|
||||
match KATA_STORAGE.read("fubar", key) {
|
||||
// NB: no serialization, returns raw data
|
||||
Ok(value) => {
|
||||
(*c_raw_value).copy_from_slice(&value);
|
||||
StorageManagerError::SmeSuccess
|
||||
}
|
||||
Err(e) => map_storage_error(e, StorageManagerError::SmeReadFailed),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
trace!("read: keyinvalid {:?}", e);
|
||||
StorageManagerError::SmeKeyInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn storage_write(
|
||||
c_key: *const cstr_core::c_char,
|
||||
c_raw_value_len: usize,
|
||||
c_raw_value: *const u8,
|
||||
) -> StorageManagerError {
|
||||
unsafe {
|
||||
match CStr::from_ptr(c_key).to_str() {
|
||||
Ok(key) => {
|
||||
// TODO(sleffler): de-badge reply cap to get bundle_id
|
||||
match KATA_STORAGE.write(
|
||||
"fubar",
|
||||
key,
|
||||
slice::from_raw_parts(c_raw_value, c_raw_value_len),
|
||||
) {
|
||||
Ok(_) => StorageManagerError::SmeSuccess,
|
||||
Err(e) => map_storage_error(e, StorageManagerError::SmeWriteFailed),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
trace!("write: keyinvalid {:?}", e);
|
||||
StorageManagerError::SmeKeyInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn storage_delete(c_key: *const cstr_core::c_char) -> StorageManagerError {
|
||||
unsafe {
|
||||
match CStr::from_ptr(c_key).to_str() {
|
||||
Ok(key) => {
|
||||
// TODO(sleffler): de-badge reply cap to get bundle_id
|
||||
match KATA_STORAGE.delete("fubar", key) {
|
||||
Ok(_) => StorageManagerError::SmeSuccess,
|
||||
Err(e) => map_storage_error(e, StorageManagerError::SmeDeleteFailed),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
trace!("delete: keyinvalid {:?}", e);
|
||||
StorageManagerError::SmeKeyInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "kata-storage-interface"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cstr_core = "0.2"
|
@ -0,0 +1,105 @@
|
||||
//! Kata OS storage management support
|
||||
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
use core::str;
|
||||
use cstr_core::CString;
|
||||
|
||||
// TODO(sleffler): temp constraint on value part of key-value pairs
|
||||
pub const KEY_VALUE_DATA_SIZE: usize = 100;
|
||||
pub type KeyValueData = [u8; KEY_VALUE_DATA_SIZE];
|
||||
|
||||
// NB: struct's marked repr(C) are processed by cbindgen to get a .h file
|
||||
// used in camkes C interfaces.
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum StorageError {
|
||||
Success = 0,
|
||||
BundleNotFound,
|
||||
KeyNotFound,
|
||||
KeyInvalid,
|
||||
ValueInvalid,
|
||||
SerializeFailed,
|
||||
// Generic errors.
|
||||
ReadFailed,
|
||||
WriteFailed,
|
||||
DeleteFailed,
|
||||
}
|
||||
|
||||
pub trait StorageManagerInterface {
|
||||
fn read(&self, bundle_id: &str, key: &str) -> Result<KeyValueData, StorageError>;
|
||||
fn write(&self, bundle_id: &str, key: &str, value: &[u8]) -> Result<(), StorageError>;
|
||||
fn delete(&self, bundle_id: &str, key: &str) -> Result<(), StorageError>;
|
||||
}
|
||||
|
||||
// Public version of StorageError presented over rpc interface.
|
||||
// This is needed because the enum is exported to C users and needs to
|
||||
// be unique from other enum's.
|
||||
// TODO(sleffler): switch to single generic error space ala absl::StatusCode
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum StorageManagerError {
|
||||
SmeSuccess = 0,
|
||||
SmeBundleIdInvalid,
|
||||
SmeBundleNotFound,
|
||||
SmeKeyNotFound,
|
||||
SmeValueInvalid,
|
||||
SmeKeyInvalid,
|
||||
// Generic errors.
|
||||
SmeReadFailed,
|
||||
SmeWriteFailed,
|
||||
SmeDeleteFailed,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn kata_storage_delete(key: &str) -> Result<(), StorageManagerError> {
|
||||
// NB: this assumes the StorageManager component is named "storage".
|
||||
extern "C" {
|
||||
pub fn storage_delete(
|
||||
c_key: *const cstr_core::c_char
|
||||
) -> StorageManagerError;
|
||||
}
|
||||
let cstr = CString::new(key)
|
||||
.map_err(|_| StorageManagerError::SmeKeyInvalid)?;
|
||||
match unsafe { storage_delete(cstr.as_ptr()) } {
|
||||
StorageManagerError::SmeSuccess => Ok(()),
|
||||
status => Err(status),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn kata_storage_read(key: &str) -> Result<KeyValueData, StorageManagerError> {
|
||||
extern "C" {
|
||||
fn storage_read(
|
||||
c_key: *const cstr_core::c_char,
|
||||
c_raw_value: *mut KeyValueData,
|
||||
) -> StorageManagerError;
|
||||
}
|
||||
let cstr = CString::new(key)
|
||||
.map_err(|_| StorageManagerError::SmeKeyInvalid)?;
|
||||
let value = &mut [0u8; KEY_VALUE_DATA_SIZE];
|
||||
match unsafe { storage_read(cstr.as_ptr(), value as *mut _) } {
|
||||
StorageManagerError::SmeSuccess => Ok(*value),
|
||||
status => Err(status),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn kata_storage_write(key: &str, value: &[u8]) -> Result<(), StorageManagerError> {
|
||||
extern "C" {
|
||||
fn storage_write(
|
||||
c_key: *const cstr_core::c_char,
|
||||
c_raw_value_len: usize,
|
||||
c_raw_value: *const u8,
|
||||
) -> StorageManagerError;
|
||||
}
|
||||
let cstr = CString::new(key)
|
||||
.map_err(|_| StorageManagerError::SmeKeyInvalid)?;
|
||||
match unsafe { storage_write(cstr.as_ptr(), value.len(), value.as_ptr()) } {
|
||||
StorageManagerError::SmeSuccess => Ok(()),
|
||||
status => Err(status),
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "kata-storage-manager"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
kata-security-common = { path = "../../SecurityCoordinator/kata-security-common" }
|
||||
kata-storage-interface = { path = "../kata-storage-interface" }
|
||||
log = "0.4"
|
||||
postcard = "0.7"
|
@ -0,0 +1,115 @@
|
||||
//! Kata OS storage management support
|
||||
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use kata_security_common::*;
|
||||
use kata_storage_interface::{KeyValueData, KEY_VALUE_DATA_SIZE};
|
||||
use kata_storage_interface::StorageError;
|
||||
use kata_storage_interface::StorageManagerInterface;
|
||||
use log::trace;
|
||||
use postcard;
|
||||
|
||||
// NB: KATA_STORAGE cannot be used before setup is completed with a call to init()
|
||||
#[cfg(not(test))]
|
||||
pub static mut KATA_STORAGE: KataStorageManager = KataStorageManager{};
|
||||
|
||||
// KataStorageManager bundles an instance of the StorageManager that operates
|
||||
// on KataOS interfaces. There is a two-step dance to setup an instance because
|
||||
// we want KATA_STORAGE static and there is no const Box::new variant.
|
||||
pub struct KataStorageManager;
|
||||
impl StorageManagerInterface for KataStorageManager {
|
||||
fn read(&self, bundle_id: &str, key: &str) -> Result<KeyValueData, StorageError> {
|
||||
trace!("read bundle_id:{} key:{}", bundle_id, key);
|
||||
|
||||
fn serialize_failure(e: postcard::Error) -> StorageError {
|
||||
trace!("read: serialize failure {:?}", e);
|
||||
StorageError::SerializeFailed
|
||||
}
|
||||
|
||||
// Send request to Security Core via SecurityCoordinator
|
||||
let mut request = [0u8; SECURITY_REQUEST_DATA_SIZE];
|
||||
let _ = postcard::to_slice(
|
||||
&ReadKeyRequest {
|
||||
bundle_id: String::from(bundle_id),
|
||||
key: String::from(key),
|
||||
},
|
||||
&mut request[..],
|
||||
)
|
||||
.map_err(serialize_failure)?;
|
||||
let result = &mut [0u8; SECURITY_REPLY_DATA_SIZE];
|
||||
match kata_security_request(SecurityRequest::SrReadKey, &request, result) {
|
||||
SecurityRequestError::SreSuccess => {
|
||||
let mut keyval = [0u8; KEY_VALUE_DATA_SIZE];
|
||||
keyval.copy_from_slice(&result[..KEY_VALUE_DATA_SIZE]);
|
||||
Ok(keyval)
|
||||
}
|
||||
e => Err(map_security_request_error(e, StorageError::ReadFailed)),
|
||||
}
|
||||
}
|
||||
fn write(&self, bundle_id: &str, key: &str, value: &[u8]) -> Result<(), StorageError> {
|
||||
trace!(
|
||||
"write bundle_id:{} key:{} value:{:?}",
|
||||
bundle_id,
|
||||
key,
|
||||
value
|
||||
);
|
||||
|
||||
fn serialize_failure(e: postcard::Error) -> StorageError {
|
||||
trace!("write: serialize failure {:?}", e);
|
||||
StorageError::SerializeFailed
|
||||
}
|
||||
|
||||
// Send request to Security Core via SecurityCoordinator
|
||||
let mut request = [0u8; SECURITY_REQUEST_DATA_SIZE];
|
||||
let _ = postcard::to_slice(
|
||||
&WriteKeyRequest {
|
||||
bundle_id: String::from(bundle_id),
|
||||
key: String::from(key),
|
||||
value: value,
|
||||
},
|
||||
&mut request[..],
|
||||
)
|
||||
.map_err(serialize_failure)?;
|
||||
let result = &mut [0u8; SECURITY_REPLY_DATA_SIZE];
|
||||
match kata_security_request(SecurityRequest::SrWriteKey, &request, result) {
|
||||
SecurityRequestError::SreSuccess => Ok(()),
|
||||
e => Err(map_security_request_error(e, StorageError::WriteFailed)),
|
||||
}
|
||||
}
|
||||
fn delete(&self, bundle_id: &str, key: &str) -> Result<(), StorageError> {
|
||||
trace!("delete bundle_id:{} key:{}", bundle_id, key);
|
||||
|
||||
fn serialize_failure(e: postcard::Error) -> StorageError {
|
||||
trace!("delete: serialize failure {:?}", e);
|
||||
StorageError::SerializeFailed
|
||||
}
|
||||
|
||||
// Send request to Security Core via SecurityCoordinator
|
||||
let mut request = [0u8; SECURITY_REQUEST_DATA_SIZE];
|
||||
let _ = postcard::to_slice(
|
||||
&DeleteKeyRequest {
|
||||
bundle_id: String::from(bundle_id),
|
||||
key: String::from(key),
|
||||
},
|
||||
&mut request[..],
|
||||
)
|
||||
.map_err(serialize_failure)?;
|
||||
let result = &mut [0u8; SECURITY_REPLY_DATA_SIZE];
|
||||
match kata_security_request(SecurityRequest::SrDeleteKey, &request, result) {
|
||||
SecurityRequestError::SreSuccess => Ok(()),
|
||||
e => Err(map_security_request_error(e, StorageError::DeleteFailed)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps a SecuritRequestError to a StorageError.
|
||||
fn map_security_request_error(sre: SecurityRequestError, def: StorageError) -> StorageError {
|
||||
match sre {
|
||||
SecurityRequestError::SreSuccess => StorageError::Success,
|
||||
SecurityRequestError::SreBundleNotFound => StorageError::BundleNotFound,
|
||||
SecurityRequestError::SreKeyNotFound => StorageError::KeyNotFound,
|
||||
_ => def,
|
||||
}
|
||||
}
|
7
apps/system/interfaces/StorageInterface.camkes
Normal file
7
apps/system/interfaces/StorageInterface.camkes
Normal file
@ -0,0 +1,7 @@
|
||||
procedure StorageInterface {
|
||||
include <StorageManagerBindings.h>;
|
||||
|
||||
StorageManagerError read(in string key, out KeyValueData value);
|
||||
StorageManagerError write(in string key, in char value[]);
|
||||
StorageManagerError delete(in string key);
|
||||
};
|
22
apps/system/interfaces/StorageManagerBindings.h
Normal file
22
apps/system/interfaces/StorageManagerBindings.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __STORAGE_MANAGER_BINDINGS_H__
|
||||
#define __STORAGE_MANAGER_BINDINGS_H__
|
||||
|
||||
/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
|
||||
|
||||
#define KEY_VALUE_DATA_SIZE 100
|
||||
|
||||
typedef enum StorageManagerError {
|
||||
SmeSuccess = 0,
|
||||
SmeBundleIdInvalid,
|
||||
SmeBundleNotFound,
|
||||
SmeKeyNotFound,
|
||||
SmeValueInvalid,
|
||||
SmeKeyInvalid,
|
||||
SmeReadFailed,
|
||||
SmeWriteFailed,
|
||||
SmeDeleteFailed,
|
||||
} StorageManagerError;
|
||||
|
||||
typedef uint8_t KeyValueData[KEY_VALUE_DATA_SIZE];
|
||||
|
||||
#endif /* __STORAGE_MANAGER_BINDINGS_H__ */
|
@ -20,6 +20,7 @@ import "components/DebugConsole/DebugConsole.camkes";
|
||||
import "components/ProcessManager/ProcessManager.camkes";
|
||||
import "components/MlCoordinator/MlCoordinator.camkes";
|
||||
import "components/SeL4Debug/SeL4Debug.camkes";
|
||||
import "components/StorageManager/StorageManager.camkes";
|
||||
import "components/SecurityCoordinator/SecurityCoordinator.camkes";
|
||||
import "components/VectorCoreDriver/VectorCoreDriver.camkes";
|
||||
|
||||
@ -51,6 +52,7 @@ assembly {
|
||||
component MlCoordinator ml_coordinator;
|
||||
component DebugConsole debug_console;
|
||||
component SecurityCoordinator security_coordinator;
|
||||
component StorageManager storage_manager;
|
||||
|
||||
// OpenTitanUARTDriver
|
||||
connection seL4HardwareMMIO uart_mem(from uart_driver.mmio_region,
|
||||
@ -74,6 +76,8 @@ assembly {
|
||||
to process_manager.pkg_mgmt);
|
||||
connection seL4RPCCall shell_ml(from debug_console.mlcoord,
|
||||
to ml_coordinator.mlcoord);
|
||||
connection seL4RPCCall shell_storage(from debug_console.storage,
|
||||
to storage_manager.storage);
|
||||
|
||||
// Connect the SecurityCoordinatorInterface to each component that needs
|
||||
// access to the Security Core. Note this allocates a 4KB shared memory
|
||||
@ -82,6 +86,7 @@ assembly {
|
||||
from debug_console.security, // NB: for debug/test
|
||||
from process_manager.security,
|
||||
from ml_coordinator.security, // NB: for LoadModel but not in design
|
||||
from storage_manager.security,
|
||||
to security_coordinator.security);
|
||||
|
||||
// Connect the DebugConsole to the OpenTitanUARTDriver.
|
||||
@ -101,6 +106,7 @@ assembly {
|
||||
from process_manager.logger,
|
||||
from ml_coordinator.logger,
|
||||
from security_coordinator.logger,
|
||||
from storage_manager.logger,
|
||||
to debug_console.logger);
|
||||
|
||||
// Connect the SeL4Debug interface of each component that needs access.
|
||||
|
Loading…
Reference in New Issue
Block a user