From 2e9c69e16003495e6cc9f39600ac5910715a3e66 Mon Sep 17 00:00:00 2001 From: g2flyer Date: Fri, 31 May 2024 09:37:46 -0700 Subject: [PATCH] fixup! [LibOS] Test-cases for SPLRB Signed-off-by: g2flyer --- libos/test/regression/meson.build | 1 + libos/test/regression/pf_rollback.c | 78 +++++++++++++++++++ libos/test/regression/pf_rollback.gdb | 63 +++++++++++++++ .../regression/pf_rollback.manifest.template | 30 +++++++ libos/test/regression/test_libos.py | 21 +++++ libos/test/regression/tests.toml | 1 + libos/test/regression/tests_musl.toml | 1 + .../regression/tmp_enc/pm_non_strict/.gitkeep | 0 .../test/regression/tmp_enc/pm_none/.gitkeep | 0 .../regression/tmp_enc/pm_strict/.gitkeep | 0 10 files changed, 195 insertions(+) create mode 100644 libos/test/regression/pf_rollback.c create mode 100644 libos/test/regression/pf_rollback.gdb create mode 100644 libos/test/regression/pf_rollback.manifest.template create mode 100644 libos/test/regression/tmp_enc/pm_non_strict/.gitkeep create mode 100644 libos/test/regression/tmp_enc/pm_none/.gitkeep create mode 100644 libos/test/regression/tmp_enc/pm_strict/.gitkeep diff --git a/libos/test/regression/meson.build b/libos/test/regression/meson.build index 11c1f0156a..b8cd8ccbb9 100644 --- a/libos/test/regression/meson.build +++ b/libos/test/regression/meson.build @@ -84,6 +84,7 @@ tests = { 'c_args': '-fopenmp', 'link_args': '-fopenmp', }, + 'pf_rollback': {}, 'pipe': {}, 'pipe_nonblocking': {}, 'pipe_ocloexec': {}, diff --git a/libos/test/regression/pf_rollback.c b/libos/test/regression/pf_rollback.c new file mode 100644 index 0000000000..457698743a --- /dev/null +++ b/libos/test/regression/pf_rollback.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* Copyright (C) 2024 Intel Corporation + * Paweł Marczewski + * Michael Steiner + */ + +/* + * Tests for rollback protection of protected (encrypted) files + */ + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "rw_file.h" + +static const char message1[] = "first message\n"; +static const size_t message1_len = sizeof(message1) - 1; + +static const char message2[] = "second message\n"; +static const size_t message2_len = sizeof(message2) - 1; + +static_assert(sizeof(message1) != sizeof(message2), "the messages should have different lengths"); + +/* TODO: eventually remove below copy/paste/extract heap +static int create_file(const char* path, const char* str, size_t len) { + int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + err(1, "open %s", path); + + ssize_t n = posix_fd_write(fd, str, len); + if (n < 0) + errx(1, "posix_fd_write %s", path); + if ((size_t)n != len) + errx(1, "written less bytes than expected into %s", path); + + if (rename(path, path) != 0) + err(1, "rename"); + + if (unlink(path) != 0) + err(1, "unlink %s", path); + + if (close(fd) != 0) + err(1, "close %s", path); + +} +*/ + +/* dummy functions which are gdb break-point targets */ +static void save_file() {} +static void reset_file() {} +static void delete_file() {} +static void delete_second_file() {} + +static void test_test(const char* dir) { + save_file(); + reset_file(); + delete_file(); + delete_second_file(); +} + +int main(int argc, char* argv[]) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + if (argc != 2) + errx(1, "Usage: %s ", argv[0]); + + const char* dir = argv[1]; + + test_test(dir); + printf("TEST OK\n"); + return 0; +} diff --git a/libos/test/regression/pf_rollback.gdb b/libos/test/regression/pf_rollback.gdb new file mode 100644 index 0000000000..03a253adcd --- /dev/null +++ b/libos/test/regression/pf_rollback.gdb @@ -0,0 +1,63 @@ +set breakpoint pending on +set pagination off +set backtrace past-main on + +# We want to check what happens in the child process after fork() +set follow-fork-mode child + +# Cannot detach after fork because of some bug in SGX version of GDB (GDB would segfault) +set detach-on-fork off + +break save_file +commands + python print(f"BREAK: {gdb.selected_frame().older().name()} in {gdb.selected_frame().name()}"), + + # TODO: save file + # shell echo "WRITING NEW CONTENT IN FORK_AND_ACCESS_FILE_TESTFILE" > fork_and_access_file_testfile + + continue +end + +break reset_file +commands + python print(f"BREAK: {gdb.selected_frame().older().name()} in {gdb.selected_frame().name()}"), + + # TODO: reset file + # shell echo "WRITING NEW CONTENT IN FORK_AND_ACCESS_FILE_TESTFILE" > fork_and_access_file_testfile + + continue +end + +break delete_file +commands + python print(f"BREAK: {gdb.selected_frame().older().name()} in {gdb.selected_frame().name()}"), + + # TODO: delete file + # shell echo "WRITING NEW CONTENT IN FORK_AND_ACCESS_FILE_TESTFILE" > fork_and_access_file_testfile + + continue +end + +break delete_second_file +commands + python print(f"BREAK: {gdb.selected_frame().older().name()} in {gdb.selected_frame().name()}"), + + # TODO: delete second file + # shell echo "WRITING NEW CONTENT IN FORK_AND_ACCESS_FILE_TESTFILE" > fork_and_access_file_testfile + + continue +end + +break die_or_inf_loop +commands + echo EXITING GDB WITH A GRAMINE ERROR\n + quit +end + +break exit +commands + echo EXITING GDB WITHOUT A GRAMINE ERROR\n + quit +end + +run diff --git a/libos/test/regression/pf_rollback.manifest.template b/libos/test/regression/pf_rollback.manifest.template new file mode 100644 index 0000000000..226c59f016 --- /dev/null +++ b/libos/test/regression/pf_rollback.manifest.template @@ -0,0 +1,30 @@ +loader.entrypoint = "file:{{ gramine.libos }}" +libos.entrypoint = "{{ entrypoint }}" + +loader.env.LD_LIBRARY_PATH = "/lib:{{ arch_libdir }}:/usr/{{ arch_libdir }}" +loader.insecure__use_cmdline_argv = true + +fs.mounts = [ + { path = "/lib", uri = "file:{{ gramine.runtimedir(libc) }}" }, + { path = "/{{ entrypoint }}", uri = "file:{{ binary_dir }}/{{ entrypoint }}" }, + { path = "/bin", uri = "file:/bin" }, + + { type = "encrypted", protection_mode = "strict", path = "/tmp_enc/pm_strict", uri = "file:tmp_enc", key_name = "my_custom_key" }, + { type = "encrypted", protection_mode = "strict", path = "/tmp_enc/pm_non_strict", uri = "file:tmp_enc", key_name = "my_custom_key" }, + { type = "encrypted", protection_mode = "strict", path = "/tmp_enc/pm_none", uri = "file:tmp_enc", key_name = "my_custom_key" }, +] + +sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '16' }} +sgx.debug = true +sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} + + +sgx.trusted_files = [ + "file:{{ gramine.libos }}", + "file:{{ gramine.runtimedir(libc) }}/", + "file:{{ binary_dir }}/{{ entrypoint }}", +] + +# See the `keys.c` test. +fs.insecure__keys.default = "ffeeddccbbaa99887766554433221100" +fs.insecure__keys.my_custom_key = "00112233445566778899aabbccddeeff" diff --git a/libos/test/regression/test_libos.py b/libos/test/regression/test_libos.py index 3f16eae33e..022f35af65 100644 --- a/libos/test/regression/test_libos.py +++ b/libos/test/regression/test_libos.py @@ -1385,6 +1385,27 @@ def test_020_gdb_fork_and_access_file_bug(self): with open('fork_and_access_file_testfile', 'w') as f: f.write('fork_and_access_file_testfile') + def test_030_gdb_pf_rollback(self): + # To run this test manually, use: + # GDB=1 GDB_SCRIPT=pf_rollback.gdb gramine-[sgx|direct] pf_rollback + # + # This test checks rollback protection. + try: + stdout, _ = self.run_gdb(['pf_rollback', '/tmp_enc/pm_strict'], 'pf_rollback.gdb') + # TODO (MST): This test is not yet implemented. + # - loop for /tmp_enc/pm_strict, /tmp_enc/pm_non_strict, /tmp_enc/pm_none + # - define expected sequence for each test + self.assertIn('BREAK: test_test in save_file', stdout) + self.assertIn('BREAK: test_test in reset_file', stdout) + self.assertIn('BREAK: test_test in delete_file', stdout) + self.assertIn('BREAK: test_test in delete_second_file', stdout) + self.assertIn('EXITING GDB WITHOUT A GRAMINE ERROR', stdout) + self.assertNotIn('EXITING GDB WITH A GRAMINE ERROR', stdout) + finally: + # restore the trusted file contents (modified by the GDB script in this test) + with open('fork_and_access_file_testfile', 'w') as f: + f.write('fork_and_access_file_testfile') + class TC_80_Socket(RegressionTestCase): def test_000_getsockopt(self): stdout, _ = self.run_binary(['getsockopt']) diff --git a/libos/test/regression/tests.toml b/libos/test/regression/tests.toml index 1ed4da79f4..0108e6ef8f 100644 --- a/libos/test/regression/tests.toml +++ b/libos/test/regression/tests.toml @@ -83,6 +83,7 @@ manifests = [ "munmap", "open_opath", "openmp", + "pf_rollback", "pipe", "pipe_nonblocking", "pipe_ocloexec", diff --git a/libos/test/regression/tests_musl.toml b/libos/test/regression/tests_musl.toml index d8cbfac653..11fd1b8a0d 100644 --- a/libos/test/regression/tests_musl.toml +++ b/libos/test/regression/tests_musl.toml @@ -85,6 +85,7 @@ manifests = [ "munmap", "open_opath", "openmp", + "pf_rollback", "pipe", "pipe_nonblocking", "pipe_ocloexec", diff --git a/libos/test/regression/tmp_enc/pm_non_strict/.gitkeep b/libos/test/regression/tmp_enc/pm_non_strict/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libos/test/regression/tmp_enc/pm_none/.gitkeep b/libos/test/regression/tmp_enc/pm_none/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libos/test/regression/tmp_enc/pm_strict/.gitkeep b/libos/test/regression/tmp_enc/pm_strict/.gitkeep new file mode 100644 index 0000000000..e69de29bb2