Skip to content

Commit

Permalink
fixup! [LibOS] Single-process-lifetime rollback protection for protec…
Browse files Browse the repository at this point in the history
…ted files (WIP)

Signed-off-by: g2flyer <[email protected]>
  • Loading branch information
g2flyer committed May 21, 2024
1 parent bf218a2 commit 11d4bb0
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 17 deletions.
35 changes: 35 additions & 0 deletions libos/include/libos_fs_encrypted.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,18 @@ typedef enum {
PF_ENCLAVE_LIFE_RB_PROTECTION_STRICT = 2,
} libos_encrypted_files_mode_t;

DEFINE_LIST(libos_encrypted_volume);
DEFINE_LISTP(libos_encrypted_volume);
struct libos_encrypted_volume {
char* mount_point_path;
libos_encrypted_files_mode_t protection_mode;

struct libos_encrypted_volume_state_map* files_state_map;
struct libos_lock files_state_map_lock;

struct libos_encrypted_files_key* key;

LIST_TYPE(libos_encrypted_volume) list;
};

/*
Expand Down Expand Up @@ -141,6 +146,36 @@ 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 Retrieve a volume.
*
* Returns a volume with a given mount_point_path, or NULL if it has not been created yet. Note that
* even if the key exists, it might not be set yet (see `struct libos_encrypted_files_key`).
*
* This does not pass ownership of the key: the key objects are still managed by this module.
*/
struct libos_encrypted_volume* get_encrypted_volume(const char* mount_point_path);

/*
* \brief List existing volumes.
*
* Calls `callback` on each currently existing volume.
*/
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.
*
Expand Down
31 changes: 14 additions & 17 deletions libos/src/fs/chroot/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,15 @@ static int chroot_encrypted_mount(struct libos_mount_params* params, void** moun
}
}

struct libos_encrypted_volume* volume = malloc(sizeof(struct libos_encrypted_volume));
if (!volume)
return -ENOMEM;
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->protection_mode = protection_mode;
volume->key = key;
if (!create_lock(&volume->files_state_map_lock)) {
Expand All @@ -102,27 +108,18 @@ static int chroot_encrypted_mount(struct libos_mount_params* params, void** moun
static ssize_t chroot_encrypted_checkpoint(void** checkpoint, void* mount_data) {
struct libos_encrypted_volume* volume = mount_data;

// TODO (MST): fix below, doesn't really makes sense: i guess i have to duplicate something
// about volume?
*checkpoint = strdup(volume->key->name);
*checkpoint = strdup(volume->mount_point_path);
if (!*checkpoint)
return -ENOMEM;
return strlen(volume->key->name) + 1;
return strlen(volume->mount_point_path) + 1;
}

static int chroot_encrypted_migrate(void* checkpoint, void** mount_data) {
const char* name = checkpoint;
const char* mount_point_path = checkpoint;

struct libos_encrypted_volume* volume = malloc(sizeof(struct libos_encrypted_volume));
struct libos_encrypted_volume* volume = get_encrypted_volume(mount_point_path);
if (!volume)
return -ENOMEM;

if (!create_lock(&volume->files_state_map_lock))
return -ENOMEM;
// TODO (MST): initialize map
int ret = get_or_create_encrypted_files_key(name, &(volume->key));
if (ret < 0)
return ret;
return -EEXIST;
*mount_data = volume;
return 0;
}
Expand Down
102 changes: 102 additions & 0 deletions libos/src/fs/libos_fs_encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ static LISTP_TYPE(libos_encrypted_files_key) g_keys = LISTP_INIT;
/* Protects the `g_keys` list, but also individual keys, since they can be updated */
static struct libos_lock g_keys_lock;

static LISTP_TYPE(libos_encrypted_volume) g_volumes = LISTP_INIT;

/* Protects the `g_volumes` list. */
static struct libos_lock g_volumes_lock;

static pf_status_t cb_read(pf_handle_t handle, void* buffer, uint64_t offset, size_t size) {
PAL_HANDLE pal_handle = (PAL_HANDLE)handle;

Expand Down Expand Up @@ -370,6 +375,8 @@ int init_encrypted_files(void) {
#endif
if (!create_lock(&g_keys_lock))
return -ENOMEM;
if (!create_lock(&g_volumes_lock))
return -ENOMEM;

pf_set_callbacks(&cb_read, &cb_write, &cb_fsync, &cb_truncate,
&cb_aes_cmac, &cb_aes_gcm_encrypt, &cb_aes_gcm_decrypt,
Expand Down Expand Up @@ -532,6 +539,86 @@ void update_encrypted_files_key(struct libos_encrypted_files_key* key, const pf_
unlock(&g_keys_lock);
}

static struct libos_encrypted_volume* get_volume(const char* mount_point_path) {
assert(locked(&g_volumes_lock));

struct libos_encrypted_volume* volume;
LISTP_FOR_EACH_ENTRY(volume, &g_volumes, list) {
if (!strcmp(volume->mount_point_path, mount_point_path)) {
return volume;
}
}

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;
}

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;

struct libos_encrypted_volume* volume = get_or_create_volume(mount_point_path, out_created);
if (!volume) {
ret = -ENOMEM;
goto out;
}

*out_volume = volume;
ret = 0;
out:
unlock(&g_volumes_lock);
return ret;
}

struct libos_encrypted_volume* get_encrypted_volume(const char* mount_point_path) {
lock(&g_volumes_lock);
struct libos_encrypted_volume* volume = get_volume(mount_point_path);
unlock(&g_volumes_lock);
return volume;
}

int list_encrypted_volumes(int (*callback)(struct libos_encrypted_volume* volume, void* arg),
void* arg) {
lock(&g_volumes_lock);

int ret;

struct libos_encrypted_volume* volume;
LISTP_FOR_EACH_ENTRY(volume, &g_volumes, list) {
ret = callback(volume, arg);
if (ret < 0)
goto out;
}
ret = 0;
out:
unlock(&g_volumes_lock);
return ret;
}

static int encrypted_file_alloc(const char* uri, struct libos_encrypted_volume* volume,
struct libos_encrypted_file** out_enc) {
assert(strstartswith(uri, URI_PREFIX_FILE));
Expand Down Expand Up @@ -896,6 +983,21 @@ BEGIN_RS_FUNC(encrypted_files_key) {
}
END_RS_FUNC(encrypted_files_key)

/* Checkpoint the `g_volumes` list. */
BEGIN_CP_FUNC(all_encrypted_volumes) {
__UNUSED(size);
__UNUSED(obj);
__UNUSED(objp);

lock(&g_volumes_lock);
struct libos_encrypted_volume* volume;
LISTP_FOR_EACH_ENTRY(volume, &g_volumes, list) {
DO_CP(encrypted_volume, volume, /*objp=*/NULL);
}
unlock(&g_volumes_lock);
}
END_CP_FUNC_NO_RS(all_encrypted_volumes)

// TODO (MST): revisit below, probably not correct?!
BEGIN_CP_FUNC(encrypted_volume) {
__UNUSED(size);
Expand Down
1 change: 1 addition & 0 deletions libos/src/sys/libos_clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ static BEGIN_MIGRATION_DEF(fork, struct libos_process* process_description,
struct libos_ipc_ids* process_ipc_ids) {
DEFINE_MIGRATE(process_ipc_ids, process_ipc_ids, sizeof(*process_ipc_ids));
DEFINE_MIGRATE(all_encrypted_files_keys, NULL, 0);
DEFINE_MIGRATE(all_encrypted_volumes, NULL, 0);
DEFINE_MIGRATE(dentry_root, NULL, 0);
DEFINE_MIGRATE(all_mounts, NULL, 0);
DEFINE_MIGRATE(all_vmas, NULL, 0);
Expand Down

0 comments on commit 11d4bb0

Please sign in to comment.