From 6eca51679b87451bbd28de1cca4195fa05e2a9db Mon Sep 17 00:00:00 2001 From: g2flyer Date: Wed, 1 May 2024 11:26:01 -0700 Subject: [PATCH] fixup! Single-process-lifetime rollback protection for protected files (WIP) Signed-off-by: g2flyer --- libos/include/libos_fs_encrypted.h | 1 + libos/src/fs/chroot/encrypted.c | 7 +++++++ libos/src/fs/libos_fs_encrypted.c | 28 ++++++++++++++++++++++++---- libos/test/regression/rename_unlink | 1 + 4 files changed, 33 insertions(+), 4 deletions(-) create mode 120000 libos/test/regression/rename_unlink diff --git a/libos/include/libos_fs_encrypted.h b/libos/include/libos_fs_encrypted.h index cf4e022057..f1728035f3 100644 --- a/libos/include/libos_fs_encrypted.h +++ b/libos/include/libos_fs_encrypted.h @@ -202,6 +202,7 @@ int encrypted_file_read(struct libos_encrypted_file* enc, void* buf, size_t buf_ int encrypted_file_write(struct libos_encrypted_file* enc, const void* buf, size_t buf_size, file_off_t offset, size_t* out_count); int encrypted_file_rename(struct libos_encrypted_file* enc, const char* new_uri); +int encrypted_file_unlink(struct libos_encrypted_file* enc); int encrypted_file_get_size(struct libos_encrypted_file* enc, file_off_t* out_size); int encrypted_file_set_size(struct libos_encrypted_file* enc, file_off_t size); diff --git a/libos/src/fs/chroot/encrypted.c b/libos/src/fs/chroot/encrypted.c index efa68a5f5b..7b771aee43 100644 --- a/libos/src/fs/chroot/encrypted.c +++ b/libos/src/fs/chroot/encrypted.c @@ -338,6 +338,13 @@ static int chroot_encrypted_unlink(struct libos_dentry* dent) { if (ret < 0) return ret; + struct libos_encrypted_file* enc = dent->inode->data; + if (!enc) + return -EACCES; + ret = encrypted_file_unlink(enc); + if (ret < 0) + return ret; + PAL_HANDLE palhdl; ret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER, PAL_OPTION_PASSTHROUGH, &palhdl); diff --git a/libos/src/fs/libos_fs_encrypted.c b/libos/src/fs/libos_fs_encrypted.c index 0398225a6b..4c33b28ed6 100644 --- a/libos/src/fs/libos_fs_encrypted.c +++ b/libos/src/fs/libos_fs_encrypted.c @@ -300,8 +300,13 @@ static void encrypted_file_internal_close(struct libos_encrypted_file* enc) { file_state->state = PF_FILE_ERROR; pf_set_corrupted(enc->pf); } else { - memcpy(file_state->last_seen_root_gmac, closing_root_gmac, sizeof(pf_mac_t)); - file_state->state = PF_FILE_CLOSED; + // TODO (MST): Below also has to rule out that our file is stale, i.e., somebody has renamed + // a file to our own original file name + if (file_state->state != PF_FILE_DELETED) { + // TODO (MST): omit below if read-only file? + memcpy(file_state->last_seen_root_gmac, closing_root_gmac, sizeof(pf_mac_t)); + file_state->state = PF_FILE_CLOSED; + } } unlock(&(enc->volume->files_state_map_lock)); @@ -768,8 +773,8 @@ int encrypted_file_rename(struct libos_encrypted_file* enc, const char* new_uri) HASH_ADD_KEYPTR(hh, enc->volume->files_state_map, new_file_state->norm_path, strlen(new_file_state->norm_path), new_file_state); } else { - free(new_file_state->norm_path); // should be same but free old one to simplify below - new_file_state->norm_path = new_norm_path; + free(new_norm_path); // should be same as old one used during HASH_ADD + new_norm_path = new_file_state->norm_path; } new_file_state->state = old_file_state->state; memcpy(new_file_state->last_seen_root_gmac, new_root_gmac, sizeof(pf_mac_t)); @@ -803,6 +808,21 @@ int encrypted_file_rename(struct libos_encrypted_file* enc, const char* new_uri) return ret; } +int encrypted_file_unlink(struct libos_encrypted_file* enc) { + lock(&(enc->volume->files_state_map_lock)); + struct libos_encrypted_volume_state_map* file_state = NULL; + HASH_FIND_STR(enc->volume->files_state_map, enc->norm_path, file_state); + assert(file_state != NULL); + pf_mac_t root_gmac_before_unlink; + memcpy(root_gmac_before_unlink, file_state->last_seen_root_gmac, sizeof(pf_mac_t)); + file_state->state = PF_FILE_DELETED; + memset(file_state->last_seen_root_gmac, 0, sizeof(pf_mac_t)); + unlock(&(enc->volume->files_state_map_lock)); + log_debug("file '%s' unlinked, previously with MAC=" MAC_PRINTF_PATTERN, enc->norm_path, + MAC_PRINTF_ARGS(root_gmac_before_unlink)); // TODO (MST): remove me eventually? + return 0; +} + /* Checkpoint the `g_keys` list. */ BEGIN_CP_FUNC(all_encrypted_files_keys) { __UNUSED(size); diff --git a/libos/test/regression/rename_unlink b/libos/test/regression/rename_unlink new file mode 120000 index 0000000000..aacb13a56b --- /dev/null +++ b/libos/test/regression/rename_unlink @@ -0,0 +1 @@ +../../../build/libos/test/regression/rename_unlink \ No newline at end of file