diff --git a/.gitignore b/.gitignore index a3b7452..9e8d4b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ out/* cache/* .* +src/init/target diff --git a/Makefile b/Makefile index eff93cf..59f22e1 100644 --- a/Makefile +++ b/Makefile @@ -218,6 +218,7 @@ define toolchain --env KBUILD_BUILD_TIMESTAMP=$(KBUILD_BUILD_TIMESTAMP) \ --env KCONFIG_NOTIMESTAMP=$(KCONFIG_NOTIMESTAMP) \ --env SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \ + --env CARGO_HOME=/cache/cargo \ local/$(NAME)-build \ bash -c $(2) endef @@ -250,12 +251,12 @@ $(OUT_DIR)/busybox: \ $(OUT_DIR)/init: $(call toolchain,$(USER)," \ - gcc \ - -static \ - -static-libgcc /src/init/init.c \ - -o /out/init; \ + cd /src/init/ && \ + RUSTFLAGS='-C target-feature=+crt-static' cargo build --release && \ + cp /src/init/target/release/init /out/init \ ") + $(CACHE_DIR)/linux-$(LINUX_VERSION)/usr/gen_init_cpio: \ $(CACHE_DIR)/linux-$(LINUX_VERSION) \ $(CACHE_DIR)/linux-$(LINUX_VERSION) \ @@ -269,21 +270,17 @@ $(CACHE_DIR)/linux-$(LINUX_VERSION)/usr/gen_init_cpio: \ $(OUT_DIR)/$(TARGET)/rootfs.cpio: \ $(OUT_DIR)/busybox \ $(OUT_DIR)/init \ + $(OUT_DIR)/aws/nsm.ko \ $(CACHE_DIR)/linux-$(LINUX_VERSION)/usr/gen_init_cpio - mkdir -p $(CACHE_DIR)/$(TARGET)/rootfs/bin - cp $(CONFIG_DIR)/generic/rootfs.list $(CACHE_DIR)/$(TARGET)/rootfs.list + cp $(CONFIG_DIR)/$(TARGET)/rootfs.list $(CACHE_DIR)/$(TARGET)/rootfs.list + cp $(OUT_DIR)/init $(CACHE_DIR)/$(TARGET)/rootfs/init ifeq ($(DEBUG), true) - cp $(OUT_DIR)/init $(CACHE_DIR)/$(TARGET)/rootfs/real_init + mv $(CACHE_DIR)/$(TARGET)/rootfs/init $(CACHE_DIR)/$(TARGET)/rootfs/real_init cp $(SRC_DIR)/scripts/busybox_init $(CACHE_DIR)/$(TARGET)/rootfs/init + mkdir -p $(CACHE_DIR)/$(TARGET)/rootfs/bin cp $(OUT_DIR)/busybox $(CACHE_DIR)/$(TARGET)/rootfs/bin/ echo "file /bin/busybox /cache/rootfs/bin/busybox 0755 0 0" \ >> $(CACHE_DIR)/$(TARGET)/rootfs.list -else - cp $(OUT_DIR)/init $(CACHE_DIR)/$(TARGET)/rootfs/init -endif -ifeq ($(TARGET), aws) - echo "file /nsm.ko /out/aws/nsm.ko 0755 0 0" \ - >> $(CACHE_DIR)/$(TARGET)/rootfs.list endif $(call toolchain,$(USER)," \ cd /cache/$(TARGET)/rootfs && \ @@ -294,11 +291,11 @@ endif -o /out/$(TARGET)/rootfs.cpio \ /cache/$(TARGET)/rootfs.list && \ cpio -itv < /out/$(TARGET)/rootfs.cpio && \ - sha256sum /out/rootfs.cpio; \ + sha256sum /out/$(TARGET)/rootfs.cpio; \ ") $(OUT_DIR)/$(TARGET)/bzImage: \ - $(OUT_DIR)/rootfs.cpio + $(OUT_DIR)/$(TARGET)/rootfs.cpio $(call toolchain,$(USER)," \ cd /cache/linux-$(LINUX_VERSION) && \ cp /config/$(TARGET)/linux.config .config && \ @@ -332,14 +329,14 @@ endif $(OUT_DIR)/aws/nitro.eif: \ $(OUT_DIR)/aws/eif_build \ $(OUT_DIR)/$(TARGET)/bzImage \ - $(OUT_DIR)/rootfs.cpio + $(OUT_DIR)/$(TARGET)/rootfs.cpio ifeq ($(TARGET), aws) $(call toolchain,$(USER)," \ /out/eif_build \ --kernel /out/$(TARGET)/bzImage \ --kernel_config /config/$(TARGET)/linux.config \ --cmdline 'reboot=k initrd=0x2000000$(,)3228672 root=/dev/ram0 panic=1 pci=off nomodules console=ttyS0 i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd' \ - --ramdisk /out/rootfs.cpio \ + --ramdisk /out/aws/rootfs.cpio \ --output /out/aws/nitro.eif; \ ") endif diff --git a/config/aws/rootfs.list b/config/aws/rootfs.list new file mode 100644 index 0000000..ba57101 --- /dev/null +++ b/config/aws/rootfs.list @@ -0,0 +1,12 @@ +dir /dev 0755 0 0 +nod /dev/console 0600 0 0 c 5 1 +dir /sys 0755 0 0 +dir /usr 0755 0 0 +dir /etc 0755 0 0 +dir /proc 0755 0 0 +dir /bin 0755 0 0 +dir /sbin 0755 0 0 +dir /usr/bin 0755 0 0 +dir /usr/sbin 0755 0 0 +file /init /cache/aws/rootfs/init 0755 0 0 +file /nsm.ko /out/aws/nsm.ko 0755 0 0 diff --git a/src/init/Cargo.lock b/src/init/Cargo.lock new file mode 100644 index 0000000..e75c922 --- /dev/null +++ b/src/init/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "init" +version = "0.1.0" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.134" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" diff --git a/src/init/Cargo.toml b/src/init/Cargo.toml new file mode 100644 index 0000000..dbd0f2c --- /dev/null +++ b/src/init/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "init" +version = "0.1.0" +edition = "2021" + +[dependencies] +libc = "0.2.134" + +[[bin]] +name = "init" +path = "init.rs" diff --git a/src/init/init.c b/src/init/init.c deleted file mode 100644 index e590cb1..0000000 --- a/src/init/init.c +++ /dev/null @@ -1,189 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -_Noreturn void die(const char *msg); -#define die_on(CONDITION, ...) \ - do { \ - if (CONDITION) { \ - die(__VA_ARGS__); \ - } \ - } while (0) - -#define finit_module(fd, param_values, flags) (int)syscall(__NR_finit_module, fd, param_values, flags) -#define DEFAULT_PATH_ENV "PATH=/sbin:/usr/sbin:/bin:/usr/bin" -#define NSM_PATH "nsm.ko" -#define TIMEOUT 20000 -#define VSOCK_PORT 9000 -#define VSOCK_CID 3 -#define HEART_BEAT 0xB7 - -const char *const default_envp[] = { - DEFAULT_PATH_ENV, - NULL, -}; - -const char *const default_argv[] = { "sh", NULL }; - -struct Mount { - const char *source, *target, *type; - unsigned long flags; - const void *data; -}; - -struct Mkdir { - const char *path; - mode_t mode; -}; - -struct Mknod { - const char *path; - mode_t mode; - int major, minor; -}; - -struct Symlink { - const char *linkpath, *target; -}; - -enum OpType { - OpMount, - OpMkdir, - OpMknod, - OpSymlink, -}; - -struct InitOp { - enum OpType op; - union { - struct Mount mount; - struct Mkdir mkdir; - struct Mknod mknod; - struct Symlink symlink; - }; -}; - -const struct InitOp ops[] = { - { OpMount, .mount = { "proc", "/proc", "proc", MS_NODEV | MS_NOSUID | MS_NOEXEC } }, - { OpSymlink, .symlink = { "/dev/fd", "/proc/self/fd" } }, - { OpSymlink, .symlink = { "/dev/stdin", "/proc/self/fd/0" } }, - { OpSymlink, .symlink = { "/dev/stdout", "/proc/self/fd/1" } }, - { OpSymlink, .symlink = { "/dev/stderr", "/proc/self/fd/2" } }, - { OpMkdir, .mkdir = { "/dev/shm", 0755 } }, - { OpMkdir, .mkdir = { "/dev/pts", 0755 } }, - { OpMount, .mount = { "devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC } }, - { OpMount, .mount = { "sysfs", "/sys", "sysfs", MS_NODEV | MS_NOSUID | MS_NOEXEC } }, -}; - -void warn(const char *msg) { - int error = errno; - perror(msg); - errno = error; -} - -void warn2(const char *msg1, const char *msg2) { - int error = errno; - fputs(msg1, stderr); - fputs(": ", stderr); - errno = error; - warn(msg2); -} - -_Noreturn void dien() { - exit(errno); -} - -_Noreturn void die(const char *msg) { - warn(msg); - dien(); -} - -_Noreturn void die2(const char *msg1, const char *msg2) { - warn2(msg1, msg2); - dien(); -} - -void init_dev() { - if (mount("dev", "/dev", "devtmpfs", MS_NOSUID | MS_NOEXEC, NULL) < 0) { - warn2("mount", "/dev"); - if (errno != EBUSY) { - dien(); - } - } -} - -void init_console() { - const char *console_path = "/dev/console"; - die_on(freopen(console_path, "r", stdin) == NULL, - "freopen failed for stdin"); - die_on(freopen(console_path, "w", stdout) == NULL, - "freopen failed for stdout"); - die_on(freopen(console_path, "w", stderr) == NULL, - "freopen failed for stderr"); -} - -void enclave_ready() { - int socket_fd; - struct sockaddr_vm sa = { - .svm_family = AF_VSOCK, - .svm_cid = VSOCK_CID, - .svm_port = VSOCK_PORT, - .svm_reserved1 = 0, - }; - - uint8_t buf[1]; - buf[0] = HEART_BEAT; - errno = -EINVAL; - - socket_fd = socket(AF_VSOCK, SOCK_STREAM, 0); - die_on(socket_fd < 0, "socket"); - die_on(connect(socket_fd, (struct sockaddr*) &sa, sizeof(sa)), "connect"); - die_on(write(socket_fd, buf, 1) != 1, "write heartbeat"); - die_on(read(socket_fd, buf, 1) != 1, "read heartbeat"); - die_on(buf[0] != HEART_BEAT, "received wrong heartbeat"); - die_on(close(socket_fd), "close"); -} - -void init_nsm_driver() { - int fd; - int rc; - - fd = open(NSM_PATH, O_RDONLY | O_CLOEXEC); - if (fd < 0 && errno == ENOENT) { - return; - } - die_on(fd < 0, "failed to open nsm fd"); - rc = finit_module(fd, "", 0); - die_on(rc < 0, "failed to insert nsm driver"); - - die_on(close(fd), "close nsm fd"); - rc = unlink(NSM_PATH); - if (rc < 0) - warn("Could not unlink " NSM_PATH); -} - -int main() { - init_dev(); - init_console(); - init_nsm_driver(); - enclave_ready(); - puts("\nHello World with NSM!\n"); - reboot(RB_AUTOBOOT); -} diff --git a/src/init/init.rs b/src/init/init.rs new file mode 100644 index 0000000..7a0e3da --- /dev/null +++ b/src/init/init.rs @@ -0,0 +1,65 @@ +extern crate libc; +use libc::mount; +use libc::read; +use libc::write; +use libc::close; +use libc::reboot; +use libc::socket; +use libc::connect; +use libc::freopen; +use libc::fdopen; +use libc::c_void; +use libc::sockaddr; +use libc::sockaddr_vm; +use libc::SOCK_STREAM; +use libc::AF_VSOCK; +use libc::MS_NOSUID; +use libc::MS_NOEXEC; +use libc::RB_AUTOBOOT; +use std::mem::zeroed; +use std::mem::size_of; + +fn main() { + unsafe { + mount( + b"devtmpfs\0".as_ptr() as _, + b"/dev\0".as_ptr() as _, + b"devtmpfs\0".as_ptr() as _, + MS_NOSUID | MS_NOEXEC, + b"mode=0755\0".as_ptr() as *const c_void, + ); + freopen( + b"/dev/console\0".as_ptr() as _, + b"r\0".as_ptr() as _, + fdopen(0, b"r\0".as_ptr() as *const i8) + ); + freopen( + b"/dev/console\0".as_ptr() as _, + b"w\0".as_ptr() as _, + fdopen(1, b"w\0".as_ptr() as *const i8) + ); + freopen( + b"/dev/console\0".as_ptr() as _, + b"w\0".as_ptr() as _, + + fdopen(2, b"w\0".as_ptr() as *const i8) + ); + let mut sa: sockaddr_vm = zeroed(); + sa.svm_family = AF_VSOCK as _; + sa.svm_port = 9000; + sa.svm_cid = 3; + let fd = socket(AF_VSOCK, SOCK_STREAM, 0); + connect( + fd, + &sa as *const _ as *mut sockaddr, + size_of::() as _, + ); + let mut buf: [u8; 1] = [0; 1]; + buf[0] = 0xB7; + write(fd, buf.as_ptr() as _, 1); + read(fd, buf.as_ptr() as _, 1); + close(fd); + println!("Hello World from Rust init!"); + reboot(RB_AUTOBOOT); + } +}