Skip to content

Commit 11d4bb0

Browse files
committed
fixup! [LibOS] Single-process-lifetime rollback protection for protected files (WIP)
Signed-off-by: g2flyer <[email protected]>
1 parent bf218a2 commit 11d4bb0

File tree

4 files changed

+152
-17
lines changed

4 files changed

+152
-17
lines changed

libos/include/libos_fs_encrypted.h

+35
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,18 @@ typedef enum {
6060
PF_ENCLAVE_LIFE_RB_PROTECTION_STRICT = 2,
6161
} libos_encrypted_files_mode_t;
6262

63+
DEFINE_LIST(libos_encrypted_volume);
64+
DEFINE_LISTP(libos_encrypted_volume);
6365
struct libos_encrypted_volume {
66+
char* mount_point_path;
6467
libos_encrypted_files_mode_t protection_mode;
6568

6669
struct libos_encrypted_volume_state_map* files_state_map;
6770
struct libos_lock files_state_map_lock;
6871

6972
struct libos_encrypted_files_key* key;
73+
74+
LIST_TYPE(libos_encrypted_volume) list;
7075
};
7176

7277
/*
@@ -141,6 +146,36 @@ bool read_encrypted_files_key(struct libos_encrypted_files_key* key, pf_key_t* p
141146
*/
142147
void update_encrypted_files_key(struct libos_encrypted_files_key* key, const pf_key_t* pf_key);
143148

149+
/*
150+
* \brief Retrieve a volume.
151+
*
152+
* Returns a volume with a given mount_point_path, or NULL if it has not been created yet. Note that
153+
* even if the key exists, it might not be set yet (see `struct libos_encrypted_files_key`).
154+
*
155+
* This does not pass ownership of the key: the key objects are still managed by this module.
156+
*/
157+
struct libos_encrypted_volume* get_encrypted_volume(const char* mount_point_path);
158+
159+
/*
160+
* \brief List existing volumes.
161+
*
162+
* Calls `callback` on each currently existing volume.
163+
*/
164+
int list_encrypted_volumes(int (*callback)(struct libos_encrypted_volume* volume, void* arg),
165+
void* arg);
166+
167+
/*
168+
* \brief Create a volume.
169+
*
170+
* Sets `*out_volume` to a volume with given mount_point_path. If the volume has not been created
171+
* yet, creates a new one (with mount_point_path and list only fields initialized!).
172+
* out_created is set to whether volume is newly created or not.
173+
*
174+
* Similar to `get_encrypted_volumes`, this does not pass ownership of `*out_volume`.
175+
*/
176+
int get_or_create_encrypted_volume(const char* mount_point_path,
177+
struct libos_encrypted_volume** out_volume, bool* out_created);
178+
144179
/*
145180
* \brief Open an existing encrypted file.
146181
*

libos/src/fs/chroot/encrypted.c

+14-17
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,15 @@ static int chroot_encrypted_mount(struct libos_mount_params* params, void** moun
8484
}
8585
}
8686

87-
struct libos_encrypted_volume* volume = malloc(sizeof(struct libos_encrypted_volume));
88-
if (!volume)
89-
return -ENOMEM;
87+
struct libos_encrypted_volume* volume;
88+
bool created;
89+
ret = get_or_create_encrypted_volume(params->path, &volume, &created);
90+
if (ret < 0)
91+
return ret;
92+
if (!created) {
93+
log_error("Volume '%s' is already mounted", params->path);
94+
return -EEXIST;
95+
}
9096
volume->protection_mode = protection_mode;
9197
volume->key = key;
9298
if (!create_lock(&volume->files_state_map_lock)) {
@@ -102,27 +108,18 @@ static int chroot_encrypted_mount(struct libos_mount_params* params, void** moun
102108
static ssize_t chroot_encrypted_checkpoint(void** checkpoint, void* mount_data) {
103109
struct libos_encrypted_volume* volume = mount_data;
104110

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

113117
static int chroot_encrypted_migrate(void* checkpoint, void** mount_data) {
114-
const char* name = checkpoint;
118+
const char* mount_point_path = checkpoint;
115119

116-
struct libos_encrypted_volume* volume = malloc(sizeof(struct libos_encrypted_volume));
120+
struct libos_encrypted_volume* volume = get_encrypted_volume(mount_point_path);
117121
if (!volume)
118-
return -ENOMEM;
119-
120-
if (!create_lock(&volume->files_state_map_lock))
121-
return -ENOMEM;
122-
// TODO (MST): initialize map
123-
int ret = get_or_create_encrypted_files_key(name, &(volume->key));
124-
if (ret < 0)
125-
return ret;
122+
return -EEXIST;
126123
*mount_data = volume;
127124
return 0;
128125
}

libos/src/fs/libos_fs_encrypted.c

+102
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ static LISTP_TYPE(libos_encrypted_files_key) g_keys = LISTP_INIT;
2020
/* Protects the `g_keys` list, but also individual keys, since they can be updated */
2121
static struct libos_lock g_keys_lock;
2222

