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

[Pal/Linux-SGX] Allow READ+WRITE mmap of protected files selectively #526

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions LibOS/shim/test/fs/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ tests = {
'seek_tell': {},
'stat': {},
'truncate': {},
'open_mmap': {},
}

install_dir = join_paths(pkglibdir, 'tests', 'libos', 'fs')
Expand Down
61 changes: 61 additions & 0 deletions LibOS/shim/test/fs/open_mmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "common.h"

static void mmap_test(int fd, off_t offset, size_t length,
int prot, const char *prot_str,
int flags, const char *flags_str,
bool expect_success) {
void *address = mmap(NULL, length, prot, flags, fd, offset);
if (address == MAP_FAILED) {
if (expect_success) {
fatal_error("mmap %s, %s failed\n", prot_str, flags_str);
} else {
printf("mmap %s, %s failed as expected\n", prot_str, flags_str);
}
} else {
munmap(address, length);
if (expect_success) {
printf("mmap %s, %s succeeded as expected\n", prot_str, flags_str);
} else {
fatal_error("mmap %s, %s unexpectedly succeeded\n", prot_str, flags_str);
}
}
}

#define MMAP_TEST(fd, offset, length, prot, flags, expect_success) \
mmap_test(fd, offset, length, prot, #prot, flags, #flags, expect_success)

static void open_mmap(const char* path) {
int fd = open(path, O_RDWR);

if (fd < 0) {
fatal_error("open %s failed!\n", path);
}

seek_fd(path, fd, 0, SEEK_END);
size_t length = (size_t)tell_fd(path, fd);

MMAP_TEST(fd, 0, length, PROT_READ, MAP_SHARED,
/*expect_success=*/true);
MMAP_TEST(fd, 0, length, PROT_WRITE, MAP_SHARED,
/*expect_success=*/true);
MMAP_TEST(fd, 0, length, PROT_READ, MAP_PRIVATE,
/*expect_success=*/true);
MMAP_TEST(fd, 0, length, PROT_WRITE, MAP_PRIVATE,
/*expect_success=*/true);
MMAP_TEST(fd, 0, length, PROT_READ | PROT_WRITE, MAP_PRIVATE,
/*expect_success=*/true);

close(fd);
}

int main(int argc, char* argv[]) {
if (argc < 2) {
fatal_error("Usage: %s <path>\n", argv[0]);
}

setup();

open_mmap(argv[1]);

return 0;
}
13 changes: 13 additions & 0 deletions LibOS/shim/test/fs/test_pf.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,16 @@ def test_500_invalid(self):
else:
print('[!] Fail: successfully decrypted file: ' + name)
self.fail()

@unittest.skipIf(os.environ.get('ASAN') == '1', 'mapping protected files is broken')
def test_501_open_mmap(self):
# the test binary expects a path to read-only (existing) file or a path to file that
# will get created
input_path = self.ENCRYPTED_FILES[-1] # existing file
stdout, stderr = self.run_binary(['open_mmap', input_path])
self.assertNotIn('ERROR: ', stderr)
self.assertIn('mmap PROT_READ, MAP_SHARED succeeded as expected', stdout)
self.assertIn('mmap PROT_WRITE, MAP_SHARED succeeded as expected', stdout)
self.assertIn('mmap PROT_READ, MAP_PRIVATE succeeded as expected', stdout)
self.assertIn('mmap PROT_WRITE, MAP_PRIVATE succeeded as expected', stdout)
self.assertIn('mmap PROT_READ | PROT_WRITE, MAP_PRIVATE succeeded as expected', stdout)
1 change: 1 addition & 0 deletions LibOS/shim/test/fs/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ manifests = [
"seek_tell",
"stat",
"truncate",
"open_mmap",
]
7 changes: 7 additions & 0 deletions Pal/src/host/Linux-SGX/db_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,13 @@ static int pf_file_map(struct protected_file* pf, PAL_HANDLE handle, void** addr
return -PAL_ERROR_INVAL;

assert(WITHIN_MASK(prot, PAL_PROT_MASK));

/* If MAP_PRIVATE flag is set, we don't need to write the changes back to the file.
* Proceed as if it's read only. */
if ((prot & PAL_PROT_WRITECOPY) && (prot & PAL_PROT_WRITE)) {
prot = prot & ~PAL_PROT_WRITE;
}

if ((prot & PAL_PROT_READ) && (prot & PAL_PROT_WRITE)) {
log_warning("pf_file_map(PF fd %d): trying to map with R+W access", fd);
return -PAL_ERROR_NOTSUPPORT;
Expand Down