Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LibOS,Pal,common,tools] Improved protected files performance #1681

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 138 additions & 120 deletions common/src/protected_files/protected_files.c

Large diffs are not rendered by default.

46 changes: 11 additions & 35 deletions common/src/protected_files/protected_files.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ typedef enum _pf_status_t {
PF_STATUS_CRYPTO_ERROR = -15,
PF_STATUS_CORRUPTED = -16,
PF_STATUS_WRITE_TO_DISK_FAILED = -17,
PF_STATUS_INVALID_ADDRESS = -18,
PF_STATUS_INVALID_FILE_SIZE = -19,
} pf_status_t;

#define PF_SUCCESS(status) ((status) == PF_STATUS_SUCCESS)
Expand All @@ -66,40 +68,16 @@ typedef enum _pf_file_mode_t {
/*! Opaque file handle type, interpreted by callbacks as necessary */
typedef void* pf_handle_t;

/*!
* \brief File read callback.
*
* \param handle File handle.
* \param[out] buffer Buffer to read to.
* \param offset Offset to read from.
* \param size Number of bytes to read.
*
* \returns PF status.
*/
typedef pf_status_t (*pf_read_f)(pf_handle_t handle, void* buffer, uint64_t offset, size_t size);

/*!
* \brief File write callback.
*
* \param handle File handle.
* \param buffer Buffer to write from.
* \param offset Offset to write to.
* \param size Number of bytes to write.
*
* \returns PF status.
*/
typedef pf_status_t (*pf_write_f)(pf_handle_t handle, const void* buffer, uint64_t offset,
size_t size);

/*!
* \brief File truncate callback.
*
* \param handle File handle.
* \param size Target file size.
* \param handle File handle.
* \param size Target file size.
* \param[out] addr A pointer to the mapped area.
*
* \returns PF status.
*/
typedef pf_status_t (*pf_truncate_f)(pf_handle_t handle, uint64_t size);
typedef pf_status_t (*pf_truncate_f)(pf_handle_t handle, uint64_t size, void** addr);

/*!
* \brief Debug print callback.
Expand Down Expand Up @@ -170,8 +148,6 @@ typedef pf_status_t (*pf_random_f)(uint8_t* buffer, size_t size);
/*!
* \brief Initialize I/O callbacks.
*
* \param read_f File read callback.
* \param write_f File write callback.
* \param truncate_f File truncate callback.
* \param aes_cmac_f AES-CMAC callback.
* \param aes_gcm_encrypt_f AES-GCM encrypt callback.
Expand All @@ -181,10 +157,9 @@ typedef pf_status_t (*pf_random_f)(uint8_t* buffer, size_t size);
*
* Must be called before any actual APIs.
*/
void pf_set_callbacks(pf_read_f read_f, pf_write_f write_f, pf_truncate_f truncate_f,
pf_aes_cmac_f aes_cmac_f, pf_aes_gcm_encrypt_f aes_gcm_encrypt_f,
pf_aes_gcm_decrypt_f aes_gcm_decrypt_f, pf_random_f random_f,
pf_debug_f debug_f);
void pf_set_callbacks(pf_truncate_f truncate_f, pf_aes_cmac_f aes_cmac_f,
pf_aes_gcm_encrypt_f aes_gcm_encrypt_f, pf_aes_gcm_decrypt_f aes_gcm_decrypt_f,
pf_random_f random_f, pf_debug_f debug_f);

/*! Context representing an open protected file */
typedef struct pf_context pf_context_t;
Expand All @@ -207,14 +182,15 @@ const char* pf_strerror(int err);
* \param path Path to the file. If NULL and \p create is false, don't check path
* for validity.
* \param underlying_size Underlying file size.
* \param addr Mapped file address.
* \param mode Access mode.
* \param create Overwrite file contents if true.
* \param key Wrap key.
* \param[out] context PF context for later calls.
*
* \returns PF status.
*/
pf_status_t pf_open(pf_handle_t handle, const char* path, uint64_t underlying_size,
pf_status_t pf_open(pf_handle_t handle, const char* path, uint64_t underlying_size, void* addr,
pf_file_mode_t mode, bool create, const pf_key_t* key, pf_context_t** context);

/*!
Expand Down
11 changes: 1 addition & 10 deletions common/src/protected_files/protected_files_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,6 @@ typedef struct _data_node {

static_assert(sizeof(data_node_t) == PF_NODE_SIZE, "sizeof(data_node_t)");

typedef struct _encrypted_node {
uint8_t cipher[PF_NODE_SIZE];
} encrypted_node_t;

static_assert(sizeof(encrypted_node_t) == PF_NODE_SIZE, "sizeof(encrypted_node_t)");

#define MAX_PAGES_IN_CACHE 48

typedef enum {
Expand All @@ -119,10 +113,7 @@ typedef struct _file_node {
struct _file_node* parent;
bool need_writing;
bool new_node;
struct {
uint64_t physical_node_number;
encrypted_node_t encrypted; // the actual data from the disk
};
uint64_t physical_node_number;
union { // decrypted data
mht_node_t mht;
data_node_t data;
Expand Down
1 change: 1 addition & 0 deletions common/src/protected_files/protected_files_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct pf_context {
metadata_encrypted_t encrypted_part_plain; // encrypted part of metadata node, decrypted
file_node_t root_mht; // the root of the mht is always needed (for files bigger than 3KB)
pf_handle_t file;
void* addr;
pf_file_mode_t mode;
uint64_t real_file_size;
bool need_writing;
Expand Down
2 changes: 1 addition & 1 deletion libos/src/fs/chroot/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ static int chroot_encrypted_fchmod(struct libos_handle* hdl, mode_t perm) {

struct libos_encrypted_file* enc = hdl->inode->data;
mode_t host_perm = HOST_PERM(perm);
PAL_STREAM_ATTR attr = {.share_flags = host_perm};
PAL_STREAM_ATTR attr = {.share_flags = host_perm, .addr = (void*)-1};
int ret = PalStreamAttributesSetByHandle(enc->pal_handle, &attr);
if (ret < 0)
return pal_to_unix_errno(ret);
Expand Down
103 changes: 38 additions & 65 deletions libos/src/fs/libos_fs_encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,72 +20,24 @@ 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 pf_status_t cb_read(pf_handle_t handle, void* buffer, uint64_t offset, size_t size) {
static pf_status_t cb_truncate(pf_handle_t handle, uint64_t size, void** ret_addr) {
int ret;
PAL_HANDLE pal_handle = (PAL_HANDLE)handle;

size_t buffer_offset = 0;
size_t remaining = size;

while (remaining > 0) {
size_t count = remaining;
int ret = PalStreamRead(pal_handle, offset + buffer_offset, &count, buffer + buffer_offset);
if (ret == -PAL_ERROR_INTERRUPTED)
continue;

if (ret < 0) {
log_warning("PalStreamRead failed: %s", pal_strerror(ret));
return PF_STATUS_CALLBACK_FAILED;
}

if (count == 0) {
log_warning("EOF");
return PF_STATUS_CALLBACK_FAILED;
}

assert(count <= remaining);
remaining -= count;
buffer_offset += count;
ret = PalStreamSetLength(pal_handle, size);
if (ret < 0) {
log_warning("PalStreamSetLength failed: %s", pal_strerror(ret));
return PF_STATUS_CALLBACK_FAILED;
}
return PF_STATUS_SUCCESS;
}

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

size_t buffer_offset = 0;
size_t remaining = size;

while (remaining > 0) {
size_t count = remaining;
int ret = PalStreamWrite(pal_handle, offset + buffer_offset, &count,
(void*)(buffer + buffer_offset));
if (ret == -PAL_ERROR_INTERRUPTED)
continue;

if (ret_addr) {
PAL_STREAM_ATTR pal_attr;
ret = PalStreamAttributesQueryByHandle(pal_handle, &pal_attr);
if (ret < 0) {
log_warning("PalStreamWrite failed: %s", pal_strerror(ret));
return PF_STATUS_CALLBACK_FAILED;
}

if (count == 0) {
log_warning("EOF");
log_warning("PalStreamAttributesQueryByHandle failed: %s", pal_strerror(ret));
return PF_STATUS_CALLBACK_FAILED;
}

assert(count <= remaining);
remaining -= count;
buffer_offset += count;
}
return PF_STATUS_SUCCESS;
}

static pf_status_t cb_truncate(pf_handle_t handle, uint64_t size) {
PAL_HANDLE pal_handle = (PAL_HANDLE)handle;

int ret = PalStreamSetLength(pal_handle, size);
if (ret < 0) {
log_warning("PalStreamSetLength failed: %s", pal_strerror(ret));
return PF_STATUS_CALLBACK_FAILED;
*ret_addr = pal_attr.addr;
}

return PF_STATUS_SUCCESS;
Expand Down Expand Up @@ -157,7 +109,7 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
if (!pal_handle) {
enum pal_create_mode create_mode = create ? PAL_CREATE_ALWAYS : PAL_CREATE_NEVER;
ret = PalStreamOpen(enc->uri, PAL_ACCESS_RDWR, share_flags, create_mode,
PAL_OPTION_PASSTHROUGH, &pal_handle);
PAL_OPTION_PASSTHROUGH | PAL_OPTION_ENCRYPTED_FILE, &pal_handle);
if (ret < 0) {
log_warning("PalStreamOpen failed: %s", pal_strerror(ret));
return pal_to_unix_errno(ret);
Expand All @@ -172,6 +124,7 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
goto out;
}
size_t size = pal_attr.pending_size;
void* addr = pal_attr.addr;

assert(strstartswith(enc->uri, URI_PREFIX_FILE));
const char* path = enc->uri + static_strlen(URI_PREFIX_FILE);
Expand All @@ -196,7 +149,7 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
ret = -EACCES;
goto out;
}
pf_status_t pfs = pf_open(pal_handle, normpath, size, PF_FILE_MODE_READ | PF_FILE_MODE_WRITE,
pf_status_t pfs = pf_open(pal_handle, normpath, size, addr, PF_FILE_MODE_READ | PF_FILE_MODE_WRITE,
create, &enc->key->pf_key, &pf);
unlock(&g_keys_lock);
if (PF_FAILURE(pfs)) {
Expand Down Expand Up @@ -272,9 +225,8 @@ int init_encrypted_files(void) {
if (!create_lock(&g_keys_lock))
return -ENOMEM;

pf_set_callbacks(&cb_read, &cb_write, &cb_truncate,
&cb_aes_cmac, &cb_aes_gcm_encrypt, &cb_aes_gcm_decrypt,
&cb_random, cb_debug_ptr);
pf_set_callbacks(&cb_truncate, &cb_aes_cmac, &cb_aes_gcm_encrypt,
&cb_aes_gcm_decrypt, &cb_random, cb_debug_ptr);

int ret;

Expand Down Expand Up @@ -782,7 +734,28 @@ BEGIN_RS_FUNC(encrypted_file) {
assert(!enc->pf);
if (enc->use_count > 0) {
assert(enc->pal_handle);
int ret = encrypted_file_internal_open(enc, enc->pal_handle, /*create=*/false,

/* Recreate file map: set handle->file.addr to NULL and call PalStreamSetLength */
int ret;
PAL_STREAM_ATTR pal_attr;
ret = PalStreamAttributesQueryByHandle(enc->pal_handle, &pal_attr);
if (ret < 0) {
log_warning("PalStreamAttributesQueryByHandle failed: %s", pal_strerror(ret));
return pal_to_unix_errno(ret);
}
pal_attr.addr = NULL;
ret = PalStreamAttributesSetByHandle(enc->pal_handle, &pal_attr);
if (ret < 0) {
log_warning("PalStreamAttributesQueryByHandle failed: %s", pal_strerror(ret));
return pal_to_unix_errno(ret);
}
ret = PalStreamSetLength(enc->pal_handle, pal_attr.pending_size);
if (ret < 0) {
log_warning("PalStreamSetLength failed: %s", pal_strerror(ret));
return pal_to_unix_errno(ret);
}

ret = encrypted_file_internal_open(enc, enc->pal_handle, /*create=*/false,
/*share_flags=*/0);
if (ret < 0)
return ret;
Expand Down
2 changes: 1 addition & 1 deletion pal/include/host/linux-common/pal_flags_conv.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ static inline int PAL_CREATE_TO_LINUX_OPEN(enum pal_create_mode create) {
}

static inline int PAL_OPTION_TO_LINUX_OPEN(pal_stream_options_t options) {
assert(WITHIN_MASK(options, PAL_OPTION_NONBLOCK | PAL_OPTION_PASSTHROUGH));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
return options & PAL_OPTION_NONBLOCK ? O_NONBLOCK : 0;
}
4 changes: 3 additions & 1 deletion pal/include/pal/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ typedef uint32_t pal_stream_options_t; /* bitfield */
#define PAL_OPTION_EFD_SEMAPHORE 0x1 /*!< specific to `eventfd` syscall */
#define PAL_OPTION_NONBLOCK 0x2
#define PAL_OPTION_PASSTHROUGH 0x4 /*!< Disregard `sgx.{allowed,trusted}_files` */
#define PAL_OPTION_MASK 0x7
#define PAL_OPTION_ENCRYPTED_FILE 0x8 /*!< Open encrypted file */
#define PAL_OPTION_MASK 0xf

/*!
* \brief Open/create a stream resource specified by `uri`.
Expand Down Expand Up @@ -467,6 +468,7 @@ typedef struct _PAL_STREAM_ATTR {
bool nonblocking;
pal_share_flags_t share_flags;
size_t pending_size;
void* addr;
union {
struct {
uint64_t linger;
Expand Down
Loading