From 17d0062bf261929b97f4468a9bf01db120b830a0 Mon Sep 17 00:00:00 2001 From: g2flyer Date: Wed, 22 May 2024 10:32:14 -0700 Subject: [PATCH] fixup! [LibOS] Single-process-lifetime rollback protection for protected files (WIP) Signed-off-by: g2flyer --- libos/include/libos_fs_encrypted.h | 20 ++--- libos/src/fs/chroot/encrypted.c | 32 +++++--- libos/src/fs/libos_fs_encrypted.c | 103 ++++++++++++-------------- python/graminelibos/manifest_check.py | 1 + 4 files changed, 77 insertions(+), 79 deletions(-) diff --git a/libos/include/libos_fs_encrypted.h b/libos/include/libos_fs_encrypted.h index aab66643da..69bcb77b04 100644 --- a/libos/include/libos_fs_encrypted.h +++ b/libos/include/libos_fs_encrypted.h @@ -146,6 +146,14 @@ bool read_encrypted_files_key(struct libos_encrypted_files_key* key, pf_key_t* p */ void update_encrypted_files_key(struct libos_encrypted_files_key* key, const pf_key_t* pf_key); +/* + * \brief Register a volume. + * + * Registers passed volume -- assumed to be initialized, in particular with valid mount_point_path + * -- in global list of mounted volumes. Returns an error if a volume with identical + * mount_point_path already exists. + */ +int register_encrypted_volume(struct libos_encrypted_volume* volume); /* * \brief Retrieve a volume. * @@ -164,18 +172,6 @@ struct libos_encrypted_volume* get_encrypted_volume(const char* mount_point_path int list_encrypted_volumes(int (*callback)(struct libos_encrypted_volume* volume, void* arg), void* arg); -/* - * \brief Create a volume. - * - * Sets `*out_volume` to a volume with given mount_point_path. If the volume has not been created - * yet, creates a new one (with mount_point_path and list only fields initialized!). - * out_created is set to whether volume is newly created or not. - * - * Similar to `get_encrypted_volumes`, this does not pass ownership of `*out_volume`. - */ -int get_or_create_encrypted_volume(const char* mount_point_path, - struct libos_encrypted_volume** out_volume, bool* out_created); - /* * \brief Open an existing encrypted file. * diff --git a/libos/src/fs/chroot/encrypted.c b/libos/src/fs/chroot/encrypted.c index 0e5290678e..c510b9c136 100644 --- a/libos/src/fs/chroot/encrypted.c +++ b/libos/src/fs/chroot/encrypted.c @@ -85,24 +85,36 @@ static int chroot_encrypted_mount(struct libos_mount_params* params, void** moun } struct libos_encrypted_volume* volume; - bool created; - ret = get_or_create_encrypted_volume(params->path, &volume, &created); - if (ret < 0) - return ret; - if (!created) { - log_error("Volume '%s' is already mounted", params->path); - return -EEXIST; + volume = calloc(1, sizeof(*volume)); + if (!volume) + return -ENOMEM; + volume->mount_point_path = strdup(params->path); + if (!volume->mount_point_path) { + ret = -ENOMEM; + goto err; } volume->protection_mode = protection_mode; - volume->key = key; + volume->key = key; if (!create_lock(&volume->files_state_map_lock)) { - free(volume); - return -ENOMEM; + ret = -ENOMEM; + goto err; } volume->files_state_map = NULL; + ret = register_encrypted_volume(volume); + if (ret < 0) + goto err; + *mount_data = volume; return 0; +err: + if (volume) { + if (lock_created(&volume->files_state_map_lock)) + destroy_lock(&volume->files_state_map_lock); + free(volume->mount_point_path); + } + free(volume); + return ret; } static ssize_t chroot_encrypted_checkpoint(void** checkpoint, void* mount_data) { diff --git a/libos/src/fs/libos_fs_encrypted.c b/libos/src/fs/libos_fs_encrypted.c index 8e7d2b648e..d96e8cf7c0 100644 --- a/libos/src/fs/libos_fs_encrypted.c +++ b/libos/src/fs/libos_fs_encrypted.c @@ -552,43 +552,19 @@ static struct libos_encrypted_volume* get_volume(const char* mount_point_path) { return NULL; } -static struct libos_encrypted_volume* get_or_create_volume(const char* mount_point_path, - bool* out_created) { - assert(locked(&g_volumes_lock)); - - struct libos_encrypted_volume* volume = get_volume(mount_point_path); - if (volume) { - *out_created = false; - return volume; - } +int register_encrypted_volume(struct libos_encrypted_volume* volume) { + assert(volume && volume->mount_point_path); - volume = calloc(1, sizeof(*volume)); - if (!volume) - return NULL; - volume->mount_point_path = strdup(mount_point_path); - if (!volume->mount_point_path) { - free(volume); - return NULL; - } - LISTP_ADD_TAIL(volume, &g_volumes, list); - *out_created = true; - return volume; -} - -int get_or_create_encrypted_volume(const char* mount_point_path, - struct libos_encrypted_volume** out_volume, bool* out_created) { lock(&g_volumes_lock); - int ret; + int ret = 0; - struct libos_encrypted_volume* volume = get_or_create_volume(mount_point_path, out_created); - if (!volume) { - ret = -ENOMEM; + struct libos_encrypted_volume* existing_volume = get_volume(volume->mount_point_path); + if (existing_volume) { + ret = -EEXIST; goto out; } - - *out_volume = volume; - ret = 0; + LISTP_ADD_TAIL(volume, &g_volumes, list); out: unlock(&g_volumes_lock); return ret; @@ -983,7 +959,9 @@ BEGIN_RS_FUNC(encrypted_files_key) { } END_RS_FUNC(encrypted_files_key) -/* Checkpoint the `g_volumes` list. */ +/* Checkpoint the `g_volumes` list. Note we only call this to checkpoint all volumes. The list + * itself is not checkpointed (and hence also no corresponding restore function). The list is + * reconstructed in the restore function of the volumes itself. */ BEGIN_CP_FUNC(all_encrypted_volumes) { __UNUSED(size); __UNUSED(obj); @@ -1005,23 +983,30 @@ BEGIN_CP_FUNC(encrypted_volume) { struct libos_encrypted_volume* volume = obj; struct libos_encrypted_volume* new_volume = NULL; - size_t off = ADD_CP_OFFSET(sizeof(struct libos_encrypted_volume)); - - new_volume = (struct libos_encrypted_volume*)(base + off); - - // TODO (MST): do something with remaining fields of struct - log_debug("CP(encrypted_volume): protection_mode=%d file_state_mape=%p", - volume->protection_mode, volume->files_state_map); // TODO (MST): DEBUG - // - protection_mode -> automatically copied - // - files_state_map - // - files_state_map_lock - - lock(&g_keys_lock); - DO_CP_MEMBER(encrypted_files_key, volume, new_volume, key); - unlock(&g_keys_lock); - - ADD_CP_FUNC_ENTRY(off); + size_t off = GET_FROM_CP_MAP(obj); + if (!off) { /* We haven't already checkpointed this volume */ + off = ADD_CP_OFFSET(sizeof(struct libos_encrypted_volume)); + ADD_TO_CP_MAP(obj, off); + new_volume = (struct libos_encrypted_volume*)(base + off); + + log_debug("CP(encrypted_volume): mount_point_path=%s protection_mode=%d file_state_mape=%p", + volume->mount_point_path, volume->protection_mode, + volume->files_state_map); // TODO (MST): DEBUG + DO_CP_MEMBER(str, volume, new_volume, mount_point_path); + new_volume->protection_mode = volume->protection_mode; + lock(&volume->files_state_map_lock); + // - files_state_map -> TODO (MST): Serialize me + unlock(&volume->files_state_map_lock); + // files_state_map_lock has no check point, it will be recreated in restore + lock(&g_keys_lock); + DO_CP_MEMBER(encrypted_files_key, volume, new_volume, key); + unlock(&g_keys_lock); + INIT_LIST_HEAD(new_volume, list); + ADD_CP_FUNC_ENTRY(off); + } else { + new_volume = (struct libos_encrypted_volume*)(base + off); + } if (objp) *objp = (void*)new_volume; } @@ -1029,20 +1014,24 @@ END_CP_FUNC(encrypted_volume) // TODO (MST): revisit below, probably not correct?! BEGIN_RS_FUNC(encrypted_volume) { - struct libos_encrypted_volume* volume = (void*)(base + GET_CP_FUNC_ENTRY()); __UNUSED(offset); + struct libos_encrypted_volume* migrated_volume = (void*)(base + GET_CP_FUNC_ENTRY()); + + CP_REBASE(migrated_volume->mount_point_path); - // TODO (MST): do something with remaining fields of struct - log_debug("RS(encrypted_volume): protection_mode=%d file_state_mape=%p", - volume->protection_mode, volume->files_state_map); // TODO (MST): DEBUG - // - protection_mode -> automatically copied - // - files_state_map - // - files_state_map_lock - if (!create_lock(&volume->files_state_map_lock)) { + /* protection_mode needs no restore action */ + // files_state_map: TODO (MST): deserialize me + if (!create_lock(&migrated_volume->files_state_map_lock)) { return -ENOMEM; } + CP_REBASE(migrated_volume->key); + log_debug("RS(encrypted_volume): mount_point_path=%s protection_mode=%d file_state_mape=%p", + migrated_volume->mount_point_path, migrated_volume->protection_mode, + migrated_volume->files_state_map); // TODO (MST): DEBUG - CP_REBASE(volume->key); + int ret = register_encrypted_volume(migrated_volume); + if (ret < 0) + return ret; } END_RS_FUNC(encrypted_volume) diff --git a/python/graminelibos/manifest_check.py b/python/graminelibos/manifest_check.py index 1f0b9ea6a6..0f3814fcb4 100644 --- a/python/graminelibos/manifest_check.py +++ b/python/graminelibos/manifest_check.py @@ -30,6 +30,7 @@ Required('type'): 'encrypted', Required('uri'): _uri, 'key_name': str, + 'protection_mode': str, }, { Required('type'): 'tmpfs',