Skip to content

Commit

Permalink
[LibOS] Updates to encrypted files
Browse files Browse the repository at this point in the history
* make corruption status for encrypted files sticky
* update filemap state for any corruption also encountered
  during operations other than open, close, unlink and rename
  • Loading branch information
g2flyer committed Aug 15, 2024
1 parent cd03cef commit 6f71463
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 62 deletions.
17 changes: 17 additions & 0 deletions common/src/protected_files/protected_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,9 @@ static bool ipf_init_existing_file(pf_context_t* pf, const char* path) {
if (PF_FAILURE(status)) {
pf->last_error = status;
DEBUG_PF("failed to decrypt metadata: %d", status);
if (status == PF_STATUS_MAC_MISMATCH)
// MAC could also mismatch if wrong key was provided but we err on side of safety ...
pf->file_status = PF_STATUS_CORRUPTED;
return false;
}

Expand Down Expand Up @@ -818,6 +821,8 @@ static bool ipf_init_existing_file(pf_context_t* pf, const char* path) {
&pf->metadata_decrypted.root_mht_node_mac);
if (PF_FAILURE(status)) {
pf->last_error = status;
if (status == PF_STATUS_MAC_MISMATCH)
pf->file_status = PF_STATUS_CORRUPTED;
return false;
}
}
Expand Down Expand Up @@ -1162,6 +1167,9 @@ pf_status_t pf_get_size(pf_context_t* pf, uint64_t* size) {
if (!g_initialized)
return PF_STATUS_UNINITIALIZED;

if (pf->file_status == PF_STATUS_CORRUPTED)
return pf->file_status; // Make corruption "sticky"

*size = pf->metadata_decrypted.file_size;
return PF_STATUS_SUCCESS;
}
Expand All @@ -1173,6 +1181,9 @@ pf_status_t pf_set_size(pf_context_t* pf, uint64_t size) {
if (!(pf->mode & PF_FILE_MODE_WRITE))
return PF_STATUS_INVALID_MODE;

if (pf->file_status == PF_STATUS_CORRUPTED)
return pf->file_status; // Make corruption "sticky"

if (size == pf->metadata_decrypted.file_size)
return PF_STATUS_SUCCESS;

Expand Down Expand Up @@ -1221,6 +1232,9 @@ pf_status_t pf_rename(pf_context_t* pf, const char* new_path, pf_mac_t* new_root
if (!g_initialized)
return PF_STATUS_UNINITIALIZED;

if (pf->file_status == PF_STATUS_CORRUPTED)
return pf->file_status; // Make corruption "sticky"

if (!(pf->mode & PF_FILE_MODE_WRITE))
return PF_STATUS_INVALID_MODE;

Expand Down Expand Up @@ -1293,6 +1307,9 @@ pf_status_t pf_flush(pf_context_t* pf) {
if (!g_initialized)
return PF_STATUS_UNINITIALIZED;

if (pf->file_status == PF_STATUS_CORRUPTED)
return pf->file_status; // Make corruption "sticky"

if (!ipf_internal_flush(pf))
return pf->last_error;

Expand Down
18 changes: 12 additions & 6 deletions libos/include/libos_fs_encrypted.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,19 @@ typedef enum {
PF_FILE_STATE_DELETED = 2, // file was previously seen but then either unlinked or renamed
} libos_encrypted_file_state_t;

inline static const char* file_state_to_string(libos_encrypted_file_state_t state) {
return (state == PF_FILE_STATE_ERROR ? "error"
: (state == PF_FILE_STATE_ACTIVE ? "active" : "deleted"));
}

/*
* Map mapping file URIs to state providing information on files, in particular whether we have seen
* them before and what the last seen root-hash is. This is necessary to provide rollback
*/
struct libos_encrypted_volume_state_map {
char* norm_path; // assumptions: all paths canonicalized, symlinks are resolved & no hard links
libos_encrypted_file_state_t state;
pf_mac_t last_seen_root_mac;
pf_mac_t last_seen_root_mac; // valid only if state == PF_FILE_STATE_ACTIVE
UT_hash_handle hh;
};

Expand Down Expand Up @@ -224,16 +229,17 @@ void encrypted_file_put(struct libos_encrypted_file* enc, bool fs_reachable);
/*
* \brief Flush pending writes to an encrypted file.
*/
int encrypted_file_flush(struct libos_encrypted_file* enc);
int encrypted_file_flush(struct libos_encrypted_file* enc, bool fs_reachable);

int encrypted_file_read(struct libos_encrypted_file* enc, void* buf, size_t buf_size,
file_off_t offset, size_t* out_count);
file_off_t offset, size_t* out_count, bool fs_reachable);
int encrypted_file_write(struct libos_encrypted_file* enc, const void* buf, size_t buf_size,
file_off_t offset, size_t* out_count);
file_off_t offset, size_t* out_count, bool fs_reachable);
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);
int encrypted_file_get_size(struct libos_encrypted_file* enc, file_off_t* out_size,
bool fs_reachable);
int encrypted_file_set_size(struct libos_encrypted_file* enc, file_off_t size, bool fs_reachable);

int parse_pf_key(const char* key_str, pf_key_t* pf_key);
12 changes: 7 additions & 5 deletions libos/src/fs/chroot/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ static int chroot_encrypted_lookup(struct libos_dentry* dent) {
goto out;
}
} else {
ret = encrypted_file_get_size(enc, &size);
ret = encrypted_file_get_size(enc, &size, true);
encrypted_file_put(enc, true);

if (ret < 0) {
Expand Down Expand Up @@ -468,7 +468,7 @@ static int chroot_encrypted_flush(struct libos_handle* hdl) {

/* This will write changes from `enc` to host file */
lock(&hdl->inode->lock);
ret = encrypted_file_flush(enc);
ret = encrypted_file_flush(enc, hdl->inode == hdl->dentry->inode);
unlock(&hdl->inode->lock);
return ret;
}
Expand Down Expand Up @@ -502,7 +502,8 @@ static ssize_t chroot_encrypted_read(struct libos_handle* hdl, void* buf, size_t
size_t actual_count;

lock(&hdl->inode->lock);
int ret = encrypted_file_read(enc, buf, count, *pos, &actual_count);
int ret =
encrypted_file_read(enc, buf, count, *pos, &actual_count, hdl->inode == hdl->dentry->inode);
unlock(&hdl->inode->lock);

if (ret < 0)
Expand All @@ -527,7 +528,8 @@ static ssize_t chroot_encrypted_write(struct libos_handle* hdl, const void* buf,

lock(&hdl->inode->lock);

int ret = encrypted_file_write(enc, buf, count, *pos, &actual_count);
int ret = encrypted_file_write(enc, buf, count, *pos, &actual_count,
hdl->inode == hdl->dentry->inode);
if (ret < 0) {
unlock(&hdl->inode->lock);
return ret;
Expand Down Expand Up @@ -557,7 +559,7 @@ static int chroot_encrypted_truncate(struct libos_handle* hdl, file_off_t size)
assert(enc);

lock(&hdl->inode->lock);
ret = encrypted_file_set_size(enc, size);
ret = encrypted_file_set_size(enc, size, hdl->inode == hdl->dentry->inode);
if (ret < 0) {
unlock(&hdl->inode->lock);
return ret;
Expand Down
Loading

0 comments on commit 6f71463

Please sign in to comment.