Convert flags between PAL API and host syscalls

Currently various flags in file and memory syscalls work mostly by an
accident, because values of some of them align with corresponding Linux
syscall flags. Some APIs weren't that lucky though - e.g.
DkStreamOpen(..., /*options=*/PAL_OPTION_CLOEXEC) deletes file contents
(sic!) intead of opening it with O_CLOEXEC. This is because
PAL_OPTION_CLOEXEC == O_TRUNC.

This commit fixes all this mess and also adds asserts to check validity
of flags passed to Dk* handlers.
This commit is contained in:
Michał Kowalczyk
2020-04-22 22:14:14 +02:00
parent 9aa4370084
commit e39ee4767f
34 changed files with 477 additions and 283 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ struct shim_mem_entry {
void* addr;
size_t size;
void** paddr;
int prot;
int prot; /*< Combination of PAL_PROT_* flags */
void* data;
};
+59
View File
@@ -0,0 +1,59 @@
/* Copyright (C) 2020 Invisible Things Lab
Michał Kowalczyk <mkow@invisiblethingslab.com>
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/*
* This file defines conversions between Linux syscall flags and PAL API flags.
*
* For Linux-based PALs there is pal_flag_conv.h in Linux-common, mirroring those conversions.
*/
#ifndef SHIM_FLAGS_CONV_H
#define SHIM_FLAGS_CONV_H
#include <asm/fcntl.h>
#include <asm/mman.h>
#include <linux/fcntl.h>
#include "assert.h"
#include "pal.h"
static inline int LINUX_PROT_TO_PAL(int prot, int map_flags) {
assert(WITHIN_MASK(prot, PROT_READ | PROT_WRITE | PROT_EXEC));
return (prot & PROT_READ ? PAL_PROT_READ : 0) |
(prot & PROT_WRITE ? PAL_PROT_WRITE : 0) |
(prot & PROT_EXEC ? PAL_PROT_EXEC : 0) |
(map_flags & MAP_PRIVATE ? PAL_PROT_WRITECOPY : 0);
}
static inline int LINUX_OPEN_FLAGS_TO_PAL_ACCESS(int access) {
return (access & O_RDONLY ? PAL_ACCESS_RDONLY : 0) |
(access & O_WRONLY ? PAL_ACCESS_WRONLY : 0) |
(access & O_RDWR ? PAL_ACCESS_RDWR : 0) |
(access & O_APPEND ? PAL_ACCESS_APPEND : 0);
}
static inline int LINUX_OPEN_FLAGS_TO_PAL_CREATE(int flags) {
if (WITHIN_MASK(O_CREAT | O_EXCL, flags))
return PAL_CREATE_ALWAYS;
if (flags & O_CREAT)
return PAL_CREATE_TRY;
return 0;
}
static inline int LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(int flags) {
return (flags & O_CLOEXEC ? PAL_OPTION_CLOEXEC : 0) |
(flags & O_NONBLOCK ? PAL_OPTION_NONBLOCK : 0);
}
#endif /* SHIM_FLAGS_CONV_H */
+1 -1
View File
@@ -350,7 +350,7 @@ struct shim_handle {
struct shim_dir_handle dir_info;
int flags;
int flags; /* Linux' O_* flags */
int acc_mode;
IDTYPE owner;
struct shim_lock lock;
-16
View File
@@ -80,22 +80,6 @@ static inline void free_vma_val_array(struct shim_vma_val* vmas, size_t count) {
#define NEED_MIGRATE_MEMORY(vma) \
(((vma)->flags & VMA_TAINTED || !(vma)->file) && !((vma)->flags & VMA_UNMAPPED))
static inline PAL_FLG PAL_PROT(int prot, int flags) {
PAL_FLG pal_prot = 0;
if (prot & PROT_READ)
pal_prot |= PAL_PROT_READ;
if (prot & PROT_WRITE)
pal_prot |= PAL_PROT_WRITE;
if (prot & PROT_EXEC)
pal_prot |= PAL_PROT_EXEC;
if (flags & MAP_PRIVATE)
pal_prot |= PAL_PROT_WRITECOPY;
return pal_prot;
}
int init_vma(void);
/* Bookkeeping mmap() system call */
+14 -16
View File
@@ -20,20 +20,20 @@
* This file contains code to maintain bookkeeping of VMAs in library OS.
*/
#include <shim_internal.h>
#include <shim_thread.h>
#include <shim_handle.h>
#include <shim_vma.h>
#include <shim_checkpoint.h>
#include <shim_fs.h>
#include <pal.h>
#include <list.h>
#include <asm/mman.h>
#include <errno.h>
#include <stdbool.h>
#include "list.h"
#include "pal.h"
#include "shim_checkpoint.h"
#include "shim_flags_conv.h"
#include "shim_fs.h"
#include "shim_handle.h"
#include "shim_internal.h"
#include "shim_thread.h"
#include "shim_vma.h"
/*
* Internal bookkeeping for VMAs (virtual memory areas). This data
* structure can only be accessed in this source file, with vma_list_lock
@@ -1080,7 +1080,7 @@ BEGIN_CP_FUNC(vma)
struct shim_vma_val * vma = (struct shim_vma_val *) obj;
struct shim_vma_val * new_vma = NULL;
PAL_FLG pal_prot = PAL_PROT(vma->prot, 0);
PAL_FLG pal_prot = LINUX_PROT_TO_PAL(vma->prot, /*map_flags=*/0);
ptr_t off = GET_FROM_CP_MAP(obj);
@@ -1187,11 +1187,9 @@ BEGIN_RS_FUNC(vma)
}
if (need_mapped < vma->addr + vma->length) {
int pal_alloc_type = 0;
int pal_prot = vma->prot;
if (DkVirtualMemoryAlloc(need_mapped,
vma->addr + vma->length - need_mapped,
pal_alloc_type, pal_prot)) {
if (DkVirtualMemoryAlloc(need_mapped, vma->addr + vma->length - need_mapped,
/*alloc_type=*/0,
LINUX_PROT_TO_PAL(vma->prot, /*map_flags=*/0))) {
need_mapped += vma->length;
}
}
+21 -16
View File
@@ -26,18 +26,19 @@
#include <asm/mman.h>
#include <asm/prctl.h>
#include <errno.h>
#include <shim_checkpoint.h>
#include <shim_fs.h>
#include <shim_handle.h>
#include <shim_internal.h>
#include <shim_table.h>
#include <shim_thread.h>
#include <shim_utils.h>
#include <shim_vdso.h>
#include <shim_vma.h>
#include "elf.h"
#include "ldsodefs.h"
#include "shim_checkpoint.h"
#include "shim_flags_conv.h"
#include "shim_fs.h"
#include "shim_handle.h"
#include "shim_internal.h"
#include "shim_table.h"
#include "shim_thread.h"
#include "shim_utils.h"
#include "shim_vdso.h"
#include "shim_vma.h"
#ifndef DT_THISPROCNUM
#define DT_THISPROCNUM 0
@@ -199,7 +200,8 @@ static int protect_page(struct link_map* l, void* addr, size_t size) {
void* start = ALLOC_ALIGN_DOWN_PTR(addr);
void* end = ALLOC_ALIGN_UP_PTR(addr + size);
if (!DkVirtualMemoryProtect(start, end - start, PAL_PROT_READ | PAL_PROT_WRITE | prot))
if (!DkVirtualMemoryProtect(start, end - start,
PAL_PROT_READ | PAL_PROT_WRITE | LINUX_PROT_TO_PAL(prot, /*map_flags=*/0)))
return -PAL_ERRNO;
if (!c)
@@ -237,7 +239,8 @@ static int reprotect_map(struct link_map* l) {
t = next;
l->textrels = t;
if (c && !DkVirtualMemoryProtect((void*)start, end - start, prot)) {
if (c && !DkVirtualMemoryProtect((void*)start, end - start,
LINUX_PROT_TO_PAL(prot, /*map_flags=*/0))) {
ret = -PAL_ERRNO;
break;
}
@@ -613,13 +616,14 @@ do_remap:
if ((c->prot & PROT_WRITE) == 0) {
/* Dag nab it. */
if (!DkVirtualMemoryProtect((caddr_t)ALLOC_ALIGN_DOWN(zero), g_pal_alloc_align,
c->prot | PAL_PROT_WRITE)) {
LINUX_PROT_TO_PAL(c->prot, /*map_flags=*/0)
| PAL_PROT_WRITE)) {
errstring = "cannot change memory protections";
goto call_lose;
}
memset((void*)zero, '\0', zeropage - zero);
if (!DkVirtualMemoryProtect((caddr_t)ALLOC_ALIGN_DOWN(zero), g_pal_alloc_align,
c->prot)) {
LINUX_PROT_TO_PAL(c->prot, /*map_flags=*/0))) {
errstring = "cannot change memory protections";
goto call_lose;
}
@@ -632,7 +636,8 @@ do_remap:
if (type != OBJECT_MAPPED && type != OBJECT_INTERNAL && type != OBJECT_USER &&
type != OBJECT_VDSO) {
PAL_PTR mapat =
DkVirtualMemoryAlloc((void*)zeropage, zeroend - zeropage, 0, c->prot);
DkVirtualMemoryAlloc((void*)zeropage, zeroend - zeropage, /*alloc_type=*/0,
LINUX_PROT_TO_PAL(c->prot, /*map_flags=*/0));
if (!mapat) {
errstring = "cannot map zero-fill pages";
goto call_lose;
@@ -1431,8 +1436,8 @@ static int vdso_map_init(void) {
return -ENOMEM;
assert(addr == ALLOC_ALIGN_UP_PTR(addr));
void* ret_addr = (void*)DkVirtualMemoryAlloc(addr, ALLOC_ALIGN_UP(vdso_so_size), 0,
PAL_PROT_READ | PAL_PROT_WRITE);
void* ret_addr = (void*)DkVirtualMemoryAlloc(addr, ALLOC_ALIGN_UP(vdso_so_size),
/*alloc_type=*/0, PAL_PROT_READ | PAL_PROT_WRITE);
if (!ret_addr)
return -PAL_ERRNO;
assert(addr == ret_addr);
+28 -36
View File
@@ -20,25 +20,24 @@
* This file contains codes for implementation of 'chroot' filesystem.
*/
#include <shim_internal.h>
#include <shim_thread.h>
#include <shim_handle.h>
#include <shim_vma.h>
#include <shim_fs.h>
#include <shim_utils.h>
#include <pal.h>
#include <pal_error.h>
#include <errno.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
// FIXME: Sorting these includes causes a bunch of "error: S_IFREG undeclared" errors.
#include "shim_flags_conv.h"
#include "shim_internal.h"
#include "shim_thread.h"
#include "shim_handle.h"
#include "shim_vma.h"
#include "shim_fs.h"
#include "shim_utils.h"
#include "pal.h"
#include "pal_error.h"
#include <asm/fcntl.h>
#include <asm/mman.h>
#include <asm/unistd.h>
#include <asm/prctl.h>
#include <asm/unistd.h>
#include <errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
#define URI_MAX_SIZE STR_SIZE
@@ -382,11 +381,8 @@ static int chroot_lookup (struct shim_dentry * dent)
return query_dentry(dent, NULL, NULL, NULL);
}
static int __chroot_open (struct shim_dentry * dent,
const char * uri, int flags, mode_t mode,
struct shim_handle * hdl,
struct shim_file_data * data)
{
static int __chroot_open(struct shim_dentry* dent, const char* uri, int flags, mode_t mode,
struct shim_handle* hdl, struct shim_file_data* data) {
int ret = 0;
if (!uri) {
@@ -394,13 +390,12 @@ static int __chroot_open (struct shim_dentry * dent,
}
int version = atomic_read(&data->version);
int oldmode = flags & O_ACCMODE;
int oldmode = LINUX_OPEN_FLAGS_TO_PAL_ACCESS(flags);
int accmode = oldmode;
int creat = flags & PAL_CREATE_MASK;
int option = flags & PAL_OPTION_MASK;
int create = LINUX_OPEN_FLAGS_TO_PAL_CREATE(flags);
int options = LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(flags);
if ((data->type == FILE_REGULAR || data->type == FILE_UNKNOWN)
&& accmode == O_WRONLY)
if ((data->type == FILE_REGULAR || data->type == FILE_UNKNOWN) && accmode == O_WRONLY)
accmode = O_RDWR;
PAL_HANDLE palhdl;
@@ -408,12 +403,11 @@ static int __chroot_open (struct shim_dentry * dent,
if (hdl && hdl->pal_handle) {
palhdl = hdl->pal_handle;
} else {
palhdl = DkStreamOpen(uri, accmode, mode, creat, option);
palhdl = DkStreamOpen(uri, accmode, mode, create, options);
if (!palhdl) {
if (PAL_NATIVE_ERRNO == PAL_ERROR_DENIED &&
accmode != oldmode)
palhdl = DkStreamOpen(uri, oldmode, mode, creat, option);
if (PAL_NATIVE_ERRNO == PAL_ERROR_DENIED && accmode != oldmode)
palhdl = DkStreamOpen(uri, oldmode, mode, create, options);
if (!palhdl)
return -PAL_ERRNO;
@@ -421,7 +415,7 @@ static int __chroot_open (struct shim_dentry * dent,
/* If DENTRY_LISTED is set on the parent dentry, list_directory_dentry() will not update
* dent's ino, so ino will be actively updated here. */
if (creat)
if (create)
chroot_update_ino(dent);
}
@@ -445,11 +439,9 @@ static int __chroot_open (struct shim_dentry * dent,
return ret;
}
static int chroot_open (struct shim_handle * hdl, struct shim_dentry * dent,
int flags)
{
static int chroot_open(struct shim_handle* hdl, struct shim_dentry* dent, int flags) {
int ret = 0;
struct shim_file_data * data;
struct shim_file_data* data;
if ((ret = try_create_data(dent, NULL, 0, &data)) < 0)
return ret;
@@ -529,7 +521,7 @@ static int chroot_mkdir (struct shim_dentry * dir, struct shim_dentry * dent,
return ret;
}
ret = __chroot_open(dent, NULL, O_CREAT|O_EXCL, mode, NULL, data);
ret = __chroot_open(dent, NULL, O_CREAT | O_EXCL, mode, NULL, data);
/* Increment the parent's link count */
struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir);
@@ -726,7 +718,7 @@ static int chroot_mmap (struct shim_handle * hdl, void ** addr, size_t size,
if (NEED_RECREATE(hdl) && (ret = chroot_recreate(hdl)) < 0)
return ret;
int pal_prot = PAL_PROT(prot, flags);
int pal_prot = LINUX_PROT_TO_PAL(prot, flags);
#if MAP_FILE == 0
if (flags & MAP_ANONYMOUS)
+2 -5
View File
@@ -605,8 +605,7 @@ static void * cp_alloc (struct shim_cp_store * store, void * addr, size_t size)
bkeep_munmap(addr + size, reserve_size, CP_VMA_FLAGS);
}
addr = (void *) DkVirtualMemoryAlloc(addr, size, 0,
PAL_PROT_READ|PAL_PROT_WRITE);
addr = (void*)DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ | PAL_PROT_WRITE);
if (!addr)
bkeep_munmap(addr, size, CP_VMA_FLAGS);
@@ -863,9 +862,7 @@ int do_migration (struct newproc_cp_header * hdr, void ** cpptr)
debug("checkpoint mapped at %p-%p\n", base, base + size);
PAL_FLG pal_prot = PAL_PROT_READ|PAL_PROT_WRITE;
PAL_PTR mapped = DkVirtualMemoryAlloc(mapaddr, mapsize, 0, pal_prot);
PAL_PTR mapped = DkVirtualMemoryAlloc(mapaddr, mapsize, 0, PAL_PROT_READ | PAL_PROT_WRITE);
if (!mapped)
return -PAL_ERRNO;
+1 -3
View File
@@ -207,9 +207,7 @@ void * allocate_stack (size_t size, size_t protect_size, bool user)
if (!stack)
return NULL;
stack = (void *)
DkVirtualMemoryAlloc(stack, size + protect_size,
0, PAL_PROT_NONE);
stack = (void*)DkVirtualMemoryAlloc(stack, size + protect_size, 0, PAL_PROT_NONE);
} else {
stack = system_malloc(size + protect_size);
}
+4 -3
View File
@@ -140,8 +140,8 @@ int init_brk_region(void* brk_region, size_t data_segment_size) {
void* end_brk_region = NULL;
/* Allocate the whole brk region */
void* ret =
(void*)DkVirtualMemoryAlloc(brk_region, brk_max_size, 0, PAL_PROT_READ | PAL_PROT_WRITE);
void* ret = (void*)DkVirtualMemoryAlloc(brk_region, brk_max_size, /*alloc_type=*/0,
PAL_PROT_READ | PAL_PROT_WRITE);
/* Checking if the PAL call succeeds. */
if (!ret) {
@@ -286,7 +286,8 @@ BEGIN_RS_FUNC(brk) {
if (ret < 0)
return ret;
void* ptr = DkVirtualMemoryAlloc(alloc_addr, alloc_size, 0, PAL_PROT_READ | PAL_PROT_WRITE);
void* ptr = DkVirtualMemoryAlloc(alloc_addr, alloc_size, /*alloc_type=*/0,
PAL_PROT_READ | PAL_PROT_WRITE);
__UNUSED(ptr);
assert(ptr == alloc_addr);
debug("brk reserved area: %p - %p\n", alloc_addr, alloc_addr + alloc_size);
+9
View File
@@ -195,6 +195,9 @@ int shim_do_chmod(const char* path, mode_t mode) {
struct shim_dentry* dent = NULL;
int ret = 0;
/* This isn't documented, but that's what Linux does. */
mode &= 07777;
if (test_user_string(path))
return -EFAULT;
@@ -221,6 +224,9 @@ int shim_do_fchmodat(int dfd, const char* filename, mode_t mode) {
if (test_user_string(filename))
return -EFAULT;
/* This isn't documented, but that's what Linux does. */
mode &= 07777;
struct shim_dentry* dir = NULL;
struct shim_dentry* dent = NULL;
int ret = 0;
@@ -251,6 +257,9 @@ int shim_do_fchmod(int fd, mode_t mode) {
if (!hdl)
return -EBADF;
/* This isn't documented, but that's what Linux does. */
mode &= 07777;
struct shim_dentry* dent = hdl->dentry;
int ret = 0;
+13 -10
View File
@@ -21,16 +21,18 @@
*/
#include <errno.h>
#include <pal.h>
#include <pal_error.h>
#include <shim_fs.h>
#include <shim_handle.h>
#include <shim_internal.h>
#include <shim_table.h>
#include <shim_vma.h>
#include <stdatomic.h>
#include <sys/mman.h>
#include "pal.h"
#include "pal_error.h"
#include "shim_flags_conv.h"
#include "shim_fs.h"
#include "shim_handle.h"
#include "shim_internal.h"
#include "shim_table.h"
#include "shim_vma.h"
void* shim_do_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) {
struct shim_handle* hdl = NULL;
long ret = 0;
@@ -116,7 +118,8 @@ void* shim_do_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t
/* addr needs to be kept for bkeep_munmap() below */
void* ret_addr = addr;
if (!hdl) {
ret_addr = (void*)DkVirtualMemoryAlloc(ret_addr, length, pal_alloc_type, PAL_PROT(prot, 0));
ret_addr = (void*)DkVirtualMemoryAlloc(ret_addr, length, pal_alloc_type,
LINUX_PROT_TO_PAL(prot, /*map_flags=*/0));
if (!ret_addr) {
if (PAL_NATIVE_ERRNO == PAL_ERROR_DENIED)
@@ -125,7 +128,7 @@ void* shim_do_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t
ret = -PAL_ERRNO;
}
} else {
ret = hdl->fs->fs_ops->mmap(hdl, &ret_addr, length, PAL_PROT(prot, flags), flags, offset);
ret = hdl->fs->fs_ops->mmap(hdl, &ret_addr, length, prot, flags, offset);
}
if (hdl)
@@ -153,7 +156,7 @@ int shim_do_mprotect(void* addr, size_t length, int prot) {
if (bkeep_mprotect(addr, length, prot, 0) < 0)
return -EPERM;
if (!DkVirtualMemoryProtect(addr, length, prot))
if (!DkVirtualMemoryProtect(addr, length, LINUX_PROT_TO_PAL(prot, /*map_flags=*/0)))
return -PAL_ERRNO;
return 0;
+16
View File
@@ -114,6 +114,14 @@ int shim_do_open (const char * file, int flags, mode_t mode)
if (file[0] == '\0')
return -EINVAL;
if (!(flags & O_CREAT)) {
/* `mode` should be ignored if O_CREAT is not specified, according to man */
mode = 0;
} else {
/* This isn't documented, but that's what Linux does. */
mode &= 07777;
}
struct shim_handle * hdl = get_new_handle();
if (!hdl)
return -ENOMEM;
@@ -139,6 +147,14 @@ int shim_do_openat (int dfd, const char * filename, int flags, int mode)
if (!filename || test_user_string(filename))
return -EFAULT;
if (!(flags & O_CREAT)) {
/* `mode` should be ignored if O_CREAT is not specified, according to man */
mode = 0;
} else {
/* This isn't documented, but that's what Linux does. */
mode &= 07777;
}
struct shim_dentry * dir = NULL;
int ret = 0;
+15 -8
View File
@@ -22,13 +22,15 @@
#include <asm/fcntl.h>
#include <errno.h>
#include <pal.h>
#include <pal_error.h>
#include <shim_fs.h>
#include <shim_handle.h>
#include <shim_internal.h>
#include <shim_table.h>
#include <shim_utils.h>
#include "pal.h"
#include "pal_error.h"
#include "shim_flags_conv.h"
#include "shim_fs.h"
#include "shim_handle.h"
#include "shim_internal.h"
#include "shim_table.h"
#include "shim_utils.h"
static int create_pipes(PAL_HANDLE* srv, PAL_HANDLE* cli, int flags, char* name,
struct shim_qstr* qstr) {
@@ -39,13 +41,18 @@ static int create_pipes(PAL_HANDLE* srv, PAL_HANDLE* cli, int flags, char* name,
PAL_HANDLE hdl1 = NULL; /* one pipe end (accepted connect from hdl2) */
PAL_HANDLE hdl2 = NULL; /* other pipe end (connects to hdl0 and talks to hdl1) */
if (flags & O_DIRECT) {
debug("create_pipes(): tried to create O_DIRECT pipe, which is not supported.\n");
flags &= ~O_DIRECT;
}
if ((ret = create_pipe(name, uri, PIPE_URI_SIZE, &hdl0, qstr,
/*use_vmid_for_name=*/false)) < 0) {
debug("pipe creation failure\n");
return ret;
}
if (!(hdl2 = DkStreamOpen(uri, 0, 0, 0, flags & O_NONBLOCK))) {
if (!(hdl2 = DkStreamOpen(uri, 0, 0, 0, LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(flags)))) {
ret = -PAL_ERRNO;
debug("pipe connection failure\n");
goto out;
+13 -10
View File
@@ -31,13 +31,13 @@
#include "hex.h"
#include "pal.h"
#include "pal_error.h"
#include <shim_checkpoint.h>
#include <shim_fs.h>
#include <shim_handle.h>
#include <shim_internal.h>
#include <shim_table.h>
#include <shim_utils.h>
#include "shim_checkpoint.h"
#include "shim_flags_conv.h"
#include "shim_fs.h"
#include "shim_handle.h"
#include "shim_internal.h"
#include "shim_table.h"
#include "shim_utils.h"
/*
* User-settable options (used with setsockopt).
@@ -533,7 +533,8 @@ int shim_do_bind(int sockfd, struct sockaddr* addr, socklen_t addrlen) {
create_flags &= ~PAL_CREATE_DUALSTACK;
}
PAL_HANDLE pal_hdl = DkStreamOpen(qstrgetstr(&hdl->uri), 0, 0, create_flags, hdl->flags & O_NONBLOCK);
PAL_HANDLE pal_hdl = DkStreamOpen(qstrgetstr(&hdl->uri), 0, 0, create_flags,
hdl->flags & O_NONBLOCK ? PAL_OPTION_NONBLOCK : 0);
if (!pal_hdl) {
ret = (PAL_NATIVE_ERRNO == PAL_ERROR_STREAMEXIST) ? -EADDRINUSE : -PAL_ERRNO;
@@ -802,7 +803,8 @@ int shim_do_connect(int sockfd, struct sockaddr* addr, int addrlen) {
if ((ret = create_socket_uri(hdl)) < 0)
goto out;
PAL_HANDLE pal_hdl = DkStreamOpen(qstrgetstr(&hdl->uri), 0, 0, 0, hdl->flags & O_NONBLOCK);
PAL_HANDLE pal_hdl = DkStreamOpen(qstrgetstr(&hdl->uri), 0, 0, 0,
hdl->flags & O_NONBLOCK ? PAL_OPTION_NONBLOCK : 0);
if (!pal_hdl) {
ret = (PAL_NATIVE_ERRNO == PAL_ERROR_DENIED) ? -ECONNREFUSED : -PAL_ERRNO;
@@ -1061,7 +1063,8 @@ static ssize_t do_sendmsg(int fd, struct iovec* bufs, int nbufs, int flags,
}
if (sock->sock_state == SOCK_CREATED && !pal_hdl) {
pal_hdl = DkStreamOpen(URI_PREFIX_UDP, 0, 0, 0, hdl->flags & O_NONBLOCK);
pal_hdl = DkStreamOpen(URI_PREFIX_UDP, 0, 0, 0,
hdl->flags & O_NONBLOCK ? PAL_OPTION_NONBLOCK : 0);
if (!pal_hdl) {
ret = -PAL_ERRNO;
goto out_locked;
+6
View File
@@ -2,6 +2,7 @@
import os
import unittest
import shutil
import subprocess
from regression import (
@@ -240,6 +241,9 @@ class TC_30_Syscall(RegressionTestCase):
self.assertIn('fstat returned the fd type as S_IFDIR', stdout)
def test_020_getdents(self):
if os.path.exists("root"):
shutil.rmtree("root")
# This doesn't catch extraneous entries, but should be fine
# until the LTP test can be run (need symlink support)
@@ -261,6 +265,8 @@ class TC_30_Syscall(RegressionTestCase):
self.assertIn('getdents64: dir3 [0x4]', stdout)
def test_021_getdents_large_dir(self):
if os.path.exists("tmp/large_dir"):
shutil.rmtree("tmp/large_dir")
stdout, _ = self.run_binary(['large_dir_read', 'tmp/large_dir', '3000'])
self.assertIn('Success!', stdout)
@@ -0,0 +1,68 @@
/* Copyright (C) 2020 Invisible Things Lab
Michał Kowalczyk <mkow@invisiblethingslab.com>
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/*
* This file defines conversions between various PAL API flags and the flags used by Linux syscalls.
*
* The counterpart of this file is shim_flag_conv.h in LibOS.
*/
#ifndef PAL_FLAGS_CONV_H
#define PAL_FLAGS_CONV_H
#undef __GLIBC__
#include <asm/fcntl.h>
#include <linux/mman.h>
#include <linux/stat.h>
#include <sys/types.h>
#include "assert.h"
#include "pal.h"
static inline int PAL_MEM_FLAGS_TO_LINUX(int alloc_type, int prot) {
assert(WITHIN_MASK(alloc_type, PAL_ALLOC_MASK));
assert(WITHIN_MASK(prot, PAL_PROT_MASK));
return (alloc_type & PAL_ALLOC_RESERVE ? MAP_NORESERVE | MAP_UNINITIALIZED : 0) |
(prot & PAL_PROT_WRITECOPY ? MAP_PRIVATE : MAP_SHARED);
}
static inline int PAL_PROT_TO_LINUX(int prot) {
assert(WITHIN_MASK(prot, PAL_PROT_MASK));
return (prot & PAL_PROT_READ ? PROT_READ : 0) |
(prot & PAL_PROT_WRITE ? PROT_WRITE : 0) |
(prot & PAL_PROT_EXEC ? PROT_EXEC : 0);
}
static inline int PAL_ACCESS_TO_LINUX_OPEN(int access) {
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
return (access & PAL_ACCESS_RDONLY ? O_RDONLY : 0) |
(access & PAL_ACCESS_WRONLY ? O_WRONLY : 0) |
(access & PAL_ACCESS_RDWR ? O_RDWR : 0) |
(access & PAL_ACCESS_APPEND ? O_APPEND : 0);
}
static inline int PAL_CREATE_TO_LINUX_OPEN(int create) {
assert(create == 0 || create == PAL_CREATE_TRY || create == PAL_CREATE_ALWAYS);
return (create & PAL_CREATE_TRY ? O_CREAT : 0) |
(create & PAL_CREATE_ALWAYS ? O_CREAT | O_EXCL : 0);
}
static inline int PAL_OPTION_TO_LINUX_OPEN(int options) {
assert(WITHIN_MASK(options, PAL_OPTION_CLOEXEC | PAL_OPTION_NONBLOCK));
return (options & PAL_OPTION_CLOEXEC ? O_CLOEXEC : 0) |
(options & PAL_OPTION_NONBLOCK ? O_NONBLOCK : 0);
}
#endif /* PAL_FLAGS_CONV_H */
+36 -30
View File
@@ -352,8 +352,10 @@ PAL_CONTROL * pal_control_addr (void);
/*! Memory Allocation Flags */
enum PAL_ALLOC {
PAL_ALLOC_RESERVE = 0x0001, /*!< Only reserve the memory */
PAL_ALLOC_INTERNAL = 0x8000, /*!< Allocate for PAL (valid only if #IN_PAL) */
PAL_ALLOC_RESERVE = 0x1, /*!< Only reserve the memory */
PAL_ALLOC_INTERNAL = 0x2, /*!< Allocate for PAL (valid only if #IN_PAL) */
PAL_ALLOC_MASK = 0x3,
};
/*! Memory Protection Flags */
@@ -447,44 +449,49 @@ DkProcessExit(PAL_NUM exitCode);
/*! Stream Access Flags */
enum PAL_ACCESS {
PAL_ACCESS_RDONLY = 00,
PAL_ACCESS_WRONLY = 01,
PAL_ACCESS_RDWR = 02,
PAL_ACCESS_APPEND = 04,
PAL_ACCESS_MASK = 07,
PAL_ACCESS_RDONLY = 0,
PAL_ACCESS_WRONLY = 1,
PAL_ACCESS_RDWR = 2,
PAL_ACCESS_APPEND = 4,
PAL_ACCESS_MASK = 7,
};
/*! Stream Sharing Flags */
// FIXME: These flags currently must correspond 1-1 to Linux flags, which is totally unportable.
// They should be redesigned when we'll be rewriting the filesystem layer.
enum PAL_SHARE {
PAL_SHARE_GLOBAL_X = 01,
PAL_SHARE_GLOBAL_W = 02,
PAL_SHARE_GLOBAL_R = 04,
PAL_SHARE_GROUP_X = 010,
PAL_SHARE_GROUP_W = 020,
PAL_SHARE_GROUP_R = 040,
PAL_SHARE_OWNER_X = 0100,
PAL_SHARE_OWNER_W = 0200,
PAL_SHARE_OWNER_R = 0400,
PAL_SHARE_MASK = 0777,
PAL_SHARE_GLOBAL_X = 01,
PAL_SHARE_GLOBAL_W = 02,
PAL_SHARE_GLOBAL_R = 04,
PAL_SHARE_GROUP_X = 010,
PAL_SHARE_GROUP_W = 020,
PAL_SHARE_GROUP_R = 040,
PAL_SHARE_OWNER_X = 0100,
PAL_SHARE_OWNER_W = 0200,
PAL_SHARE_OWNER_R = 0400,
PAL_SHARE_STICKY = 01000,
PAL_SHARE_SET_GID = 02000,
PAL_SHARE_SET_UID = 04000,
PAL_SHARE_MASK = 07777,
};
/*! Stream Create Flags */
enum PAL_CREATE {
PAL_CREATE_TRY = 0100, /*!< Create file if file not exist (O_CREAT) */
PAL_CREATE_ALWAYS = 0200, /*!< Create file and fail if file already exist
(O_CREAT|O_EXCL) */
PAL_CREATE_DUALSTACK = 0400, /*!< Create dual-stack socket (opposite of IPV6_V6ONLY) */
PAL_CREATE_TRY = 1, /*!< Create file if file does not exist */
PAL_CREATE_ALWAYS = 2, /*!< Create file and fail if file already exists */
PAL_CREATE_DUALSTACK = 4, /*!< Create dual-stack socket (opposite of IPV6_V6ONLY) */
PAL_CREATE_MASK = 0700,
PAL_CREATE_MASK = 7,
};
/*! Stream Option Flags */
enum PAL_OPTION {
PAL_OPTION_CLOEXEC = 01000,
PAL_OPTION_EFD_SEMAPHORE = 02000, /*!< specific to `eventfd` syscall */
PAL_OPTION_NONBLOCK = 04000,
PAL_OPTION_CLOEXEC = 1,
PAL_OPTION_EFD_SEMAPHORE = 2, /*!< specific to `eventfd` syscall */
PAL_OPTION_NONBLOCK = 4,
PAL_OPTION_MASK = 07000,
PAL_OPTION_MASK = 7,
};
@@ -551,8 +558,8 @@ PAL_NUM
DkStreamWrite(PAL_HANDLE handle, PAL_NUM offset, PAL_NUM count, PAL_PTR buffer, PAL_STR dest);
enum PAL_DELETE {
PAL_DELETE_RD = 01, /*!< shut down the read side only */
PAL_DELETE_WR = 02, /*!< shut down the write side only */
PAL_DELETE_RD = 1, /*!< shut down the read side only */
PAL_DELETE_WR = 2, /*!< shut down the write side only */
};
/*!
@@ -560,8 +567,7 @@ enum PAL_DELETE {
*
* \param access which side to shut down (#PAL_DELETE), or both if 0 is given.
*/
void
DkStreamDelete(PAL_HANDLE handle, PAL_FLG access);
void DkStreamDelete(PAL_HANDLE handle, PAL_FLG access);
/*!
* \brief Map a file to a virtual memory address in the current process.
+3 -3
View File
@@ -103,13 +103,13 @@ int main(int argc, char** argv, char** envp) {
PAL_HANDLE file4 =
DkStreamOpen("file:file_nonexist.tmp", PAL_ACCESS_RDWR,
PAL_SHARE_OWNER_R | PAL_SHARE_OWNER_W, PAL_CREATE_TRY | PAL_CREATE_ALWAYS, 0);
PAL_SHARE_OWNER_R | PAL_SHARE_OWNER_W, PAL_CREATE_ALWAYS, 0);
if (file4)
pal_printf("File Creation Test 1 OK\n");
PAL_HANDLE file5 =
DkStreamOpen("file:file_nonexist.tmp", PAL_ACCESS_RDWR,
PAL_SHARE_OWNER_R | PAL_SHARE_OWNER_W, PAL_CREATE_TRY | PAL_CREATE_ALWAYS, 0);
PAL_SHARE_OWNER_R | PAL_SHARE_OWNER_W, PAL_CREATE_ALWAYS, 0);
if (file5) {
DkObjectClose(file5);
} else {
@@ -125,7 +125,7 @@ int main(int argc, char** argv, char** envp) {
file6 =
DkStreamOpen("file:file_nonexist_disallowed.tmp", PAL_ACCESS_RDWR,
PAL_SHARE_OWNER_R | PAL_SHARE_OWNER_W, PAL_CREATE_TRY | PAL_CREATE_ALWAYS, 0);
PAL_SHARE_OWNER_R | PAL_SHARE_OWNER_W, PAL_CREATE_ALWAYS, 0);
if (!file6) {
pal_printf("File Creation Test 4 OK\n");
} else {
+1 -2
View File
@@ -27,8 +27,7 @@
#include "pal_error.h"
#include "pal_internal.h"
PAL_PTR
DkVirtualMemoryAlloc(PAL_PTR addr, PAL_NUM size, PAL_FLG alloc_type, PAL_FLG prot) {
PAL_PTR DkVirtualMemoryAlloc(PAL_PTR addr, PAL_NUM size, PAL_FLG alloc_type, PAL_FLG prot) {
ENTER_PAL_CALL(DkVirtualMemoryAlloc);
void* map_addr = (void*)addr;
+22 -14
View File
@@ -157,6 +157,11 @@ int _DkStreamOpen(PAL_HANDLE* handle, const char* uri, int access, int share, in
struct handle_ops* ops = NULL;
char* type = NULL;
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
int ret = parse_stream_uri(&uri, &type, &ops);
if (ret < 0)
return ret;
@@ -169,13 +174,17 @@ int _DkStreamOpen(PAL_HANDLE* handle, const char* uri, int access, int share, in
/* PAL call DkStreamOpen: Open stream based on uri, as given access/share/
create/options flags. DkStreamOpen return a PAL_HANDLE to access the
stream, or return NULL. Error code is notified. */
PAL_HANDLE
DkStreamOpen(PAL_STR uri, PAL_FLG access, PAL_FLG share, PAL_FLG create, PAL_FLG options) {
stream, or return NULL. Error code is notified.
FIXME: Currently `share` must match 1-1 to Linux open() `mode` argument. This isn't really
portable and will cause problems when implementing other PALs.
*/
PAL_HANDLE DkStreamOpen(PAL_STR uri, PAL_FLG access, PAL_FLG share, PAL_FLG create,
PAL_FLG options) {
ENTER_PAL_CALL(DkStreamOpen);
PAL_HANDLE handle = NULL;
int ret = _DkStreamOpen(&handle, uri, access, share, create, options);
int ret = _DkStreamOpen(&handle, uri, access, share, create, options);
if (ret < 0) {
_DkRaiseFailure(-ret);
@@ -221,6 +230,8 @@ DkStreamWaitForClient(PAL_HANDLE handle) {
the stream. For example, file will be deleted, socket witll be
disconnected, etc */
int _DkStreamDelete(PAL_HANDLE handle, int access) {
assert(access == 0 || access == PAL_DELETE_RD || access == PAL_DELETE_WR);
const struct handle_ops* ops = HANDLE_OPS(handle);
if (!ops)
@@ -371,8 +382,7 @@ int _DkStreamAttributesQuery(const char* uri, PAL_STREAM_ATTR* attr) {
/* PAL call DkStreamAttributeQuery: query attribute of a stream by its
URI, attr is memory given by user space. Return the pointer of attr
if succeeded, or NULL if failed. Error code is notified */
PAL_BOL
DkStreamAttributesQuery(PAL_STR uri, PAL_STREAM_ATTR* attr) {
PAL_BOL DkStreamAttributesQuery(PAL_STR uri, PAL_STREAM_ATTR* attr) {
ENTER_PAL_CALL(DkStreamAttributesQuery);
if (!uri || !attr) {
@@ -410,8 +420,7 @@ int _DkStreamAttributesQueryByHandle(PAL_HANDLE hdl, PAL_STREAM_ATTR* attr) {
/* PAL call DkStreamAttributesQueryByHandle: Query attribute of a stream by
its handle, attr is memory given by user space. Return the pointer of attr
if succeeded, or NULL if failed. Error code is notified */
PAL_BOL
DkStreamAttributesQueryByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
PAL_BOL DkStreamAttributesQueryByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
ENTER_PAL_CALL(DkStreamAttributesQueryByHandle);
if (!handle || !attr) {
@@ -432,8 +441,7 @@ DkStreamAttributesQueryByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
/* PAL call DkStreamAttributesSetByHandle: Set attribute of a stream by
its handle, attr is memory given by user space. Return the pointer of attr
if succeeded, or NULL if failed. Error code is notified */
PAL_BOL
DkStreamAttributesSetByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
PAL_BOL DkStreamAttributesSetByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
ENTER_PAL_CALL(DkStreamAttributesSetByHandle);
if (!handle || !attr) {
@@ -507,6 +515,8 @@ int _DkStreamMap(PAL_HANDLE handle, void** paddr, int prot, uint64_t offset, uin
void* addr = *paddr;
int ret;
assert(WITHIN_MASK(prot, PAL_PROT_MASK));
const struct handle_ops* ops = HANDLE_OPS(handle);
if (!ops)
@@ -526,8 +536,7 @@ int _DkStreamMap(PAL_HANDLE handle, void** paddr, int prot, uint64_t offset, uin
space. prot/offset/size are the protection, offset and size of the memory
mapping. Return the address if succeeded or NULL if failed. Error code
is notified. */
PAL_PTR
DkStreamMap(PAL_HANDLE handle, PAL_PTR addr, PAL_FLG prot, PAL_NUM offset, PAL_NUM size) {
PAL_PTR DkStreamMap(PAL_HANDLE handle, PAL_PTR addr, PAL_FLG prot, PAL_NUM offset, PAL_NUM size) {
ENTER_PAL_CALL(DkStreamMap);
void* map_addr = (void*)addr;
@@ -598,8 +607,7 @@ int64_t _DkStreamSetLength(PAL_HANDLE handle, uint64_t length) {
/* PAL call DkStreamSetLength: Truncate the stream at certain length.
Return the length if succeeded or 0 if failed. Error code is notified. */
PAL_NUM
DkStreamSetLength(PAL_HANDLE handle, PAL_NUM length) {
PAL_NUM DkStreamSetLength(PAL_HANDLE handle, PAL_NUM length) {
PAL_NUM rv = 0;
ENTER_PAL_CALL(DkStreamSetLength);
+9 -4
View File
@@ -115,11 +115,16 @@ static int open_standard_term(PAL_HANDLE* handle, const char* param, int access)
/* 'open' operation for terminal stream */
static int term_open(PAL_HANDLE* handle, const char* type, const char* uri, int access, int share,
int create, int options) {
if (strcmp_static(type, "tty"))
return -PAL_ERROR_INVAL;
__UNUSED(share);
__UNUSED(create);
__UNUSED(options);
if (!WITHIN_MASK(share, PAL_SHARE_MASK) || !WITHIN_MASK(create, PAL_CREATE_MASK) ||
!WITHIN_MASK(options, PAL_OPTION_MASK))
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
if (strcmp_static(type, "tty"))
return -PAL_ERROR_INVAL;
const char* term = NULL;
+16 -6
View File
@@ -29,6 +29,7 @@
#include "pal_debug.h"
#include "pal_defs.h"
#include "pal_error.h"
#include "pal_flags_conv.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_linux_defs.h"
@@ -48,7 +49,10 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
if (strcmp_static(type, URI_TYPE_FILE))
return -PAL_ERROR_INVAL;
/* try to do the real open */
int fd = ocall_open(uri, access | create | options, share);
int fd = ocall_open(uri, PAL_ACCESS_TO_LINUX_OPEN(access) |
PAL_CREATE_TO_LINUX_OPEN(create) |
PAL_OPTION_TO_LINUX_OPEN(options),
share);
if (IS_ERR(fd))
return unix_to_pal_error(ERRNO(fd));
@@ -184,7 +188,7 @@ static int file_map(PAL_HANDLE handle, void** addr, int prot, uint64_t offset, u
* does not request a specific address.
*/
if (!mem && !stubs && !(prot & PAL_PROT_WRITECOPY)) {
ret = ocall_mmap_untrusted(handle->file.fd, offset, size, HOST_PROT(prot), &mem);
ret = ocall_mmap_untrusted(handle->file.fd, offset, size, PAL_PROT_TO_LINUX(prot), &mem);
if (!IS_ERR(ret))
*addr = mem;
return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : ret;
@@ -394,13 +398,19 @@ static int dir_open(PAL_HANDLE* handle, const char* type, const char* uri, int a
int ret;
if (create & PAL_CREATE_TRY) {
if (create & PAL_CREATE_TRY || create & PAL_CREATE_ALWAYS) {
ret = ocall_mkdir(uri, share);
if (IS_ERR(ret) && ERRNO(ret) == EEXIST && create & PAL_CREATE_ALWAYS)
return -PAL_ERROR_STREAMEXIST;
if (IS_ERR(ret)) {
if (ERRNO(ret) == EEXIST && create & PAL_CREATE_ALWAYS)
return -PAL_ERROR_STREAMEXIST;
if (ERRNO(ret) != EEXIST)
return unix_to_pal_error(ERRNO(ret));
assert(ERRNO(ret) == EEXIST && create & PAL_CREATE_TRY);
}
}
ret = ocall_open(uri, O_DIRECTORY | options, 0);
ret = ocall_open(uri, O_DIRECTORY | PAL_OPTION_TO_LINUX_OPEN(options), 0);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
+9 -1
View File
@@ -26,6 +26,7 @@
#include "pal_debug.h"
#include "pal_defs.h"
#include "pal_error.h"
#include "pal_flags_conv.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_linux_defs.h"
@@ -47,7 +48,12 @@ bool _DkCheckMemoryMappable(const void* addr, size_t size) {
}
int _DkVirtualMemoryAlloc(void** paddr, uint64_t size, int alloc_type, int prot) {
if (!size || !WITHIN_MASK(prot, PAL_PROT_MASK))
__UNUSED(prot);
assert(WITHIN_MASK(alloc_type, PAL_ALLOC_MASK));
assert(WITHIN_MASK(prot, PAL_PROT_MASK));
if (!size)
return -PAL_ERROR_INVAL;
void* addr = *paddr;
@@ -85,6 +91,8 @@ int _DkVirtualMemoryProtect(void* addr, uint64_t size, int prot) {
__UNUSED(size);
__UNUSED(prot);
assert(WITHIN_MASK(prot, PAL_PROT_MASK));
static struct atomic_int at_cnt = {.counter = 0};
if (atomic_cmpxchg(&at_cnt, 0, 1) == 0)
SGX_DBG(DBG_M, "[Warning] DkVirtualMemoryProtect is unimplemented in Linux-SGX PAL");
+14 -6
View File
@@ -436,9 +436,13 @@ static int tcp_connect(PAL_HANDLE* handle, char* uri, int options) {
/* 'open' operation of tcp stream */
static int tcp_open(PAL_HANDLE* handle, const char* type, const char* uri, int access, int share,
int create, int options) {
if (!WITHIN_MASK(access, PAL_ACCESS_MASK) || !WITHIN_MASK(share, PAL_SHARE_MASK) ||
!WITHIN_MASK(create, PAL_CREATE_MASK) || !WITHIN_MASK(options, PAL_OPTION_MASK))
return -PAL_ERROR_INVAL;
__UNUSED(access);
__UNUSED(share);
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
int uri_len = strlen(uri) + 1;
@@ -589,9 +593,13 @@ static int udp_connect(PAL_HANDLE* handle, char* uri, int create, int options) {
static int udp_open(PAL_HANDLE* hdl, const char* type, const char* uri, int access, int share,
int create, int options) {
if (!WITHIN_MASK(access, PAL_ACCESS_MASK) || !WITHIN_MASK(share, PAL_SHARE_MASK) ||
!WITHIN_MASK(create, PAL_CREATE_MASK) || !WITHIN_MASK(options, PAL_OPTION_MASK))
return -PAL_ERROR_INVAL;
__UNUSED(access);
__UNUSED(share);
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
char buf[PAL_SOCKADDR_SIZE];
int len = strlen(uri);
+1 -12
View File
@@ -66,18 +66,7 @@ extern struct pal_linux_state {
#define PRESET_PAGESIZE (1 << 12)
#define DEFAULT_BACKLOG 2048
static inline int HOST_FLAGS (int alloc_type, int prot)
{
return ((alloc_type & PAL_ALLOC_RESERVE) ? MAP_NORESERVE|MAP_UNINITIALIZED : 0) |
((prot & PAL_PROT_WRITECOPY) ? MAP_PRIVATE : MAP_SHARED);
}
static inline int HOST_PROT (int prot)
{
return prot & (PAL_PROT_READ|PAL_PROT_WRITE|PAL_PROT_EXEC);
}
#define DEFAULT_BACKLOG 2048
#define ACCESS_R 4
#define ACCESS_W 2
+5 -5
View File
@@ -114,13 +114,13 @@ static long sgx_ocall_cpuid(void * pms)
return 0;
}
static long sgx_ocall_open(void * pms)
{
ms_ocall_open_t * ms = (ms_ocall_open_t *) pms;
static long sgx_ocall_open(void* pms) {
ms_ocall_open_t* ms = (ms_ocall_open_t*)pms;
long ret;
ODEBUG(OCALL_OPEN, ms);
ret = INLINE_SYSCALL(open, 3, ms->ms_pathname, ms->ms_flags|O_CLOEXEC,
ms->ms_mode);
// FIXME: No idea why someone hardcoded O_CLOEXEC here. We should drop it and carefully
// investigate if this cause any descriptor leaks.
ret = INLINE_SYSCALL(open, 3, ms->ms_pathname, ms->ms_flags | O_CLOEXEC, ms->ms_mode);
return ret;
}
+8 -3
View File
@@ -113,12 +113,17 @@ static int open_standard_term(PAL_HANDLE* handle, const char* param, int access)
/* 'open' operation for terminal stream */
static int term_open(PAL_HANDLE* handle, const char* type, const char* uri, int access, int share,
int create, int options) {
__UNUSED(share);
__UNUSED(create);
__UNUSED(options);
if (strcmp_static(type, "tty"))
return -PAL_ERROR_INVAL;
if (!WITHIN_MASK(share, PAL_SHARE_MASK) || !WITHIN_MASK(create, PAL_CREATE_MASK) ||
!WITHIN_MASK(options, PAL_OPTION_MASK))
return -PAL_ERROR_INVAL;
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
const char* term = NULL;
const char* param = NULL;
+32 -19
View File
@@ -24,6 +24,7 @@
#include "pal_defs.h"
#include "pal_linux_defs.h"
#include "pal.h"
#include "pal_flags_conv.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_linux_error.h"
@@ -43,8 +44,19 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
if (strcmp_static(type, URI_TYPE_FILE))
return -PAL_ERROR_INVAL;
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
/* try to do the real open */
int ret = INLINE_SYSCALL(open, 3, uri, HOST_ACCESS(access)|create|options|O_CLOEXEC, share);
// FIXME: No idea why someone hardcoded O_CLOEXEC here. We should drop it and carefully
// investigate if this causes any descriptor leaks.
int ret = INLINE_SYSCALL(open, 3, uri, PAL_ACCESS_TO_LINUX_OPEN(access) |
PAL_CREATE_TO_LINUX_OPEN(create) |
PAL_OPTION_TO_LINUX_OPEN(options) |
O_CLOEXEC,
share);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
@@ -124,11 +136,9 @@ static int file_delete (PAL_HANDLE handle, int access)
}
/* 'map' operation for file stream. */
static int file_map (PAL_HANDLE handle, void ** addr, int prot,
uint64_t offset, uint64_t size)
{
static int file_map(PAL_HANDLE handle, void** addr, int prot, uint64_t offset, uint64_t size) {
int fd = handle->file.fd;
void * mem = *addr;
void* mem = *addr;
/*
* work around for fork emulation
* the first exec image to be loaded has to be at same address
@@ -139,12 +149,11 @@ static int file_map (PAL_HANDLE handle, void ** addr, int prot,
/* this address is used. don't over-map it later */
handle->file.map_start = NULL;
}
int flags = MAP_FILE|HOST_FLAGS(0, prot)|(mem ? MAP_FIXED : 0);
prot = HOST_PROT(prot);
int flags = MAP_FILE | PAL_MEM_FLAGS_TO_LINUX(0, prot) | (mem ? MAP_FIXED : 0);
prot = PAL_PROT_TO_LINUX(prot);
/* The memory will always allocated with flag MAP_PRIVATE
and MAP_FILE */
mem = (void *) ARCH_MMAP(mem, size, prot, flags, fd, offset);
/* The memory will always be allocated with flag MAP_PRIVATE and MAP_FILE */
mem = (void*)ARCH_MMAP(mem, size, prot, flags, fd, offset);
if (IS_ERR_P(mem))
return -PAL_ERROR_DENIED;
@@ -320,9 +329,8 @@ struct handle_ops file_ops = {
/* 'open' operation for directory stream. Directory stream does not have a
specific type prefix, its URI looks the same file streams, plus it
ended with slashes. dir_open will be called by file_open. */
static int dir_open (PAL_HANDLE * handle, const char * type, const char * uri,
int access, int share, int create, int options)
{
static int dir_open(PAL_HANDLE* handle, const char* type, const char* uri, int access, int share,
int create, int options) {
if (strcmp_static(type, URI_TYPE_DIR))
return -PAL_ERROR_INVAL;
if (!WITHIN_MASK(access, PAL_ACCESS_MASK))
@@ -330,15 +338,20 @@ static int dir_open (PAL_HANDLE * handle, const char * type, const char * uri,
int ret = 0;
if (create & PAL_CREATE_TRY) {
if (create & PAL_CREATE_TRY || create & PAL_CREATE_ALWAYS) {
ret = INLINE_SYSCALL(mkdir, 2, uri, share);
if (IS_ERR(ret) && ERRNO(ret) == EEXIST &&
create & PAL_CREATE_ALWAYS)
return -PAL_ERROR_STREAMEXIST;
if (IS_ERR(ret)) {
if (ERRNO(ret) == EEXIST && create & PAL_CREATE_ALWAYS)
return -PAL_ERROR_STREAMEXIST;
if (ERRNO(ret) != EEXIST)
return unix_to_pal_error(ERRNO(ret));
assert(ERRNO(ret) == EEXIST && create & PAL_CREATE_TRY);
}
}
ret = INLINE_SYSCALL(open, 3, uri, O_DIRECTORY|options|O_CLOEXEC, 0);
ret = INLINE_SYSCALL(open, 3, uri, O_DIRECTORY | PAL_OPTION_TO_LINUX_OPEN(options) | O_CLOEXEC,
0);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
@@ -348,7 +361,7 @@ static int dir_open (PAL_HANDLE * handle, const char * type, const char * uri,
SET_HANDLE_TYPE(hdl, dir);
HANDLE_HDR(hdl)->flags |= RFD(0);
hdl->dir.fd = ret;
char * path = (void *) hdl + HANDLE_SIZE(dir);
char* path = (void*)hdl + HANDLE_SIZE(dir);
memcpy(path, uri, len + 1);
hdl->dir.realpath = (PAL_STR) path;
hdl->dir.buf = (PAL_PTR) NULL;
+1 -2
View File
@@ -285,8 +285,7 @@ void pal_linux_main(void* initial_rsp, void* fini_callback) {
INIT_FAIL(PAL_ERROR_NOMEM, "Out of memory");
snprintf(uri, size, URI_PREFIX_FILE "%s", exec_target);
PAL_HANDLE file;
// FIXME: `options` should be `PAL_OPTION_CLOEXEC`, but _DkStreamOpen is totally broken.
int ret = _DkStreamOpen(&file, uri, PAL_ACCESS_RDONLY, 0, 0, 0);
int ret = _DkStreamOpen(&file, uri, PAL_ACCESS_RDONLY, 0, 0, PAL_OPTION_CLOEXEC);
free(uri);
if (ret < 0)
INIT_FAIL(-ret, "Failed to open file to execute");
+20 -20
View File
@@ -20,33 +20,35 @@
* This files contains APIs that allocate, free or protect virtual memory.
*/
#include "pal_defs.h"
#include "pal_linux_defs.h"
#include "api.h"
#include "pal.h"
#include "pal_debug.h"
#include "pal_defs.h"
#include "pal_error.h"
#include "pal_flags_conv.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_error.h"
#include "pal_debug.h"
#include "api.h"
#include "pal_linux_defs.h"
#include <asm/mman.h>
#include <asm/fcntl.h>
#include <asm/mman.h>
bool _DkCheckMemoryMappable (const void * addr, size_t size)
{
bool _DkCheckMemoryMappable(const void* addr, size_t size) {
return (addr < DATA_END && addr + size > TEXT_START);
}
int _DkVirtualMemoryAlloc (void ** paddr, size_t size, int alloc_type,
int prot)
{
void * addr = *paddr, * mem = addr;
int _DkVirtualMemoryAlloc(void** paddr, size_t size, int alloc_type, int prot) {
assert(WITHIN_MASK(alloc_type, PAL_ALLOC_MASK));
assert(WITHIN_MASK(prot, PAL_PROT_MASK));
int flags = HOST_FLAGS(alloc_type, prot|PAL_PROT_WRITECOPY);
prot = HOST_PROT(prot);
void* addr = *paddr;
void* mem = addr;
flags |= MAP_ANONYMOUS|(addr ? MAP_FIXED : 0);
mem = (void *) ARCH_MMAP(addr, size, prot, flags, -1, 0);
int flags = PAL_MEM_FLAGS_TO_LINUX(alloc_type, prot | PAL_PROT_WRITECOPY);
prot = PAL_PROT_TO_LINUX(prot);
flags |= MAP_ANONYMOUS | (addr ? MAP_FIXED : 0);
mem = (void*)ARCH_MMAP(addr, size, prot, flags, -1, 0);
if (IS_ERR_P(mem))
return unix_to_pal_error(ERRNO_P(mem));
@@ -62,10 +64,8 @@ int _DkVirtualMemoryFree (void * addr, size_t size)
return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
}
int _DkVirtualMemoryProtect (void * addr, size_t size, int prot)
{
int ret = INLINE_SYSCALL(mprotect, 3, addr, size, HOST_PROT(prot));
int _DkVirtualMemoryProtect(void* addr, size_t size, int prot) {
int ret = INLINE_SYSCALL(mprotect, 3, addr, size, PAL_PROT_TO_LINUX(prot));
return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
}
+26 -11
View File
@@ -339,7 +339,9 @@ static int tcp_listen(PAL_HANDLE* handle, char* uri, int create, int options) {
return -PAL_ERROR_INVAL;
#endif
fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC | options, 0);
int sock_options = options & PAL_OPTION_NONBLOCK ? SOCK_NONBLOCK : 0;
fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC | sock_options,
0);
if (IS_ERR(fd))
return -PAL_ERROR_DENIED;
@@ -411,7 +413,7 @@ static int tcp_accept(PAL_HANDLE handle, PAL_HANDLE* client) {
socklen_t addrlen = sizeof(struct sockaddr);
int ret = 0;
int newfd = INLINE_SYSCALL(accept4, 4, handle->sock.fd, &buffer, &addrlen, O_CLOEXEC);
int newfd = INLINE_SYSCALL(accept4, 4, handle->sock.fd, &buffer, &addrlen, SOCK_CLOEXEC);
if (IS_ERR(newfd))
switch (ERRNO(newfd)) {
@@ -460,7 +462,9 @@ static int tcp_connect(PAL_HANDLE* handle, char* uri, int options) {
if (bind_addr && bind_addr->sa_family != dest_addr->sa_family)
return -PAL_ERROR_INVAL;
fd = INLINE_SYSCALL(socket, 3, dest_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC | options, 0);
int sock_options = options & PAL_OPTION_NONBLOCK ? SOCK_NONBLOCK : 0;
fd = INLINE_SYSCALL(socket, 3, dest_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC | sock_options,
0);
if (IS_ERR(fd))
return -PAL_ERROR_DENIED;
@@ -521,9 +525,13 @@ failed:
/* 'open' operation of tcp stream */
static int tcp_open(PAL_HANDLE* handle, const char* type, const char* uri, int access, int share,
int create, int options) {
if (!WITHIN_MASK(access, PAL_ACCESS_MASK) || !WITHIN_MASK(share, PAL_SHARE_MASK) ||
!WITHIN_MASK(create, PAL_CREATE_MASK))
return -PAL_ERROR_INVAL;
__UNUSED(access);
__UNUSED(share);
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
size_t uri_len = strlen(uri) + 1;
@@ -626,7 +634,9 @@ static int udp_bind(PAL_HANDLE* handle, char* uri, int create, int options) {
return -PAL_ERROR_INVAL;
#endif
fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family, SOCK_DGRAM | SOCK_CLOEXEC | options, 0);
int sock_options = options & PAL_OPTION_NONBLOCK ? SOCK_NONBLOCK : 0;
fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family, SOCK_DGRAM | SOCK_CLOEXEC | sock_options,
0);
if (IS_ERR(fd))
return -PAL_ERROR_DENIED;
@@ -687,8 +697,9 @@ static int udp_connect(PAL_HANDLE* handle, char* uri, int create, int options) {
return -PAL_ERROR_INVAL;
#endif
int sock_options = options & PAL_OPTION_NONBLOCK ? SOCK_NONBLOCK : 0;
fd = INLINE_SYSCALL(socket, 3, dest_addr ? dest_addr->sa_family : AF_INET,
SOCK_DGRAM | SOCK_CLOEXEC | options, 0);
SOCK_DGRAM | SOCK_CLOEXEC | sock_options, 0);
if (IS_ERR(fd))
return -PAL_ERROR_DENIED;
@@ -737,9 +748,13 @@ failed:
static int udp_open(PAL_HANDLE* hdl, const char* type, const char* uri, int access, int share,
int create, int options) {
if (!WITHIN_MASK(access, PAL_ACCESS_MASK) || !WITHIN_MASK(share, PAL_SHARE_MASK) ||
!WITHIN_MASK(create, PAL_CREATE_MASK) || !WITHIN_MASK(options, PAL_OPTION_MASK))
return -PAL_ERROR_INVAL;
__UNUSED(access);
__UNUSED(share);
assert(WITHIN_MASK(access, PAL_ACCESS_MASK));
assert(WITHIN_MASK(share, PAL_SHARE_MASK));
assert(WITHIN_MASK(create, PAL_CREATE_MASK));
assert(WITHIN_MASK(options, PAL_OPTION_MASK));
char buf[PAL_SOCKADDR_SIZE];
size_t len = strlen(uri);
+1 -18
View File
@@ -122,24 +122,7 @@ extern struct pal_linux_state {
#define PRESET_PAGESIZE (1 << 12)
#define DEFAULT_BACKLOG 2048
static inline int HOST_FLAGS (int alloc_type, int prot)
{
return ((alloc_type & PAL_ALLOC_RESERVE) ? MAP_NORESERVE|MAP_UNINITIALIZED : 0) |
((prot & PAL_PROT_WRITECOPY) ? MAP_PRIVATE : MAP_SHARED);
}
static inline int HOST_PROT (int prot)
{
return prot & (PAL_PROT_READ|PAL_PROT_WRITE|PAL_PROT_EXEC);
}
static inline int HOST_ACCESS (int access)
{
return (access & (PAL_ACCESS_RDONLY|PAL_ACCESS_WRONLY|PAL_ACCESS_RDWR)) |
((access & PAL_ACCESS_APPEND) ? O_APPEND|O_WRONLY : 0);
}
#define DEFAULT_BACKLOG 2048
int clone (int (*__fn) (void * __arg), void * __child_stack,
int __flags, const void * __arg, ...);
+2 -2
View File
@@ -226,8 +226,8 @@ int _DkGetCPUInfo (PAL_CPU_INFO * info);
/* Internal DK calls, in case any of the internal routines needs to use them */
/* DkStream calls */
int _DkStreamOpen (PAL_HANDLE * handle, const char * uri,
int access, int share, int create, int options);
int _DkStreamOpen(PAL_HANDLE* handle, const char* uri, int access, int share, int create,
int options);
int _DkStreamDelete (PAL_HANDLE handle, int access);
int64_t _DkStreamRead (PAL_HANDLE handle, uint64_t offset, uint64_t count,
void * buf, char * addr, int addrlen);