Skip to content

Commit 10d4597

Browse files
committed
[LibOS] Single-process-lifetime rollback protection for protected files (WIP)
* adds libos_encrypted_volume as mount-data for protected fileystem which includes map <name, <last-root-hash, ...>> to keep track of root hashes across open/close cycles of a particular value, ensuring consistency across the whole enclave life-time Signed-off-by: g2flyer <[email protected]>
1 parent e1c97d5 commit 10d4597

File tree

8 files changed

+404
-106
lines changed

8 files changed

+404
-106
lines changed

common/src/protected_files/protected_files.c

+21-5
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ static void ipf_delete_cache(pf_context_t* pf) {
11251125
}
11261126
}
11271127

1128-
static bool ipf_close(pf_context_t* pf) {
1128+
static bool ipf_close(pf_context_t* pf, pf_mac_t* closing_root_gmac) {
11291129
bool retval = true;
11301130

11311131
if (pf->file_status != PF_STATUS_SUCCESS) {
@@ -1138,6 +1138,10 @@ static bool ipf_close(pf_context_t* pf) {
11381138
}
11391139
}
11401140

1141+
if (closing_root_gmac != NULL) {
1142+
memcpy(*closing_root_gmac, pf->file_metadata.plain_part.metadata_gmac, sizeof(pf_mac_t));
1143+
}
1144+
11411145
// omeg: fs close is done by Gramine handler
11421146
pf->file_status = PF_STATUS_UNINITIALIZED;
11431147

@@ -1176,20 +1180,25 @@ void pf_set_callbacks(pf_read_f read_f, pf_write_f write_f, pf_fsync_f fsync_f,
11761180
}
11771181

11781182
pf_status_t pf_open(pf_handle_t handle, const char* path, uint64_t underlying_size,
1179-
pf_file_mode_t mode, bool create, const pf_key_t* key, pf_context_t** context) {
1183+
pf_file_mode_t mode, bool create, const pf_key_t* key,
1184+
pf_mac_t* opening_root_gmac, pf_context_t** context) {
11801185
if (!g_initialized)
11811186
return PF_STATUS_UNINITIALIZED;
11821187

11831188
pf_status_t status;
11841189
*context = ipf_open(path, mode, create, handle, underlying_size, key, &status);
1190+
if (opening_root_gmac != NULL) {
1191+
memcpy(*opening_root_gmac, (*context)->file_metadata.plain_part.metadata_gmac,
1192+
sizeof(pf_mac_t));
1193+
}
11851194
return status;
11861195
}
11871196

1188-
pf_status_t pf_close(pf_context_t* pf) {
1197+
pf_status_t pf_close(pf_context_t* pf, pf_mac_t* closing_root_gmac) {
11891198
if (!g_initialized)
11901199
return PF_STATUS_UNINITIALIZED;
11911200

1192-
if (ipf_close(pf)) {
1201+
if (ipf_close(pf, closing_root_gmac)) {
11931202
free(pf);
11941203
return PF_STATUS_SUCCESS;
11951204
}
@@ -1259,7 +1268,7 @@ pf_status_t pf_set_size(pf_context_t* pf, uint64_t size) {
12591268
return PF_STATUS_SUCCESS;
12601269
}
12611270

1262-
pf_status_t pf_rename(pf_context_t* pf, const char* new_path) {
1271+
pf_status_t pf_rename(pf_context_t* pf, const char* new_path, pf_mac_t* new_root_gmac) {
12631272
if (!g_initialized)
12641273
return PF_STATUS_UNINITIALIZED;
12651274

@@ -1275,6 +1284,9 @@ pf_status_t pf_rename(pf_context_t* pf, const char* new_path) {
12751284
pf->need_writing = true;
12761285
if (!ipf_internal_flush(pf))
12771286
return pf->last_error;
1287+
if (new_root_gmac != NULL) {
1288+
memcpy(*new_root_gmac, pf->file_metadata.plain_part.metadata_gmac, sizeof(pf_mac_t));
1289+
}
12781290

12791291
return PF_STATUS_SUCCESS;
12801292
}
@@ -1348,3 +1360,7 @@ pf_status_t pf_flush(pf_context_t* pf) {
13481360

13491361
return PF_STATUS_SUCCESS;
13501362
}
1363+
1364+
void pf_set_corrupted(pf_context_t* pf) {
1365+
pf->file_status = PF_STATUS_CORRUPTED;
1366+
}

common/src/protected_files/protected_files.h

+30-14
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ typedef uint8_t pf_mac_t[PF_MAC_SIZE];
2626
typedef uint8_t pf_key_t[PF_KEY_SIZE];
2727
typedef uint8_t pf_keyid_t[32]; /* key derivation material */
2828

29+
// convenience macros to print out some mac fingerprint: printf( "some text " MAC_PRINTF_PATTERN "
30+
// yet other text", MAC_PRINTF_ARGS(mac) );
31+
#define MAC_PRINTF_PATTERN "0x%02x%02x%02x%02x..."
32+
#define MAC_PRINTF_ARGS(mac) (mac)[0], (mac)[1], (mac)[2], (mac)[3]
33+
2934
typedef enum _pf_status_t {
3035
PF_STATUS_SUCCESS = 0,
3136
PF_STATUS_UNKNOWN_ERROR = -1,
@@ -209,28 +214,31 @@ const char* pf_strerror(int err);
209214
/*!
210215
* \brief Open a protected file.
211216
*
212-
* \param handle Open underlying file handle.
213-
* \param path Path to the file. If NULL and \p create is false, don't check path
214-
* for validity.
215-
* \param underlying_size Underlying file size.
216-
* \param mode Access mode.
217-
* \param create Overwrite file contents if true.
218-
* \param key Wrap key.
219-
* \param[out] context PF context for later calls.
217+
* \param handle Open underlying file handle.
218+
* \param path Path to the file. If NULL and \p create is false, don't check path
219+
* for validity.
220+
* \param underlying_size Underlying file size.
221+
* \param mode Access mode.
222+
* \param create Overwrite file contents if true.
223+
* \param key Wrap key.
224+
* \param opening_root_gmac If non-NULL, !create & successfull open, returns root-hash of file
225+
* \param[out] context PF context for later calls.
220226
*
221227
* \returns PF status.
222228
*/
223229
pf_status_t pf_open(pf_handle_t handle, const char* path, uint64_t underlying_size,
224-
pf_file_mode_t mode, bool create, const pf_key_t* key, pf_context_t** context);
230+
pf_file_mode_t mode, bool create, const pf_key_t* key,
231+
pf_mac_t* opening_root_gmac, pf_context_t** context);
225232

226233
/*!
227234
* \brief Close a protected file and commit all changes to disk.
228235
*
229-
* \param pf PF context.
236+
* \param pf PF context.
237+
* \param closing_root_gmac If non-NULL, returns root-hash of file at closing time
230238
*
231239
* \returns PF status.
232240
*/
233-
pf_status_t pf_close(pf_context_t* pf);
241+
pf_status_t pf_close(pf_context_t* pf, pf_mac_t* closing_root_gmac);
234242

235243
/*!
236244
* \brief Read from a protected file.
@@ -283,13 +291,14 @@ pf_status_t pf_set_size(pf_context_t* pf, uint64_t size);
283291
/*!
284292
* \brief Rename a PF.
285293
*
286-
* \param pf PF context.
287-
* \param new_path New file path.
294+
* \param pf PF context.
295+
* \param new_path New file path.
296+
* \param new_root_gmac if non-NULL, returns new root-hash of file
288297
*
289298
* Updates the path inside protected file header, and flushes all changes. The caller is responsible
290299
* for renaming the underlying file.
291300
*/
292-
pf_status_t pf_rename(pf_context_t* pf, const char* new_path);
301+
pf_status_t pf_rename(pf_context_t* pf, const char* new_path, pf_mac_t* new_root_gmac);
293302

294303
/*!
295304
* \brief Flush any pending data of a protected file to disk.
@@ -299,3 +308,10 @@ pf_status_t pf_rename(pf_context_t* pf, const char* new_path);
299308
* \returns PF status.
300309
*/
301310
pf_status_t pf_flush(pf_context_t* pf);
311+
312+
/*!
313+
* \brief Set protected file state as corrupted
314+
*
315+
* \param pf PF context.
316+
*/
317+
void pf_set_corrupted(pf_context_t* pf);

libos/include/libos_fs.h

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ struct libos_mount_params {
3535

3636
/* Key name (used by `chroot_encrypted` filesystem), or NULL if not applicable */
3737
const char* key_name;
38+
39+
/* Enforcement type (used by `chroot_encrypted` filesystem), or NULL if not applicable */
40+
const char* protection_mode;
3841
};
3942

4043
struct libos_fs_ops {

libos/include/libos_fs_encrypted.h

+43-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <stddef.h>
1616

17+
#include "libos_checkpoint.h" // for include of uthash.h _and_ consistent uthash_fatal macros
1718
#include "libos_types.h"
1819
#include "list.h"
1920
#include "pal.h"
@@ -34,6 +35,40 @@ struct libos_encrypted_files_key {
3435
LIST_TYPE(libos_encrypted_files_key) list;
3536
};
3637

38+
typedef enum {
39+
PF_FILE_IN_USE_NEW = 0, // file is currently in-use but did not exist at open time
40+
PF_FILE_IN_USE_EXISTING = 1, // file is currently in-use and existed at open time
41+
PF_FILE_CLOSED = 2, // file was provisously seend with known (good committed) state
42+
PF_FILE_DELETED = 3, // the old path of renames is also considered deleted
43+
PF_FILE_ERROR = 4, // file is in non-determined state due to some errors
44+
} libos_encrypted_file_state_t;
45+
46+
/*
47+
* Map mapping file URIs to state providing information on files, in particular whether we have seen
48+
* them before and what the last seen root-hash is. This is necessary to provide rollback
49+
*/
50+
struct libos_encrypted_volume_state_map {
51+
char* norm_path; // assumptions: all paths canonicalized, symlinks are resolved & no hard links
52+
libos_encrypted_file_state_t state;
53+
pf_mac_t last_seen_root_gmac;
54+
UT_hash_handle hh;
55+
};
56+
57+
typedef enum {
58+
PF_ENCLAVE_LIFE_RB_PROTECTION_NONE = 0,
59+
PF_ENCLAVE_LIFE_RB_PROTECTION_NON_STRICT = 1,
60+
PF_ENCLAVE_LIFE_RB_PROTECTION_STRICT = 2,
61+
} libos_encrypted_files_mode_t;
62+
63+
struct libos_encrypted_volume {
64+
libos_encrypted_files_mode_t protection_mode;
65+
66+
struct libos_encrypted_volume_state_map* files_state_map;
67+
struct libos_lock files_state_map_lock;
68+
69+
struct libos_encrypted_files_key* key;
70+
};
71+
3772
/*
3873
* Represents a specific encrypted file. The file is open as long as `use_count` is greater than 0.
3974
* Note that the file can be open and closed multiple times before it's destroyed.
@@ -44,7 +79,8 @@ struct libos_encrypted_files_key {
4479
struct libos_encrypted_file {
4580
size_t use_count;
4681
char* uri;
47-
struct libos_encrypted_files_key* key;
82+
char* norm_path; // normalized path of of uri
83+
struct libos_encrypted_volume* volume;
4884

4985
/* `pf` and `pal_handle` are non-null as long as `use_count` is greater than 0 */
5086
pf_context_t* pf;
@@ -110,29 +146,29 @@ void update_encrypted_files_key(struct libos_encrypted_files_key* key, const pf_
110146
* \brief Open an existing encrypted file.
111147
*
112148
* \param uri PAL URI to open, has to begin with "file:".
113-
* \param key Key, has to be already set.
149+
* \param volume Volume assocated with file, has to be already set.
114150
* \param[out] out_enc On success, set to a newly created `libos_encrypted_file` object.
115151
*
116152
* `uri` has to correspond to an existing file that can be decrypted with `key`.
117153
*
118154
* The newly created `libos_encrypted_file` object will have `use_count` set to 1.
119155
*/
120-
int encrypted_file_open(const char* uri, struct libos_encrypted_files_key* key,
156+
int encrypted_file_open(const char* uri, struct libos_encrypted_volume* volume,
121157
struct libos_encrypted_file** out_enc);
122158

123159
/*
124160
* \brief Create a new encrypted file.
125161
*
126162
* \param uri PAL URI to open, has to begin with "file:".
127163
* \param perm Permissions for the new file.
128-
* \param key Key, has to be already set.
164+
* \param volume Volume assocated with file, has to be already set.
129165
* \param[out] out_enc On success, set to a newly created `libos_encrypted_file` object.
130166
*
131167
* `uri` must not correspond to an existing file.
132168
*
133169
* The newly created `libos_encrypted_file` object will have `use_count` set to 1.
134170
*/
135-
int encrypted_file_create(const char* uri, mode_t perm, struct libos_encrypted_files_key* key,
171+
int encrypted_file_create(const char* uri, mode_t perm, struct libos_encrypted_volume* volume,
136172
struct libos_encrypted_file** out_enc);
137173

138174
/*
@@ -154,7 +190,7 @@ int encrypted_file_get(struct libos_encrypted_file* enc);
154190
*
155191
* This decreases `use_count`, and closes the file if it reaches 0.
156192
*/
157-
void encrypted_file_put(struct libos_encrypted_file* enc);
193+
void encrypted_file_put(struct libos_encrypted_file* enc, bool fs_reachable);
158194

159195
/*
160196
* \brief Flush pending writes to an encrypted file.
@@ -166,6 +202,7 @@ int encrypted_file_read(struct libos_encrypted_file* enc, void* buf, size_t buf_
166202
int encrypted_file_write(struct libos_encrypted_file* enc, const void* buf, size_t buf_size,
167203
file_off_t offset, size_t* out_count);
168204
int encrypted_file_rename(struct libos_encrypted_file* enc, const char* new_uri);
205+
int encrypted_file_unlink(struct libos_encrypted_file* enc);
169206

170207
int encrypted_file_get_size(struct libos_encrypted_file* enc, file_off_t* out_size);
171208
int encrypted_file_set_size(struct libos_encrypted_file* enc, file_off_t size);

0 commit comments

Comments
 (0)