23+
static LISTP_TYPE(libos_encrypted_volume) g_volumes = LISTP_INIT;
24+
25+
/* Protects the `g_volumes` list. */
26+
static struct libos_lock g_volumes_lock;
27+
2328
static pf_status_t cb_read(pf_handle_t handle, void* buffer, uint64_t offset, size_t size) {
2429
PAL_HANDLE pal_handle = (PAL_HANDLE)handle;
2530

@@ -370,6 +375,8 @@ int init_encrypted_files(void) {
370375
#endif
371376
if (!create_lock(&g_keys_lock))
372377
return -ENOMEM;
378+
if (!create_lock(&g_volumes_lock))
379+
return -ENOMEM;
373380

374381
pf_set_callbacks(&cb_read, &cb_write, &cb_fsync, &cb_truncate,
375382
&cb_aes_cmac, &cb_aes_gcm_encrypt, &cb_aes_gcm_decrypt,
@@ -532,6 +539,86 @@ void update_encrypted_files_key(struct libos_encrypted_files_key* key, const pf_
532539
unlock(&g_keys_lock);
533540
}
534541

542+
static struct libos_encrypted_volume* get_volume(const char* mount_point_path) {
543+
assert(locked(&g_volumes_lock));
544+
545+
struct libos_encrypted_volume* volume;
546+
LISTP_FOR_EACH_ENTRY(volume, &g_volumes, list) {
547+
if (!strcmp(volume->mount_point_path, mount_point_path)) {
548+
return volume;
549+
}
550+
}
551+
552+
return NULL;
553+
}
554+
555+
static struct libos_encrypted_volume* get_or_create_volume(const char* mount_point_path,
556+
bool* out_created) {
557+
assert(locked(&g_volumes_lock));
558+
559+
struct libos_encrypted_volume* volume = get_volume(mount_point_path);
560+
if (volume) {
561+
*out_created = false;
562+
return volume;
563+
}
564+
565+
volume = calloc(1, sizeof(*volume));
566+
if (!volume)
567+
return NULL;
568+
volume->mount_point_path = strdup(mount_point_path);
569+
if (!volume->mount_point_path) {
570+
free(volume);
571+
return NULL;
572+
}
573+
LISTP_ADD_TAIL(volume, &g_volumes, list);
574+
*out_created = true;
575+
return volume;
576+
}
577+
578+
int get_or_create_encrypted_volume(const char* mount_point_path,
579+
struct libos_encrypted_volume** out_volume, bool* out_created) {
580+
lock(&g_volumes_lock);
581+
582+
int ret;
583+
584+
struct libos_encrypted_volume* volume = get_or_create_volume(mount_point_path, out_created);
585+
if (!volume) {
586+
ret = -ENOMEM;
587+
goto out;
588+
}
589+
590+
*out_volume = volume;
591+
ret = 0;
592+
out:
593+
unlock(&g_volumes_lock);
594+
return ret;
595+
}
596+
597+
struct libos_encrypted_volume* get_encrypted_volume(const char* mount_point_path) {
598+
lock(&g_volumes_lock);
599+
struct libos_encrypted_volume* volume = get_volume(mount_point_path);
600+
unlock(&g_volumes_lock);
601+
return volume;
602+
}
603+
604+
int list_encrypted_volumes(int (*callback)(struct libos_encrypted_volume* volume, void* arg),
605+
void* arg) {
606+
lock(&g_volumes_lock);
607+
608+
int ret;
609+
610+
struct libos_encrypted_volume* volume;
611+
LISTP_FOR_EACH_ENTRY(volume, &g_volumes, list) {
612+
ret = callback(volume, arg);
613+
if (ret < 0)
614+
goto out;
615+
}
616+
ret = 0;
617+
out:
618+
unlock(&g_volumes_lock);
619+
return ret;
620+
}
621+
535622
static int encrypted_file_alloc(const char* uri, struct libos_encrypted_volume* volume,
536623
struct libos_encrypted_file** out_enc) {
537624
assert(strstartswith(uri, URI_PREFIX_FILE));
@@ -896,6 +983,21 @@ BEGIN_RS_FUNC(encrypted_files_key) {
896983
}
897984
END_RS_FUNC(encrypted_files_key)
898985

986+
/* Checkpoint the `g_volumes` list. */
987+
BEGIN_CP_FUNC(all_encrypted_volumes) {
988+
__UNUSED(size);
989+
__UNUSED(obj);
990+
__UNUSED(objp);
991+
992+
lock(&g_volumes_lock);
993+
struct libos_encrypted_volume* volume;
994+
LISTP_FOR_EACH_ENTRY(volume, &g_volumes, list) {
995+
DO_CP(encrypted_volume, volume, /*objp=*/NULL);
996+
}
997+
unlock(&g_volumes_lock);
998+
}
999+
END_CP_FUNC_NO_RS(all_encrypted_volumes)
1000+
8991001
// TODO (MST): revisit below, probably not correct?!
9001002
BEGIN_CP_FUNC(encrypted_volume) {
9011003
__UNUSED(size);

libos/src/sys/libos_clone.c

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ static BEGIN_MIGRATION_DEF(fork, struct libos_process* process_description,
9595
struct libos_ipc_ids* process_ipc_ids) {
9696
DEFINE_MIGRATE(process_ipc_ids, process_ipc_ids, sizeof(*process_ipc_ids));
9797
DEFINE_MIGRATE(all_encrypted_files_keys, NULL, 0);
98+
DEFINE_MIGRATE(all_encrypted_volumes, NULL, 0);
9899
DEFINE_MIGRATE(dentry_root, NULL, 0);
99100
DEFINE_MIGRATE(all_mounts, NULL, 0);
100101
DEFINE_MIGRATE(all_vmas, NULL, 0);

0 commit comments

Comments
 (0)