linux-sgx: Allow to open files with arbitrary paths in the sandbox using IPFS (#1685)

A limitation of the current implementation of SGX IPFS in WAMR is that
it prevents to open files which are not in the current directory.
This restriction is lifted and can now open files in paths, similarly to the
WASI openat call, which takes into account the sandbox of the file system.
This commit is contained in:
Jämes Ménétrey 2022-11-07 12:56:16 +01:00 committed by GitHub
parent 7fd37190e8
commit 328fd59f43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 12 deletions

View File

@ -88,6 +88,8 @@ ocall_linkat(int *p_ret, int olddirfd, const char *oldpath, int newdirfd,
int int
ocall_unlinkat(int *p_ret, int dirfd, const char *pathname, int flags); ocall_unlinkat(int *p_ret, int dirfd, const char *pathname, int flags);
int int
ocall_readlink(ssize_t *p_ret, const char *pathname, char *buf, size_t bufsiz);
int
ocall_readlinkat(ssize_t *p_ret, int dirfd, const char *pathname, char *buf, ocall_readlinkat(ssize_t *p_ret, int dirfd, const char *pathname, char *buf,
size_t bufsiz); size_t bufsiz);
int int
@ -190,18 +192,29 @@ openat(int dirfd, const char *pathname, int flags, ...)
errno = get_errno(); errno = get_errno();
#if WASM_ENABLE_SGX_IPFS != 0 #if WASM_ENABLE_SGX_IPFS != 0
struct stat sb;
int ret = fstatat(dirfd, pathname, &sb, 0);
if (ret < 0) {
if (ocall_close(&ret, fd) != SGX_SUCCESS) {
TRACE_OCALL_FAIL();
}
return -1;
}
// Ony files are managed by SGX IPFS
if (S_ISREG(sb.st_mode)) {
// When WAMR uses Intel SGX IPFS to enabled, it opens a second // When WAMR uses Intel SGX IPFS to enabled, it opens a second
// file descriptor to interact with the secure file. // file descriptor to interact with the secure file.
// The first file descriptor opened earlier is used to interact // The first file descriptor opened earlier is used to interact
// with the metadata of the file (e.g., time, flags, etc.). // with the metadata of the file (e.g., time, flags, etc.).
int ret; void *file_ptr = ipfs_fopen(fd, flags);
void *file_ptr = ipfs_fopen(fd, pathname, flags);
if (file_ptr == NULL) { if (file_ptr == NULL) {
if (ocall_close(&ret, fd) != SGX_SUCCESS) { if (ocall_close(&ret, fd) != SGX_SUCCESS) {
TRACE_OCALL_FAIL(); TRACE_OCALL_FAIL();
} }
return -1; return -1;
} }
}
#endif #endif
return fd; return fd;
@ -699,6 +712,24 @@ unlinkat(int dirfd, const char *pathname, int flags)
return ret; return ret;
} }
ssize_t
readlink(const char *pathname, char *buf, size_t bufsiz)
{
ssize_t ret;
if (buf == NULL)
return -1;
if (ocall_readlink(&ret, pathname, buf, bufsiz) != SGX_SUCCESS) {
TRACE_OCALL_FAIL();
return -1;
}
if (ret == -1)
errno = get_errno();
return ret;
}
ssize_t ssize_t
readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
{ {

View File

@ -219,6 +219,8 @@ linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
int int
unlinkat(int dirfd, const char *pathname, int flags); unlinkat(int dirfd, const char *pathname, int flags);
ssize_t ssize_t
readlink(const char *pathname, char *buf, size_t bufsiz);
ssize_t
readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
int int
symlinkat(const char *target, int newdirfd, const char *linkpath); symlinkat(const char *target, int newdirfd, const char *linkpath);

View File

@ -248,7 +248,7 @@ ipfs_close(int fd)
} }
void * void *
ipfs_fopen(int fd, const char *filename, int flags) ipfs_fopen(int fd, int flags)
{ {
// Mapping back the mode // Mapping back the mode
const char *mode; const char *mode;
@ -291,8 +291,29 @@ ipfs_fopen(int fd, const char *filename, int flags)
return NULL; return NULL;
} }
// Opening the file // Determine the symbolic link of the file descriptor, because IPFS does not
void *sgx_file = sgx_fopen_auto_key(filename, mode); // support opening a relative path to a file descriptor (i.e., openat).
// Using the symbolic link in /proc/self allows to retrieve the same path as
// opened by the initial openat and respects the chroot of WAMR.
size_t ret;
char symbolic_path[32];
ret =
snprintf(symbolic_path, sizeof(symbolic_path), "/proc/self/fd/%d", fd);
if (ret >= sizeof(symbolic_path)) {
errno = ENAMETOOLONG;
return NULL;
}
// Resolve the symbolic link to real absolute path, because IPFS can only
// open a file with a same file name it was initially created. Otherwise,
// IPFS throws SGX_ERROR_FILE_NAME_MISMATCH.
char real_path[PATH_MAX] = { 0 };
ret = readlink(symbolic_path, real_path, PATH_MAX - 1);
if (ret == -1)
return NULL;
// Opening the file using the real path
void *sgx_file = sgx_fopen_auto_key(real_path, mode);
if (sgx_file == NULL) { if (sgx_file == NULL) {
errno = convert_sgx_errno(sgx_ferror(sgx_file)); errno = convert_sgx_errno(sgx_ferror(sgx_file));

View File

@ -28,7 +28,7 @@ ipfs_write(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
int int
ipfs_close(int fd); ipfs_close(int fd);
void * void *
ipfs_fopen(int fd, const char *filename, int flags); ipfs_fopen(int fd, int flags);
int int
ipfs_fflush(int fd); ipfs_fflush(int fd);
off_t off_t

View File

@ -48,6 +48,9 @@ enclave {
int flags); int flags);
int ocall_unlinkat(int dirfd, [in, string]const char *pathname, int ocall_unlinkat(int dirfd, [in, string]const char *pathname,
int flags); int flags);
ssize_t ocall_readlink([in, string]const char *pathname,
[out, size=bufsiz]char *buf,
size_t bufsiz);
ssize_t ocall_readlinkat(int dirfd, ssize_t ocall_readlinkat(int dirfd,
[in, string]const char *pathname, [in, string]const char *pathname,
[out, size=bufsiz]char *buf, [out, size=bufsiz]char *buf,

View File

@ -186,6 +186,12 @@ ocall_unlinkat(int dirfd, const char *pathname, int flags)
return unlinkat(dirfd, pathname, flags); return unlinkat(dirfd, pathname, flags);
} }
ssize_t
ocall_readlink(const char *pathname, char *buf, size_t bufsiz)
{
return readlink(pathname, buf, bufsiz);
}
ssize_t ssize_t
ocall_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) ocall_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
{ {

View File

@ -12,7 +12,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#define PATH_TEST_FILE "test.txt" #define PATH_TEST_FOLDER "./test"
#define PATH_TEST_FILE (PATH_TEST_FOLDER "/test.txt")
#define FILE_TEXT "Hello, world!" #define FILE_TEXT "Hello, world!"
#define WORLD_OFFSET 7 #define WORLD_OFFSET 7
#define NAME_REPLACMENT "James" #define NAME_REPLACMENT "James"
@ -28,6 +29,10 @@ main(int argc, char **argv)
int ret; int ret;
long long stat_size; long long stat_size;
// Test: Create a folder to store the file, if it does not exist yet
ret = mkdir(PATH_TEST_FOLDER, 777);
assert(ret == 0 || (ret == -1 && errno == EEXIST));
// Test: File opening (fopen) // Test: File opening (fopen)
printf("Opening a file..\n"); printf("Opening a file..\n");
file = fopen(PATH_TEST_FILE, "w+"); file = fopen(PATH_TEST_FILE, "w+");