Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken sigining of EXT2 rootfs #1456

Merged
merged 1 commit into from
Feb 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion samples/helloworld/ext2rootfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ package.pem:

package: package.pem ext2rootfs
echo "Generating a signed package"
@myst package-sgx --roothash=roothash appdir package.pem ../config.json
@myst package-sgx --roothash=roothash package.pem ../config.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean when both roothash and appdir are present in args? Should this be prevented(we should not change what we have, just wondering..)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TEE_aware sample also takes appdir as a command line arg


export MYST_ROOTFS_PATH=$(CURDIR)/ext2rootfs

run: package
echo "Running Mystikos packaged application. No myst exec-sgx necessary"
Expand Down
59 changes: 59 additions & 0 deletions tests/sign/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
TOP=$(abspath ../..)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test should live in the tests/myst directory with the other signing tests

include $(TOP)/defs.mak

APPDIR = appdir
CFLAGS = -fPIC
LDFLAGS = -Wl,-rpath=$(MUSL_LIB)

all:
$(MAKE) myst
$(MAKE) rootfs

rootfs: hello.c
mkdir -p $(APPDIR)/bin
$(CC) $(CFLAGS) -o $(APPDIR)/bin/hello hello.c $(LDFLAGS)
$(MYST) mkext2 $(APPDIR) rootfs

OPTS =

ifdef STRACE
OPTS += --strace
endif

ifdef PERF
OPTS += --perf
endif

OPTS += --thread-stack-size=1048576

tests: all
$(RUNTEST) $(MYST_EXEC) rootfs /bin/hello $(OPTS)
$(MAKE) sign
$(MAKE) verify
$(MAKE) fail
@ echo "=== passed all tests"

private.pem:
openssl genrsa -out private.pem -3 3072

sign: private.pem
$(MYST) fssig --roothash rootfs > roothash
rm -rf hello.signed
$(MYST) sign-sgx rootfs private.pem config.json --roothash=roothash

verify:
( cd hello.signed; ./bin/myst exec-sgx rootfs /bin/hello $(OPTS) )

myst:
$(MAKE) -C $(TOP)/tools/myst

clean:
rm -rf $(APPDIR) rootfs export ramfs hello.signed roothash private.pem

##
## Negative test to verify that hacking rootfs fails loading.
##
fail:
$(MAKE) sign
$(MYST) mkext2 --force $(APPDIR) hello.signed/rootfs
$(MAKE) verify 2> /dev/null; test $$? -eq 2
5 changes: 5 additions & 0 deletions tests/sign/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sign
====

This test verifies that a simple Mystikos application can be signed and
executed.
13 changes: 13 additions & 0 deletions tests/sign/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "0.1",
"Debug": 1,
"ProductID": 1,
"SecurityVersion": 1,
"MemorySize": "40m",
"ThreadStackSize": "16m",
"ApplicationPath": "/bin/hello",
"ApplicationParameters": [],
"HostApplicationParameters": false,
"EnvironmentVariables": [],
"HostEnvironmentVariables": []
}
17 changes: 17 additions & 0 deletions tests/sign/hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, const char* argv[])
{
printf("Hello!\n");
printf("=== passed test (%s)\n", argv[0]);

return 0;
}
32 changes: 31 additions & 1 deletion tools/myst/host/sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <myst/file.h>
#include <myst/strings.h>
#include <myst/types.h>
#include <myst/cpio.h>
#include <openenclave/host.h>
#include "../config.h"
#include "myst_u.h"
Expand Down Expand Up @@ -67,6 +68,11 @@ and <options> are one of:\n\
--outdir <path> -- optional output directory path. If not\n\
specified goes into the configurations\n\
<appdir>.signed directpry\n\
--roothash=<filename> -- add the root hash given by filename to\n\
the image when siging, which permits\n\
mounting of EXT2 root file systems.\n\
The file argument contains an ASCII root\n\
hash.\n\
\n\
"

Expand Down Expand Up @@ -293,6 +299,7 @@ int _sign(int argc, const char* argv[])
const char* signing_engine_name = NULL;
const char* signing_engine_path = NULL;
myst_buf_t roothash_buf = MYST_BUF_INITIALIZER;
char rootfs_path[] = "/tmp/mystXXXXXX";

// We are in the right operation, right?
assert(
Expand Down Expand Up @@ -341,6 +348,7 @@ int _sign(int argc, const char* argv[])

const char* program_file = get_program_file();
const char* rootfs_file = argv[2];
const char* rootfs = rootfs_file;
const char* pem_file = argv[3];
const char* config_file = argv[4];
const char* target = NULL; // Extracted from config file
Expand Down Expand Up @@ -440,10 +448,28 @@ int _sign(int argc, const char* argv[])
assert(myst_validate_file_path(program_file));
assert(myst_validate_file_path(temp_oeconfig_file));

/* if not a CPIO archive, create a zero-filled file with one page */
if (myst_cpio_test(rootfs) == -ENOTSUP)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check roothashes_opt for a quicker determination?

{
int fd;
uint8_t page[PAGE_SIZE];

if ((fd = mkstemp(rootfs_path)) < 0)
_err("failed to create temporary file");

memset(page, 0, sizeof(page));

if (write(fd, page, sizeof(page)) != sizeof(page))
_err("failed to create file");

close(fd);
rootfs = rootfs_path;
}

// Setup all the regions
if ((details = create_region_details_from_files(
target,
rootfs_file,
rootfs,
pubkeys_opt,
roothashes_opt,
config_file,
Expand All @@ -453,6 +479,10 @@ int _sign(int argc, const char* argv[])
_err("Creating region data failed.");
}

// Remove temporary file:
if (rootfs == rootfs_path)
unlink(rootfs);

if (copy_files_to_signing_directory(
sign_dir,
program_file,
Expand Down