mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 22:01:29 +00:00
[Pal/Linux-SGX] Eliminate redundant file mmap/munmap in untrusted area
Linux-SGX PAL calls `load_trusted_file()` during file open. This function mmaps trusted files to calculate checksums. Previously, file open also mmapped the same trusted file for its own purposes. This commit removes this redundancy and leaves only one mmap, the one in `load_trusted_file()`.
This commit is contained in:
committed by
Dmitrii Kuvaiskii
parent
c8632aac37
commit
4a6a9889c2
@@ -70,7 +70,8 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
|
||||
|
||||
sgx_stub_t* stubs;
|
||||
uint64_t total;
|
||||
ret = load_trusted_file(hdl, &stubs, &total, create);
|
||||
void* umem;
|
||||
ret = load_trusted_file(hdl, &stubs, &total, create, &umem);
|
||||
if (ret < 0) {
|
||||
SGX_DBG(DBG_E,
|
||||
"Accessing file:%s is denied. (%s) "
|
||||
@@ -79,19 +80,13 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
|
||||
free(hdl);
|
||||
return ret;
|
||||
}
|
||||
if (stubs && total) {
|
||||
assert(umem);
|
||||
}
|
||||
|
||||
hdl->file.stubs = (PAL_PTR)stubs;
|
||||
hdl->file.total = total;
|
||||
|
||||
if (hdl->file.stubs && hdl->file.total) {
|
||||
/* case of trusted file: mmap the whole file in untrusted memory for future reads/writes */
|
||||
ret = ocall_mmap_untrusted(hdl->file.fd, 0, hdl->file.total, PROT_READ, &hdl->file.umem);
|
||||
if (IS_ERR(ret)) {
|
||||
/* note that we don't free stubs because they are re-used in same trusted file */
|
||||
free(hdl);
|
||||
return unix_to_pal_error(ERRNO(ret));
|
||||
}
|
||||
}
|
||||
hdl->file.umem = umem;
|
||||
|
||||
*handle = hdl;
|
||||
return 0;
|
||||
|
||||
@@ -259,8 +259,12 @@ static bool path_is_equal_or_subpath(const struct trusted_file* tf,
|
||||
* Returns 0 if succeeded, or an error code otherwise.
|
||||
*/
|
||||
int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
|
||||
uint64_t * sizeptr, int create)
|
||||
uint64_t * sizeptr, int create, void** umem)
|
||||
{
|
||||
*stubptr = NULL;
|
||||
*sizeptr = 0;
|
||||
*umem = NULL;
|
||||
|
||||
struct trusted_file * tf = NULL, * tmp;
|
||||
char uri[URI_MAX];
|
||||
char normpath[URI_MAX];
|
||||
@@ -278,8 +282,6 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
|
||||
The created file is added to allowed_file list for later access */
|
||||
if (create && allow_file_creation) {
|
||||
register_trusted_file(uri, NULL);
|
||||
*stubptr = NULL;
|
||||
*sizeptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -344,6 +346,19 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
|
||||
if (tf->index < 0)
|
||||
return tf->index;
|
||||
|
||||
sgx_stub_t* stubs = NULL;
|
||||
/* mmap the whole trusted file in untrusted memory for future reads/writes; it is
|
||||
* caller's responsibility to unmap those areas after use */
|
||||
*sizeptr = tf->size;
|
||||
if (*sizeptr) {
|
||||
ret = ocall_mmap_untrusted(fd, 0, tf->size, PROT_READ, umem);
|
||||
if (IS_ERR(ret)) {
|
||||
*umem = NULL;
|
||||
ret = unix_to_pal_error(ERRNO(ret));
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
#if CACHE_FILE_STUBS == 1
|
||||
if (tf->stubs) {
|
||||
*stubptr = tf->stubs;
|
||||
@@ -355,14 +370,15 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
|
||||
int nstubs = tf->size / TRUSTED_STUB_SIZE +
|
||||
(tf->size % TRUSTED_STUB_SIZE ? 1 : 0);
|
||||
|
||||
sgx_stub_t * stubs = malloc(sizeof(sgx_stub_t) * nstubs);
|
||||
if (!stubs)
|
||||
return -PAL_ERROR_NOMEM;
|
||||
stubs = malloc(sizeof(sgx_stub_t) * nstubs);
|
||||
if (!stubs) {
|
||||
ret = -PAL_ERROR_NOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
sgx_stub_t * s = stubs; /* stubs is an array of 128bit values */
|
||||
uint64_t offset = 0;
|
||||
LIB_SHA256_CONTEXT sha;
|
||||
void * umem;
|
||||
|
||||
ret = lib_SHA256Init(&sha);
|
||||
if (ret < 0)
|
||||
@@ -377,12 +393,6 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
|
||||
ret = ocall_mmap_untrusted(fd, offset, mapping_size, PROT_READ, &umem);
|
||||
if (IS_ERR(ret)) {
|
||||
ret = unix_to_pal_error(ERRNO(ret));
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* To prevent TOCTOU attack when generating the file checksum, we
|
||||
* need to copy the file content into the enclave before hashing.
|
||||
@@ -400,23 +410,21 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
|
||||
|
||||
/* Any file content needs to be copied into the enclave before
|
||||
* checking and re-hashing */
|
||||
memcpy(small_chunk, umem + chunk_offset, chunk_size);
|
||||
memcpy(small_chunk, *umem + offset + chunk_offset, chunk_size);
|
||||
|
||||
/* Update the file checksum */
|
||||
ret = lib_SHA256Update(&sha, small_chunk, chunk_size);
|
||||
if (ret < 0)
|
||||
goto unmap;
|
||||
goto failed;
|
||||
|
||||
/* Update the checksum for the file chunk */
|
||||
ret = lib_AESCMACUpdate(&aes_cmac, small_chunk, chunk_size);
|
||||
if (ret < 0)
|
||||
goto unmap;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Store the checksum for one file chunk for checking */
|
||||
ret = lib_AESCMACFinish(&aes_cmac, (uint8_t *) s, sizeof *s);
|
||||
unmap:
|
||||
ocall_munmap_untrusted(umem, mapping_size);
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
}
|
||||
@@ -439,34 +447,23 @@ unmap:
|
||||
if (tf->stubs || tf->index == -PAL_ERROR_DENIED)
|
||||
free(tf->stubs);
|
||||
*stubptr = tf->stubs = stubs;
|
||||
*sizeptr = tf->size;
|
||||
ret = tf->index;
|
||||
spinlock_unlock(&trusted_file_lock);
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
if (*umem) {
|
||||
assert(*sizeptr > 0);
|
||||
ocall_munmap_untrusted(*umem, *sizeptr);
|
||||
}
|
||||
free(stubs);
|
||||
|
||||
spinlock_lock(&trusted_file_lock);
|
||||
if (tf->stubs) {
|
||||
*stubptr = tf->stubs;
|
||||
*sizeptr = tf->size;
|
||||
ret = tf->index;
|
||||
} else {
|
||||
if (!tf->stubs) {
|
||||
tf->index = -PAL_ERROR_DENIED;
|
||||
}
|
||||
spinlock_unlock(&trusted_file_lock);
|
||||
|
||||
#if PRINT_ENCLAVE_STAT
|
||||
if (!ret) {
|
||||
sgx_stub_t * loaded_stub;
|
||||
uint64_t loaded_size;
|
||||
PAL_HANDLE handle = NULL;
|
||||
if (!_DkStreamOpen(&handle, normpath, PAL_ACCESS_RDONLY, 0, 0, 0))
|
||||
load_trusted_file (handle, &loaded_stub, &loaded_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,8 +138,8 @@ int init_trusted_files (void);
|
||||
* return: 0 succeed
|
||||
*/
|
||||
|
||||
int load_trusted_file
|
||||
(PAL_HANDLE file, sgx_stub_t ** stubptr, uint64_t * sizeptr, int create);
|
||||
int load_trusted_file(PAL_HANDLE file, sgx_stub_t** stubptr, uint64_t* sizeptr, int create,
|
||||
void** umem);
|
||||
|
||||
enum {
|
||||
FILE_CHECK_POLICY_STRICT = 0,
|
||||
|
||||
Reference in New Issue
Block a user