Import init code from EnclaveOS to build standalone
This commit is contained in:
commit
3005596663
|
@ -0,0 +1,16 @@
|
||||||
|
FROM stagex/pallet-rust@sha256:740b9ed5f2a897d45cafdc806976d84231aa50a64998610750b42a48f8daacab as build
|
||||||
|
|
||||||
|
ENV TARGET=x86_64-unknown-linux-musl
|
||||||
|
ENV RUSTFLAGS="-C target-feature=+crt-static"
|
||||||
|
ENV CARGOFLAGS="--locked --no-default-features --release --target ${TARGET}"
|
||||||
|
|
||||||
|
ADD . /src
|
||||||
|
|
||||||
|
WORKDIR /src/init
|
||||||
|
RUN cargo build ${CARGOFLAGS}
|
||||||
|
|
||||||
|
WORKDIR /rootfs
|
||||||
|
RUN cp /src/init/target/${TARGET}/release/init .
|
||||||
|
|
||||||
|
FROM scratch as package
|
||||||
|
COPY --from=build /rootfs .
|
|
@ -0,0 +1,5 @@
|
||||||
|
Copyright 2024 Distrust, Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -0,0 +1,13 @@
|
||||||
|
.PHONY: default
|
||||||
|
default: out/init
|
||||||
|
|
||||||
|
out:
|
||||||
|
mkdir out
|
||||||
|
|
||||||
|
out/init: out
|
||||||
|
docker build \
|
||||||
|
--tag local/init \
|
||||||
|
--progress=plain \
|
||||||
|
--output type=local,rewrite-timestamp=true,dest=out\
|
||||||
|
-f Containerfile \
|
||||||
|
src/
|
|
@ -0,0 +1,24 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aws"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"system",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.174"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
|
@ -0,0 +1,10 @@
|
||||||
|
[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"
|
||||||
|
system = { path = "../system"}
|
|
@ -0,0 +1,34 @@
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aws"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"system",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "init"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"aws",
|
||||||
|
"libc",
|
||||||
|
"system",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.134"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "init"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.134"
|
||||||
|
aws = { path = "../aws"}
|
||||||
|
system = { path = "../system"}
|
||||||
|
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "init"
|
||||||
|
path = "init.rs"
|
|
@ -0,0 +1,54 @@
|
||||||
|
use system::{reboot, freopen, mount, dmesg};
|
||||||
|
|
||||||
|
use aws::{init_platform};
|
||||||
|
|
||||||
|
// Mount common filesystems with conservative permissions
|
||||||
|
fn init_rootfs() {
|
||||||
|
use libc::{MS_NOSUID, MS_NOEXEC, MS_NODEV };
|
||||||
|
let no_dse = MS_NODEV | MS_NOSUID | MS_NOEXEC;
|
||||||
|
let no_se = MS_NOSUID | MS_NOEXEC;
|
||||||
|
let args = [
|
||||||
|
("devtmpfs", "/dev", "devtmpfs", no_se, "mode=0755"),
|
||||||
|
("devtmpfs", "/dev", "devtmpfs", no_se, "mode=0755"),
|
||||||
|
("devpts", "/dev/pts", "devpts", no_se, ""),
|
||||||
|
("shm", "/dev/shm", "tmpfs", no_dse, "mode=0755"),
|
||||||
|
("proc", "/proc", "proc", no_dse, "hidepid=2"),
|
||||||
|
("tmpfs", "/run", "tmpfs", no_dse, "mode=0755"),
|
||||||
|
("tmpfs", "/tmp", "tmpfs", no_dse, ""),
|
||||||
|
("sysfs", "/sys", "sysfs", no_dse, ""),
|
||||||
|
("cgroup_root", "/sys/fs/cgroup", "tmpfs", no_dse, "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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize console with stdin/stdout/stderr
|
||||||
|
fn init_console() {
|
||||||
|
let args = [
|
||||||
|
("/dev/console", "r", 0),
|
||||||
|
("/dev/console", "w", 1),
|
||||||
|
("/dev/console", "w", 2),
|
||||||
|
];
|
||||||
|
for (filename, mode, file) in args {
|
||||||
|
match freopen(filename, mode, file) {
|
||||||
|
Ok(())=> {},
|
||||||
|
Err(e)=> eprintln!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn boot(){
|
||||||
|
init_rootfs();
|
||||||
|
init_console();
|
||||||
|
init_platform();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
boot();
|
||||||
|
dmesg("System booted".to_string());
|
||||||
|
reboot();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.174"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
|
@ -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,129 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue