Aws target booting in live nitro enclaves
This commit is contained in:
parent
db8f90ad47
commit
200f4d94f6
11
Makefile
11
Makefile
|
@ -10,6 +10,7 @@ USER := $(shell id -g):$(shell id -g)
|
||||||
CPUS := $(shell nproc)
|
CPUS := $(shell nproc)
|
||||||
ARCH := x86_64
|
ARCH := x86_64
|
||||||
TARGET_NAME := bzImage
|
TARGET_NAME := bzImage
|
||||||
|
, := ,
|
||||||
|
|
||||||
include $(PWD)/config/global.env
|
include $(PWD)/config/global.env
|
||||||
|
|
||||||
|
@ -291,7 +292,7 @@ $(OUT_DIR)/$(TARGET)/bzImage: \
|
||||||
sha256sum /out/$(TARGET)/bzImage; \
|
sha256sum /out/$(TARGET)/bzImage; \
|
||||||
")
|
")
|
||||||
|
|
||||||
$(OUT_DIR)/$(TARGET)/eif_build:
|
$(OUT_DIR)/aws/eif_build:
|
||||||
ifeq ($(TARGET), aws)
|
ifeq ($(TARGET), aws)
|
||||||
$(call toolchain,$(USER)," \
|
$(call toolchain,$(USER)," \
|
||||||
cd /cache/aws-nitro-enclaves-image-format \
|
cd /cache/aws-nitro-enclaves-image-format \
|
||||||
|
@ -300,8 +301,8 @@ ifeq ($(TARGET), aws)
|
||||||
")
|
")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(OUT_DIR)/$(TARGET)/nitro.eif: \
|
$(OUT_DIR)/aws/nitro.eif: \
|
||||||
$(OUT_DIR)/$(TARGET)/eif_build \
|
$(OUT_DIR)/aws/eif_build \
|
||||||
$(OUT_DIR)/$(TARGET)/bzImage \
|
$(OUT_DIR)/$(TARGET)/bzImage \
|
||||||
$(OUT_DIR)/rootfs.cpio
|
$(OUT_DIR)/rootfs.cpio
|
||||||
ifeq ($(TARGET), aws)
|
ifeq ($(TARGET), aws)
|
||||||
|
@ -309,9 +310,9 @@ ifeq ($(TARGET), aws)
|
||||||
/out/eif_build \
|
/out/eif_build \
|
||||||
--kernel /out/$(TARGET)/bzImage \
|
--kernel /out/$(TARGET)/bzImage \
|
||||||
--kernel_config /config/$(TARGET)/linux.config \
|
--kernel_config /config/$(TARGET)/linux.config \
|
||||||
--cmdline "init=/init" \
|
--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/rootfs.cpio \
|
||||||
--output /out/$(TARGET)/nitro.eif \
|
--output /out/aws/nitro.eif; \
|
||||||
")
|
")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
7
TODO
7
TODO
|
@ -1,7 +1,6 @@
|
||||||
* Optionally link rootfs into kernel based on target
|
|
||||||
* Fully carve out dedicated nitro target
|
|
||||||
* Only build nitro with TARGET=nitro
|
|
||||||
* verify nitro demo actually boots in live enclaves
|
|
||||||
* have "sign" make target that creates/signs hash manifest of all targets
|
* have "sign" make target that creates/signs hash manifest of all targets
|
||||||
* compile against musl
|
* compile against musl
|
||||||
* fix kernel cache misses that result in re-pull/rebuild on every build
|
* fix kernel cache misses that result in re-pull/rebuild on every build
|
||||||
|
* harden aws kernel to Kernel Self Protection Project guidelines
|
||||||
|
* get nitro init binary to return attestation cert from amazon
|
||||||
|
* re-write c init in rust
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
190
src/init/init.c
190
src/init/init.c
|
@ -1,9 +1,189 @@
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <linux/vm_sockets.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
_Noreturn void die(const char *msg);
|
||||||
(void) argc;
|
#define die_on(CONDITION, ...) \
|
||||||
(void) argv;
|
do { \
|
||||||
puts("Appliance Linux Sample Init");
|
if (CONDITION) { \
|
||||||
sleep(0xFFFFFFFF);
|
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!\n");
|
||||||
|
reboot(RB_AUTOBOOT);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue