Refactor init into modules, and implement simple/working entropy seeding
This commit is contained in:
parent
70161ec6fe
commit
7e8eda88f7
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "aws"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.134"
|
||||||
|
nsm_lib = { git = "https://github.com/aws/aws-nitro-enclaves-nsm-api.git/", branch = "main", package="nsm-lib", optional = false }
|
||||||
|
nsm_api = { git = "https://github.com/aws/aws-nitro-enclaves-nsm-api.git/", branch = "main", package="aws-nitro-enclaves-nsm-api", optional = false }
|
||||||
|
system = { path = "../system"}
|
|
@ -0,0 +1,65 @@
|
||||||
|
use system::{dmesg, SystemError};
|
||||||
|
|
||||||
|
// Signal to Nitro hypervisor that booting was successful
|
||||||
|
fn nitro_heartbeat() {
|
||||||
|
use system::socket_connect;
|
||||||
|
use libc::{write, read, close, AF_VSOCK};
|
||||||
|
let mut buf: [u8; 1] = [0; 1];
|
||||||
|
buf[0] = 0xB7; // AWS Nitro heartbeat value
|
||||||
|
let fd = match socket_connect(AF_VSOCK, 9000, 3) {
|
||||||
|
Ok(f)=> f,
|
||||||
|
Err(e)=> {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
return
|
||||||
|
},
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
write(fd, buf.as_ptr() as _, 1);
|
||||||
|
read(fd, buf.as_ptr() as _, 1);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
dmesg(format!("Sent NSM heartbeat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get entropy sample from Nitro device
|
||||||
|
pub fn get_entropy(size: usize) -> Result<Vec<u8>, SystemError> {
|
||||||
|
use nsm_api::api::ErrorCode;
|
||||||
|
use nsm_lib::{nsm_get_random, nsm_lib_init};
|
||||||
|
let nsm_fd = nsm_lib_init();
|
||||||
|
if nsm_fd < 0 {
|
||||||
|
return Err(SystemError {
|
||||||
|
message: String::from("Failed to connect to NSM device")
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let mut dest = Vec::with_capacity(size);
|
||||||
|
while dest.len() < size {
|
||||||
|
let mut buf = [0u8; 256];
|
||||||
|
let mut buf_len = buf.len();
|
||||||
|
let status = unsafe {
|
||||||
|
nsm_get_random(nsm_fd, buf.as_mut_ptr(), &mut buf_len)
|
||||||
|
};
|
||||||
|
match status {
|
||||||
|
ErrorCode::Success => {
|
||||||
|
dest.extend_from_slice(&buf);
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Err(SystemError {
|
||||||
|
message: String::from("Failed to get entropy from NSM device")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize nitro device
|
||||||
|
pub fn init_platform(){
|
||||||
|
use system::insmod;
|
||||||
|
// TODO: error handling
|
||||||
|
nitro_heartbeat();
|
||||||
|
|
||||||
|
match insmod("/nsm.ko") {
|
||||||
|
Ok(())=> dmesg(format!("Loaded nsm.ko")),
|
||||||
|
Err(e)=> eprintln!("{}", e)
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,6 +8,16 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aws"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"aws-nitro-enclaves-nsm-api",
|
||||||
|
"libc",
|
||||||
|
"nsm-lib",
|
||||||
|
"system",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-nitro-enclaves-nsm-api"
|
name = "aws-nitro-enclaves-nsm-api"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -98,9 +108,9 @@ dependencies = [
|
||||||
name = "init"
|
name = "init"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-nitro-enclaves-nsm-api",
|
"aws",
|
||||||
"libc",
|
"libc",
|
||||||
"nsm-lib",
|
"system",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -268,6 +278,13 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
|
|
|
@ -5,8 +5,8 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.134"
|
libc = "0.2.134"
|
||||||
nsm_lib = { git = "https://github.com/aws/aws-nitro-enclaves-nsm-api.git/", branch = "main", package="nsm-lib", optional = false }
|
aws = { path = "../aws"}
|
||||||
nsm_api = { git = "https://github.com/aws/aws-nitro-enclaves-nsm-api.git/", branch = "main", package="aws-nitro-enclaves-nsm-api", optional = false }
|
system = { path = "../system"}
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
264
src/init/init.rs
264
src/init/init.rs
|
@ -1,221 +1,30 @@
|
||||||
use libc::{
|
use system::{seed_entropy, reboot, freopen, mount, dmesg};
|
||||||
c_ulong,
|
|
||||||
c_int,
|
|
||||||
c_void,
|
|
||||||
MS_NOSUID,
|
|
||||||
MS_NOEXEC,
|
|
||||||
MS_NODEV,
|
|
||||||
};
|
|
||||||
use std::{
|
|
||||||
mem::zeroed,
|
|
||||||
mem::size_of,
|
|
||||||
ffi::CString,
|
|
||||||
fs::{File, read_to_string},
|
|
||||||
os::unix::io::AsRawFd,
|
|
||||||
fmt,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SystemError {
|
//TODO: Feature flag
|
||||||
message: String,
|
use aws::{init_platform, get_entropy};
|
||||||
}
|
|
||||||
impl fmt::Display for SystemError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{} {}", boot_time(), self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log dmesg formatted log to console
|
// Mount common filesystems with conservative permissions
|
||||||
fn dmesg(message: String){
|
fn init_rootfs() {
|
||||||
println!("{} {}", boot_time(), message);
|
use libc::{MS_NOSUID, MS_NOEXEC, MS_NODEV };
|
||||||
}
|
let no_dse = MS_NODEV | MS_NOSUID | MS_NOEXEC;
|
||||||
|
let no_se = MS_NOSUID | MS_NOEXEC;
|
||||||
// Dmesg formatted seconds since boot
|
let args = [
|
||||||
fn boot_time() -> String {
|
("devtmpfs", "/dev", "devtmpfs", no_se, "mode=0755"),
|
||||||
use libc::{clock_gettime, timespec, CLOCK_BOOTTIME};
|
("devtmpfs", "/dev", "devtmpfs", no_se, "mode=0755"),
|
||||||
let mut t = timespec { tv_sec: 0, tv_nsec: 0 };
|
("devpts", "/dev/pts", "devpts", no_se, ""),
|
||||||
unsafe { clock_gettime(CLOCK_BOOTTIME, &mut t as *mut timespec); }
|
("shm", "/dev/shm", "tmpfs", no_dse, "mode=0755"),
|
||||||
format!("[ {: >4}.{}]", t.tv_sec, t.tv_nsec / 1000).to_string()
|
("proc", "/proc", "proc", no_dse, "hidepid=2"),
|
||||||
}
|
("tmpfs", "/run", "tmpfs", no_dse, "mode=0755"),
|
||||||
|
("tmpfs", "/tmp", "tmpfs", no_dse, ""),
|
||||||
fn reboot(){
|
("sysfs", "/sys", "sysfs", no_dse, ""),
|
||||||
use libc::{reboot, RB_AUTOBOOT};
|
("cgroup_root", "/sys/fs/cgroup", "tmpfs", no_dse, "mode=0755"),
|
||||||
unsafe {
|
];
|
||||||
reboot(RB_AUTOBOOT);
|
for (src, target, fstype, flags, data) in args {
|
||||||
|
match mount(src, target, fstype, flags, data) {
|
||||||
|
Ok(())=> dmesg(format!("Mounted {}", target)),
|
||||||
|
Err(e)=> eprintln!("{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// libc::mount casting/error wrapper
|
|
||||||
fn mount(
|
|
||||||
src: &str,
|
|
||||||
target: &str,
|
|
||||||
fstype: &str,
|
|
||||||
flags: c_ulong,
|
|
||||||
data: &str,
|
|
||||||
) -> Result<(), SystemError> {
|
|
||||||
use libc::mount;
|
|
||||||
let src_cs = CString::new(src).unwrap();
|
|
||||||
let fstype_cs = CString::new(fstype).unwrap();
|
|
||||||
let data_cs = CString::new(data).unwrap();
|
|
||||||
let target_cs = CString::new(target).unwrap();
|
|
||||||
if unsafe {
|
|
||||||
mount(
|
|
||||||
src_cs.as_ptr(),
|
|
||||||
target_cs.as_ptr(),
|
|
||||||
fstype_cs.as_ptr(),
|
|
||||||
flags,
|
|
||||||
data_cs.as_ptr() as *const c_void
|
|
||||||
)
|
|
||||||
} != 0 {
|
|
||||||
Err(SystemError { message: format!("Failed to mount: {}", target) })
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// libc::freopen casting/error wrapper
|
|
||||||
fn freopen(
|
|
||||||
filename: &str,
|
|
||||||
mode: &str,
|
|
||||||
file: c_int,
|
|
||||||
) -> Result<(), SystemError> {
|
|
||||||
use libc::{freopen, fdopen};
|
|
||||||
let filename_cs = CString::new(filename).unwrap();
|
|
||||||
let mode_cs = CString::new(mode).unwrap();
|
|
||||||
if unsafe {
|
|
||||||
freopen(
|
|
||||||
filename_cs.as_ptr(),
|
|
||||||
mode_cs.as_ptr(),
|
|
||||||
fdopen(file, mode_cs.as_ptr() as *const i8)
|
|
||||||
)
|
|
||||||
}.is_null() {
|
|
||||||
Err(SystemError { message: format!("Failed to freopen: {}", filename) })
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert kernel module into memory
|
|
||||||
fn insmod(path: &str) -> Result<(), SystemError> {
|
|
||||||
use libc::{syscall, SYS_finit_module};
|
|
||||||
let file = File::open(path).unwrap();
|
|
||||||
let fd = file.as_raw_fd();
|
|
||||||
if unsafe { syscall(SYS_finit_module, fd, &[0u8; 1], 0) } < 0 {
|
|
||||||
Err(SystemError {
|
|
||||||
message: format!("Failed to insert kernel module: {}", path)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate a socket
|
|
||||||
fn socket_connect(
|
|
||||||
family: c_int,
|
|
||||||
port: u32,
|
|
||||||
cid: u32,
|
|
||||||
) -> Result<c_int, SystemError> {
|
|
||||||
use libc::{connect, socket, sockaddr, sockaddr_vm, SOCK_STREAM};
|
|
||||||
let fd = unsafe { socket(family, SOCK_STREAM, 0) };
|
|
||||||
if unsafe {
|
|
||||||
let mut sa: sockaddr_vm = zeroed();
|
|
||||||
sa.svm_family = family as _;
|
|
||||||
sa.svm_port = port;
|
|
||||||
sa.svm_cid = cid;
|
|
||||||
connect(
|
|
||||||
fd,
|
|
||||||
&sa as *const _ as *mut sockaddr,
|
|
||||||
size_of::<sockaddr_vm>() as _,
|
|
||||||
)
|
|
||||||
} < 0 {
|
|
||||||
Err(SystemError {
|
|
||||||
message: format!("Failed to connect to socket: {}", family)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(fd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal to Nitro hypervisor that booting was successful
|
|
||||||
fn nitro_heartbeat() {
|
|
||||||
use libc::{write, read, close, AF_VSOCK};
|
|
||||||
let mut buf: [u8; 1] = [0; 1];
|
|
||||||
buf[0] = 0xB7; // AWS Nitro heartbeat value
|
|
||||||
let fd = match socket_connect(AF_VSOCK, 9000, 3) {
|
|
||||||
Ok(f)=> f,
|
|
||||||
Err(e)=> {
|
|
||||||
eprintln!("{}", e);
|
|
||||||
return
|
|
||||||
},
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
write(fd, buf.as_ptr() as _, 1);
|
|
||||||
read(fd, buf.as_ptr() as _, 1);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
dmesg(format!("Sent NSM heartbeat"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get entropy sample from Nitro device
|
|
||||||
fn nitro_get_entropy() -> Result<[u8; 256], SystemError> {
|
|
||||||
use nsm_api::api::ErrorCode;
|
|
||||||
use nsm_lib::{nsm_get_random, nsm_lib_init};
|
|
||||||
|
|
||||||
let nsm_fd = nsm_lib_init();
|
|
||||||
if nsm_fd < 0 {
|
|
||||||
return Err(SystemError {
|
|
||||||
message: String::from("Failed to connect to NSM device")
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut dest = [0u8; 256];
|
|
||||||
let mut dest_len = dest.len();
|
|
||||||
|
|
||||||
let status = unsafe {
|
|
||||||
nsm_get_random(nsm_fd, dest.as_mut_ptr(), &mut dest_len)
|
|
||||||
};
|
|
||||||
match status {
|
|
||||||
ErrorCode::Success => {
|
|
||||||
Ok(dest)
|
|
||||||
},
|
|
||||||
_ => Err(SystemError {
|
|
||||||
message: String::from("Failed to get entropy from NSM device")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_random_poolsize() -> Result<usize, SystemError> {
|
|
||||||
let ps_path = "/proc/sys/kernel/random/poolsize";
|
|
||||||
let size_s = read_to_string(ps_path).unwrap_or_else(|_| String::new());
|
|
||||||
if size_s.is_empty(){
|
|
||||||
return Err(SystemError {
|
|
||||||
message: String::from("Failed to read kernel random poolsize"),
|
|
||||||
})
|
|
||||||
};
|
|
||||||
match size_s.parse::<usize>() {
|
|
||||||
Ok(size) => Ok(size),
|
|
||||||
Err(_) => Err(SystemError {
|
|
||||||
message: String::from("Failed to parse kernel random poolsize"),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize nitro device
|
|
||||||
fn init_nitro(){
|
|
||||||
// TODO: error handling
|
|
||||||
nitro_heartbeat();
|
|
||||||
|
|
||||||
match insmod("/nsm.ko") {
|
|
||||||
Ok(())=> dmesg(format!("Loaded nsm.ko")),
|
|
||||||
Err(e)=> eprintln!("{}", e)
|
|
||||||
};
|
|
||||||
match get_random_poolsize() {
|
|
||||||
Ok(size)=> dmesg(format!("Kernel entropy pool size: {}", size)),
|
|
||||||
Err(e)=> eprintln!("{}", e)
|
|
||||||
};
|
|
||||||
match nitro_get_entropy() {
|
|
||||||
Ok(_)=> dmesg(format!("Got NSM Entropy sample")),
|
|
||||||
Err(e)=> eprintln!("{}", e)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize console with stdin/stdout/stderr
|
// Initialize console with stdin/stdout/stderr
|
||||||
|
@ -233,31 +42,14 @@ fn init_console() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount common filesystems with conservative permissions
|
|
||||||
fn init_rootfs() {
|
|
||||||
let args = [
|
|
||||||
("devtmpfs", "/dev", "devtmpfs", MS_NOSUID | MS_NOEXEC, "mode=0755"),
|
|
||||||
("devtmpfs", "/dev", "devtmpfs", MS_NOSUID | MS_NOEXEC, "mode=0755"),
|
|
||||||
("proc", "/proc", "proc", MS_NODEV | MS_NOSUID | MS_NOEXEC, "hidepid=2"),
|
|
||||||
("tmpfs", "/run", "tmpfs", MS_NODEV | MS_NOSUID | MS_NOEXEC, "mode=0755"),
|
|
||||||
("tmpfs", "/tmp", "tmpfs", MS_NODEV | MS_NOSUID | MS_NOEXEC, ""),
|
|
||||||
("shm", "/dev/shm", "tmpfs", MS_NODEV | MS_NOSUID | MS_NOEXEC, "mode=0755"),
|
|
||||||
("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, ""),
|
|
||||||
("sysfs", "/sys", "sysfs", MS_NODEV | MS_NOSUID | MS_NOEXEC, ""),
|
|
||||||
("cgroup_root", "/sys/fs/cgroup", "tmpfs", MS_NODEV | MS_NOSUID | MS_NOEXEC, "mode=0755"),
|
|
||||||
];
|
|
||||||
for (src, target, fstype, flags, data) in args {
|
|
||||||
match mount(src, target, fstype, flags, data) {
|
|
||||||
Ok(())=> dmesg(format!("Mounted {}", target)),
|
|
||||||
Err(e)=> eprintln!("{}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn boot(){
|
fn boot(){
|
||||||
init_rootfs();
|
init_rootfs();
|
||||||
init_console();
|
init_console();
|
||||||
init_nitro();
|
init_platform();
|
||||||
|
match seed_entropy(4096, get_entropy) {
|
||||||
|
Ok(size)=> dmesg(format!("Seeded kernel with entropy: {}", size)),
|
||||||
|
Err(e)=> eprintln!("{}", e)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "system"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.134"
|
|
@ -0,0 +1,169 @@
|
||||||
|
use libc::{ c_ulong, c_int, c_void };
|
||||||
|
use std::{
|
||||||
|
mem::{zeroed, size_of},
|
||||||
|
ffi::CString,
|
||||||
|
fs::File,
|
||||||
|
os::unix::io::AsRawFd,
|
||||||
|
fmt,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SystemError {
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
impl fmt::Display for SystemError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{} {}", boot_time(), self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log dmesg formatted log to console
|
||||||
|
pub fn dmesg(message: String){
|
||||||
|
println!("{} {}", boot_time(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dmesg formatted seconds since boot
|
||||||
|
pub fn boot_time() -> String {
|
||||||
|
use libc::{clock_gettime, timespec, CLOCK_BOOTTIME};
|
||||||
|
let mut t = timespec { tv_sec: 0, tv_nsec: 0 };
|
||||||
|
unsafe { clock_gettime(CLOCK_BOOTTIME, &mut t as *mut timespec); }
|
||||||
|
format!("[ {: >4}.{}]", t.tv_sec, t.tv_nsec / 1000).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unconditionally reboot the system now
|
||||||
|
pub fn reboot(){
|
||||||
|
use libc::{reboot, RB_AUTOBOOT};
|
||||||
|
unsafe {
|
||||||
|
reboot(RB_AUTOBOOT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// libc::mount casting/error wrapper
|
||||||
|
pub fn mount(
|
||||||
|
src: &str,
|
||||||
|
target: &str,
|
||||||
|
fstype: &str,
|
||||||
|
flags: c_ulong,
|
||||||
|
data: &str,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
use libc::mount;
|
||||||
|
let src_cs = CString::new(src).unwrap();
|
||||||
|
let fstype_cs = CString::new(fstype).unwrap();
|
||||||
|
let data_cs = CString::new(data).unwrap();
|
||||||
|
let target_cs = CString::new(target).unwrap();
|
||||||
|
if unsafe {
|
||||||
|
mount(
|
||||||
|
src_cs.as_ptr(),
|
||||||
|
target_cs.as_ptr(),
|
||||||
|
fstype_cs.as_ptr(),
|
||||||
|
flags,
|
||||||
|
data_cs.as_ptr() as *const c_void
|
||||||
|
)
|
||||||
|
} != 0 {
|
||||||
|
Err(SystemError { message: format!("Failed to mount: {}", target) })
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// libc::freopen casting/error wrapper
|
||||||
|
pub fn freopen(
|
||||||
|
filename: &str,
|
||||||
|
mode: &str,
|
||||||
|
file: c_int,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
use libc::{freopen, fdopen};
|
||||||
|
let filename_cs = CString::new(filename).unwrap();
|
||||||
|
let mode_cs = CString::new(mode).unwrap();
|
||||||
|
if unsafe {
|
||||||
|
freopen(
|
||||||
|
filename_cs.as_ptr(),
|
||||||
|
mode_cs.as_ptr(),
|
||||||
|
fdopen(file, mode_cs.as_ptr() as *const i8)
|
||||||
|
)
|
||||||
|
}.is_null() {
|
||||||
|
Err(SystemError { message: format!("Failed to freopen: {}", filename) })
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert kernel module into memory
|
||||||
|
pub fn insmod(path: &str) -> Result<(), SystemError> {
|
||||||
|
use libc::{syscall, SYS_finit_module};
|
||||||
|
let file = File::open(path).unwrap();
|
||||||
|
let fd = file.as_raw_fd();
|
||||||
|
if unsafe { syscall(SYS_finit_module, fd, &[0u8; 1], 0) } < 0 {
|
||||||
|
Err(SystemError {
|
||||||
|
message: format!("Failed to insert kernel module: {}", path)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate a socket
|
||||||
|
pub fn socket_connect(
|
||||||
|
family: c_int,
|
||||||
|
port: u32,
|
||||||
|
cid: u32,
|
||||||
|
) -> Result<c_int, SystemError> {
|
||||||
|
use libc::{connect, socket, sockaddr, sockaddr_vm, SOCK_STREAM};
|
||||||
|
let fd = unsafe { socket(family, SOCK_STREAM, 0) };
|
||||||
|
if unsafe {
|
||||||
|
let mut sa: sockaddr_vm = zeroed();
|
||||||
|
sa.svm_family = family as _;
|
||||||
|
sa.svm_port = port;
|
||||||
|
sa.svm_cid = cid;
|
||||||
|
connect(
|
||||||
|
fd,
|
||||||
|
&sa as *const _ as *mut sockaddr,
|
||||||
|
size_of::<sockaddr_vm>() as _,
|
||||||
|
)
|
||||||
|
} < 0 {
|
||||||
|
Err(SystemError {
|
||||||
|
message: format!("Failed to connect to socket: {}", family)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed an entropy sample into the kernel randomness pool.
|
||||||
|
pub fn seed_entropy(
|
||||||
|
size: usize,
|
||||||
|
source: fn(usize) -> Result<Vec<u8>, SystemError>,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
let entropy_sample = match source(size) {
|
||||||
|
Ok(sample)=> sample,
|
||||||
|
Err(e)=> { return Err(e) },
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
let mut random_fd = match OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open("/dev/urandom")
|
||||||
|
{
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(_) => {
|
||||||
|
return Err(SystemError {
|
||||||
|
message: String::from("Failed to open /dev/urandom"),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// 5.10+ kernel entropy pools are made of BLAKE2 hashes fixed at 256 bit
|
||||||
|
// The RNDADDENTROPY crediting system is now complexity with no gain.
|
||||||
|
// We just simply write samples to /dev/urandom now.
|
||||||
|
// See: https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.10.119
|
||||||
|
match random_fd.write_all(&entropy_sample) {
|
||||||
|
Ok(()) => Ok(entropy_sample.len()),
|
||||||
|
Err(_) => {
|
||||||
|
return Err(SystemError {
|
||||||
|
message: String::from("Failed to write to /dev/urandom"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue