diff --git a/LibOS/shim/include/shim_handle.h b/LibOS/shim/include/shim_handle.h index 1ccf97f0..b6592dc1 100644 --- a/LibOS/shim/include/shim_handle.h +++ b/LibOS/shim/include/shim_handle.h @@ -278,7 +278,6 @@ struct shim_sem_handle { }; struct shim_futex_handle { - PAL_HANDLE event; unsigned int * uaddr; struct list_head waiters; struct shim_vma * vma; @@ -369,7 +368,9 @@ struct shim_fd_handle { struct shim_handle * handle; }; -#define MAX_FDS 1024 +#define MAX_MAX_FDS (65536) +#define DEFAULT_MAX_FDS (1024) +extern unsigned int max_fds; struct shim_handle_map { /* the top of created file descriptors */ diff --git a/LibOS/shim/include/shim_table.h b/LibOS/shim/include/shim_table.h index 33cf4484..210508ae 100644 --- a/LibOS/shim/include/shim_table.h +++ b/LibOS/shim/include/shim_table.h @@ -409,6 +409,8 @@ int shim_do_unlink (const char * file); int shim_do_readlink (const char * file, char * buf, int bufsize); int shim_do_chmod (const char * filename, mode_t mode); int shim_do_fchmod (int fd, mode_t mode); +int shim_do_chown (const char * filename, uid_t user, gid_t group); +int shim_do_fchown (int fd, uid_t user, gid_t group); mode_t shim_do_umask (mode_t mask); int shim_do_gettimeofday (struct __kernel_timeval * tv, struct __kernel_timezone * tz); @@ -425,6 +427,7 @@ pid_t shim_do_getpgrp (void); int shim_do_setsid (void); int shim_do_getpgid (pid_t pid); int shim_do_getsid (pid_t pid); +int shim_do_sigsuspend (const __sigset_t * mask); void * shim_do_arch_prctl (int code, void * addr); int shim_do_setrlimit (int resource, struct __kernel_rlimit * rlim); int shim_do_chroot (const char * filename); @@ -454,6 +457,8 @@ int shim_do_unlinkat (int dfd, const char * pathname, int flag); int shim_do_renameat (int olddfd, const char * pathname, int newdfd, const char * newname); int shim_do_fchmodat (int dfd, const char * filename, mode_t mode); +int shim_do_fchownat (int dfd, const char * filename, uid_t user, gid_t group, + int flags); int shim_do_faccessat (int dfd, const char * filename, mode_t mode); int shim_do_pselect6 (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, const struct __kernel_timespec * tsp, diff --git a/LibOS/shim/include/shim_thread.h b/LibOS/shim/include/shim_thread.h index c1c33561..c64b7b80 100644 --- a/LibOS/shim/include/shim_thread.h +++ b/LibOS/shim/include/shim_thread.h @@ -57,6 +57,7 @@ struct shim_thread { struct shim_signal_handle signal_handles[NUM_SIGS]; struct shim_atomic has_signal; struct shim_signal_log * signal_logs; + bool suspend_on_signal; /* futex robust list */ void * robust_list; @@ -201,7 +202,8 @@ static inline void thread_setwait (struct shim_thread ** queue, thread = get_cur_thread(); get_thread(thread); DkEventClear(thread->scheduler_event); - *queue = thread; + if (queue) + *queue = thread; } static inline void thread_sleep (void) diff --git a/LibOS/shim/include/shim_utils.h b/LibOS/shim/include/shim_utils.h index 67b630c6..b80f8376 100644 --- a/LibOS/shim/include/shim_utils.h +++ b/LibOS/shim/include/shim_utils.h @@ -235,7 +235,7 @@ int create_handle (const char * prefix, char * path, size_t size, /* Asynchronous event support */ int init_async (void); -int install_async_event (unsigned long time, +int install_async_event (PAL_HANDLE object, unsigned long time, void (*callback) (IDTYPE caller, void * arg), void * arg); int create_async_helper (void); diff --git a/LibOS/shim/src/bookkeep/shim_handle.c b/LibOS/shim/src/bookkeep/shim_handle.c index ca90d4e4..e95dfaf4 100644 --- a/LibOS/shim/src/bookkeep/shim_handle.c +++ b/LibOS/shim/src/bookkeep/shim_handle.c @@ -627,12 +627,12 @@ static struct shim_handle_map * __enlarge_handle_map size_t copy_size = sizeof(struct shim_fd_handle *) * map->fd_size; map->fd_size = size; - if (old_map && copy_size) - memcpy(map->map, old_map, copy_size); - memset(&map->map[map->fd_size], 0, - (sizeof(struct shim_fd_handle *) * size) - copy_size); - if (old_map) + memset(map->map, 0, sizeof(struct shim_fd_handle *) * size); + if (old_map) { + if (copy_size) + memcpy(map->map, old_map, copy_size); free(old_map); + } return map; } diff --git a/LibOS/shim/src/bookkeep/shim_signal.c b/LibOS/shim/src/bookkeep/shim_signal.c index 821a4a41..ca3dc8f6 100644 --- a/LibOS/shim/src/bookkeep/shim_signal.c +++ b/LibOS/shim/src/bookkeep/shim_signal.c @@ -124,7 +124,6 @@ void __store_context (shim_tcb_t * tcb, PAL_CONTEXT * pal_context, context->uc_mcontext.gregs[REG_RDX] = regs->rdx; context->uc_mcontext.gregs[REG_RSI] = regs->rsi; context->uc_mcontext.gregs[REG_RDI] = regs->rdi; - context->uc_mcontext.gregs[REG_R12] = regs->r12; context->uc_mcontext.gregs[REG_RBX] = regs->rbx; context->uc_mcontext.gregs[REG_RBP] = regs->rbp; } @@ -249,7 +248,7 @@ internal: } if (context) - debug("memory fault at %p (IP = %p)\n", arg, context->IP); + pal_printf("memory fault at %p (IP = %p)\n", arg, context->IP); struct shim_vma * vma = NULL; if (!lookup_supervma((void *) arg, 0, &vma)) { diff --git a/LibOS/shim/src/bookkeep/shim_thread.c b/LibOS/shim/src/bookkeep/shim_thread.c index 7a7c5c45..b10cc813 100644 --- a/LibOS/shim/src/bookkeep/shim_thread.c +++ b/LibOS/shim/src/bookkeep/shim_thread.c @@ -221,9 +221,9 @@ struct shim_thread * get_new_thread (IDTYPE new_tid) NUM_SIGS); thread->vmid = cur_process.vmid; create_lock(thread->lock); - thread->scheduler_event = DkNotificationEventCreate(1); - thread->exit_event = DkNotificationEventCreate(0); - thread->child_exit_event = DkNotificationEventCreate(0); + thread->scheduler_event = DkNotificationEventCreate(PAL_TRUE); + thread->exit_event = DkNotificationEventCreate(PAL_FALSE); + thread->child_exit_event = DkNotificationEventCreate(PAL_FALSE); return thread; } @@ -240,7 +240,7 @@ struct shim_thread * get_new_internal_thread (void) thread->tid = new_tid; thread->in_vm = thread->is_alive = true; create_lock(thread->lock); - thread->exit_event = DkNotificationEventCreate(0); + thread->exit_event = DkNotificationEventCreate(PAL_FALSE); return thread; } @@ -278,7 +278,7 @@ struct shim_simple_thread * get_new_simple_thread (void) INIT_LIST_HEAD(&thread->list); create_lock(thread->lock); - thread->exit_event = DkNotificationEventCreate(0); + thread->exit_event = DkNotificationEventCreate(PAL_FALSE); return thread; } @@ -625,9 +625,9 @@ BEGIN_RS_FUNC(thread) CP_REBASE(thread->signal_handles); create_lock(thread->lock); - thread->scheduler_event = DkNotificationEventCreate(1); - thread->exit_event = DkNotificationEventCreate(0); - thread->child_exit_event = DkNotificationEventCreate(0); + thread->scheduler_event = DkNotificationEventCreate(PAL_TRUE); + thread->exit_event = DkNotificationEventCreate(PAL_FALSE); + thread->child_exit_event = DkNotificationEventCreate(PAL_FALSE); add_thread(thread); diff --git a/LibOS/shim/src/fs/proc/thread.c b/LibOS/shim/src/fs/proc/thread.c index 7aecb4bd..57cc571f 100644 --- a/LibOS/shim/src/fs/proc/thread.c +++ b/LibOS/shim/src/fs/proc/thread.c @@ -242,7 +242,7 @@ static int parse_thread_fd (const char * name, const char ** rest, if (*p < '0' || *p > '9') return -ENOENT; fd = fd * 10 + *p - '0'; - if (fd >= MAX_FDS) + if (fd >= max_fds) return -ENOENT; } diff --git a/LibOS/shim/src/shim_async.c b/LibOS/shim/src/shim_async.c index 7d86492b..a7444295 100644 --- a/LibOS/shim/src/shim_async.c +++ b/LibOS/shim/src/shim_async.c @@ -35,6 +35,7 @@ struct async_event { struct list_head list; void (*callback) (IDTYPE caller, void * arg); void * arg; + PAL_HANDLE object; unsigned long install_time; unsigned long expire_time; }; @@ -43,13 +44,13 @@ static LIST_HEAD(async_list); enum { HELPER_NOTALIVE, HELPER_ALIVE }; -static struct shim_atomic async_helper_state; -static struct shim_thread * async_helper_thread; -static PAL_HANDLE async_helper_event; +static struct shim_atomic async_helper_state; +static struct shim_thread * async_helper_thread; +static AEVENTTYPE async_helper_event; static LOCKTYPE async_helper_lock; -int install_async_event (unsigned long time, +int install_async_event (PAL_HANDLE object, unsigned long time, void (*callback) (IDTYPE caller, void * arg), void * arg) { @@ -63,8 +64,9 @@ int install_async_event (unsigned long time, event->callback = callback; event->arg = arg; event->caller = get_cur_tid(); - event->install_time = install_time; - event->expire_time = install_time + time; + event->object = object; + event->install_time = time ? install_time : 0; + event->expire_time = time ? install_time + time : 0; lock(async_helper_lock); @@ -72,7 +74,7 @@ int install_async_event (unsigned long time, struct list_head * prev = &async_list; list_for_each_entry(tmp, &async_list, list) { - if (tmp->expire_time > event->expire_time) + if (event->expire_time && tmp->expire_time > event->expire_time) break; prev = &tmp->list; } @@ -85,7 +87,7 @@ int install_async_event (unsigned long time, if (atomic_read(&async_helper_state) == HELPER_NOTALIVE) create_async_helper(); - DkEventSet(async_helper_event); + set_event(&async_helper_event, 1); return 0; } @@ -93,7 +95,7 @@ int init_async (void) { atomic_set(&async_helper_state, HELPER_NOTALIVE); create_lock(async_helper_lock); - async_helper_event = DkSynchronizationEventCreate(0); + create_event(&async_helper_event); return 0; } @@ -112,8 +114,10 @@ static void shim_async_helper (void * arg) debug("set tcb to %p\n", &tcb); lock(async_helper_lock); + bool notme = (self != async_helper_thread); + unlock(async_helper_lock); - if (self != async_helper_thread) { + if (notme) { put_thread(self); DkThreadExit(); return; @@ -126,37 +130,102 @@ static void shim_async_helper (void * arg) swap any stack */ unsigned long idle_cycles = 0; unsigned long latest_time; - struct async_event * next_event, * finished_event = NULL; + struct async_event * next_event = NULL; + PAL_HANDLE async_event_handle = event_handle(&async_helper_event); - goto update; + int object_list_size = 32, object_num; + PAL_HANDLE polled; + PAL_HANDLE * local_objects = + malloc(sizeof(PAL_HANDLE) * (1 + object_list_size)); + local_objects[0] = async_event_handle; + + goto update_status; while (atomic_read(&async_helper_state) == HELPER_ALIVE) { + unsigned long sleep_time; + if (next_event) { + sleep_time = next_event->expire_time - latest_time; + idle_cycles = 0; + } else if (object_num) { + sleep_time = NO_TIMEOUT; + idle_cycles = 0; + } else { + sleep_time = IDLE_SLEEP_TIME; + idle_cycles++; + } + + polled = DkObjectsWaitAny(object_num + 1, local_objects, sleep_time); + + if (!polled) { + if (next_event) { + debug("async event trigger at %llu\n", + next_event->expire_time); + + next_event->callback(next_event->caller, next_event->arg); + + lock(async_helper_lock); + list_del(&next_event->list); + free(next_event); + goto update_list; + } + continue; + } + + if (polled == async_event_handle) { + clear_event(&async_helper_event); +update_status: + latest_time = DkSystemTimeQuery(); + if (atomic_read(&async_helper_state) == HELPER_NOTALIVE) { + break; + } else { + lock(async_helper_lock); + goto update_list; + } + } + + struct async_event * tmp, * n; + lock(async_helper_lock); -update: - latest_time = DkSystemTimeQuery(); + + list_for_each_entry_safe(tmp, n, &async_list, list) { + if (tmp->object == polled) { + debug("async event trigger at %llu\n", + latest_time); + unlock(async_helper_lock); + tmp->callback(tmp->caller, tmp->arg); + lock(async_helper_lock); + break; + } + } + +update_list: next_event = NULL; + object_num = 0; if (!list_empty(&async_list)) { - if (finished_event) { - list_del(&finished_event->list); - free(finished_event); - finished_event = NULL; - } - struct async_event * tmp, * n; list_for_each_entry_safe(tmp, n, &async_list, list) { + if (tmp->object) { + local_objects[object_num + 1] = tmp->object; + object_num++; + } + + if (!tmp->install_time) + continue; + if (tmp->expire_time > latest_time) { next_event = tmp; break; } - debug("async event trigger at %llu (expect expiring at %llu)\n", + debug("async event trigger at %llu (expire at %llu)\n", latest_time, tmp->expire_time); - list_del(&tmp->list); + unlock(async_helper_lock); tmp->callback(tmp->caller, tmp->arg); free(tmp); + lock(async_helper_lock); } idle_cycles = 0; @@ -164,27 +233,12 @@ update: unlock(async_helper_lock); - if (!next_event && idle_cycles++ == MAX_IDLE_CYCLES) { + if (idle_cycles++ == MAX_IDLE_CYCLES) { debug("async helper thread reach helper cycle\n"); /* walking away, if someone is issueing an event, they have to create another thread */ break; } - - unsigned long sleep_time = next_event ? - next_event->expire_time - latest_time : - IDLE_SLEEP_TIME; - - PAL_HANDLE notify = DkObjectsWaitAny(1, &async_helper_event, - sleep_time); - - /* if we are not waken up by someone, the waiting has finished */ - if (!notify && next_event) { - debug("async event trigger at %llu\n", next_event->expire_time); - - finished_event = next_event; - next_event->callback(next_event->caller, next_event->arg); - } } atomic_set(&async_helper_state, HELPER_NOTALIVE); @@ -245,6 +299,6 @@ int terminate_async_helper (void) lock(async_helper_lock); atomic_xchg(&async_helper_state, HELPER_NOTALIVE); unlock(async_helper_lock); - DkEventSet(async_helper_event); + set_event(&async_helper_event, 1); return 0; } diff --git a/LibOS/shim/src/shim_checkpoint.c b/LibOS/shim/src/shim_checkpoint.c index 5567e5d2..d46a14b8 100644 --- a/LibOS/shim/src/shim_checkpoint.c +++ b/LibOS/shim/src/shim_checkpoint.c @@ -1181,6 +1181,8 @@ void restore_context (struct shim_context * context) "popq %%r14\r\n" "popq %%r13\r\n" "popq %%r12\r\n" + "popq %%r11\r\n" + "popq %%r10\r\n" "popq %%r9\r\n" "popq %%r8\r\n" "popq %%rcx\r\n" diff --git a/LibOS/shim/src/shim_init.c b/LibOS/shim/src/shim_init.c index 9de92fd5..62c60d12 100644 --- a/LibOS/shim/src/shim_init.c +++ b/LibOS/shim/src/shim_init.c @@ -723,7 +723,7 @@ int shim_init (int argc, void * args, void ** return_stack) if (cpaddr) { restore: - thread_start_event = DkNotificationEventCreate(0); + thread_start_event = DkNotificationEventCreate(PAL_FALSE); RUN_INIT(restore_checkpoint, &hdr.checkpoint.hdr, &hdr.checkpoint.mem, (ptr_t) cpaddr, 0); diff --git a/LibOS/shim/src/shim_parser.c b/LibOS/shim/src/shim_parser.c index e36c27de..77cd0556 100644 --- a/LibOS/shim/src/shim_parser.c +++ b/LibOS/shim/src/shim_parser.c @@ -216,7 +216,7 @@ struct parser_table { { .slow = 0, .parser = { NULL } }, /* rt_sigpending */ { .slow = 0, .parser = { NULL } }, /* rt_sigtimedwait */ { .slow = 0, .parser = { NULL } }, /* rt_sigqueueinfo */ - { .slow = 0, .parser = { NULL } }, /* rt_sigsuspend */ + { .slow = 1, .parser = { NULL } }, /* rt_sigsuspend */ { .slow = 0, .parser = { NULL } }, /* sigaltstack */ { .slow = 0, .parser = { NULL } }, /* utime */ { .slow = 0, .parser = { NULL } }, /* mknod */ @@ -915,9 +915,15 @@ static void parse_futexop (const char * type, va_list * ap) case FUTEX_WAIT: PUTS("FUTEX_WAIT"); break; + case FUTEX_WAIT_BITSET: + PUTS("FUTEX_WAIT_BITSET"); + break; case FUTEX_WAKE: PUTS("FUTEX_WAKE"); break; + case FUTEX_WAKE_BITSET: + PUTS("FUTEX_WAKE_BITSET"); + break; case FUTEX_FD: PUTS("FUTEX_FD"); break; diff --git a/LibOS/shim/src/shim_syscalls.c b/LibOS/shim/src/shim_syscalls.c index e49c9b2f..db10a375 100644 --- a/LibOS/shim/src/shim_syscalls.c +++ b/LibOS/shim/src/shim_syscalls.c @@ -476,10 +476,10 @@ DEFINE_SHIM_SYSCALL (chmod, 2, shim_do_chmod, int, const char *, filename, DEFINE_SHIM_SYSCALL (fchmod, 2, shim_do_fchmod, int, int, fd, mode_t, mode) -SHIM_SYSCALL_PASSTHROUGH (chown, 3, int, const char *, filename, - uid_t, user, gid_t, group) +DEFINE_SHIM_SYSCALL (chown, 3, shim_do_chown, int, const char *, filename, + uid_t, user, gid_t, group) -SHIM_SYSCALL_PASSTHROUGH (fchown, 3, int, int, fd, uid_t, user, gid_t, group) +DEFINE_SHIM_SYSCALL (fchown, 3, shim_do_fchown, int, int, fd, uid_t, user, gid_t, group) SHIM_SYSCALL_PASSTHROUGH (lchown, 3, int, const char *, filename, uid_t, user, gid_t, group) @@ -588,7 +588,7 @@ SHIM_SYSCALL_PASSTHROUGH (rt_sigtimedwait, 4, int, const __sigset_t *, uthese, SHIM_SYSCALL_PASSTHROUGH (rt_sigqueueinfo, 3, int, int, pid, int, sig, siginfo_t *, uinfo) -SHIM_SYSCALL_PASSTHROUGH (rt_sigsuspend, 1, int, const __sigset_t *, mask) +DEFINE_SHIM_SYSCALL (rt_sigsuspend, 1, shim_do_sigsuspend, int, const __sigset_t *, mask) SHIM_SYSCALL_PASSTHROUGH (sigaltstack, 2, int, const stack_t *, ss, stack_t *, oss) @@ -1012,8 +1012,8 @@ DEFINE_SHIM_SYSCALL (mkdirat, 3, shim_do_mkdirat, int, int, dfd, SHIM_SYSCALL_PASSTHROUGH (mknodat, 4, int, int, dfd, const char *, filename, int, mode, unsigned, dev) -SHIM_SYSCALL_PASSTHROUGH (fchownat, 5, int, int, dfd, const char *, filename, - uid_t, user, gid_t, group, int, flag) +DEFINE_SHIM_SYSCALL (fchownat, 5, shim_do_fchownat, int, int, dfd, + const char *, filename, uid_t, user, gid_t, group, int, flag) SHIM_SYSCALL_PASSTHROUGH (futimesat, 3, int, int, dfd, const char *, filename, struct timeval *, utimes) diff --git a/LibOS/shim/src/sys/shim_alarm.c b/LibOS/shim/src/sys/shim_alarm.c index 9e6e88cc..19ffd11d 100644 --- a/LibOS/shim/src/sys/shim_alarm.c +++ b/LibOS/shim/src/sys/shim_alarm.c @@ -1,139 +1,138 @@ -/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */ -/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */ - -/* Copyright (C) 2014 OSCAR lab, Stony Brook University - 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* - * shim_alarm.c - * - * Implementation of system call "alarm", "setitmer" and "getitimer". - */ - -#include -#include -#include -#include -#include - -void signal_alarm (IDTYPE target, void * arg) -{ - debug("alarm goes off, signaling thread %u\n", target); - - struct shim_thread * thread = lookup_thread(target); - if (!thread) - return; - - append_signal(thread, SIGALRM, NULL, true); -} - -int shim_do_alarm (unsigned int seconds) -{ - return install_async_event(seconds * 1000000, - &signal_alarm, - NULL); -} - -static struct { - unsigned long timeout; - unsigned long reset; -} real_itimer; - -void signal_itimer (IDTYPE target, void * arg) -{ - master_lock(); - - if (real_itimer.timeout != (unsigned long) arg) { - master_unlock(); - return; - } - - real_itimer.timeout += real_itimer.reset; - real_itimer.reset = 0; - master_unlock(); -} - -#ifndef ITIMER_REAL -# define ITIMER_REAL 0 -#endif - -int shim_do_setitimer (int which, struct __kernel_itimerval * value, - struct __kernel_itimerval * ovalue) -{ - if (which != ITIMER_REAL) - return -ENOSYS; - - if (!value) - return -EFAULT; - - unsigned long setup_time = DkSystemTimeQuery(); - - unsigned long next_value = value->it_value.tv_sec * 1000000 - + value->it_value.tv_usec; - unsigned long next_reset = value->it_interval.tv_sec * 1000000 - + value->it_interval.tv_usec; - - master_lock(); - - unsigned long current_timeout = real_itimer.timeout > setup_time ? - real_itimer.timeout - setup_time : 0; - unsigned long current_reset = real_itimer.reset; - - int ret = install_async_event(next_value, &signal_itimer, - (void *) (setup_time + next_value)); - - if (ret < 0) { - master_unlock(); - return ret; - } - - real_itimer.timeout = setup_time + next_value; - real_itimer.reset = next_reset; - - master_unlock(); - - if (ovalue) { - ovalue->it_interval.tv_sec = current_reset / 1000000; - ovalue->it_interval.tv_usec = current_reset % 1000000; - ovalue->it_value.tv_sec = current_timeout / 1000000; - ovalue->it_value.tv_usec = current_timeout % 1000000; - } - - return 0; -} - -int shim_do_getitimer (int which, struct __kernel_itimerval * value) -{ - if (which != ITIMER_REAL) - return -ENOSYS; - - if (!value) - return -EFAULT; - - unsigned long setup_time = DkSystemTimeQuery(); - - master_lock(); - unsigned long current_timeout = real_itimer.timeout > setup_time ? - real_itimer.timeout - setup_time : 0; - unsigned long current_reset = real_itimer.reset; - master_unlock(); - - value->it_interval.tv_sec = current_reset / 1000000; - value->it_interval.tv_usec = current_reset % 1000000; - value->it_value.tv_sec = current_timeout / 1000000; - value->it_value.tv_usec = current_timeout % 1000000; - return 0; -} +/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */ +/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */ + +/* Copyright (C) 2014 OSCAR lab, Stony Brook University + 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 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* + * shim_alarm.c + * + * Implementation of system call "alarm", "setitmer" and "getitimer". + */ + +#include +#include +#include +#include +#include + +void signal_alarm (IDTYPE target, void * arg) +{ + debug("alarm goes off, signaling thread %u\n", target); + + struct shim_thread * thread = lookup_thread(target); + if (!thread) + return; + + append_signal(thread, SIGALRM, NULL, true); +} + +int shim_do_alarm (unsigned int seconds) +{ + uint64_t usecs = 1000000ULL * seconds; + return install_async_event(NULL, usecs, &signal_alarm, NULL); +} + +static struct { + unsigned long timeout; + unsigned long reset; +} real_itimer; + +void signal_itimer (IDTYPE target, void * arg) +{ + master_lock(); + + if (real_itimer.timeout != (unsigned long) arg) { + master_unlock(); + return; + } + + real_itimer.timeout += real_itimer.reset; + real_itimer.reset = 0; + master_unlock(); +} + +#ifndef ITIMER_REAL +# define ITIMER_REAL 0 +#endif + +int shim_do_setitimer (int which, struct __kernel_itimerval * value, + struct __kernel_itimerval * ovalue) +{ + if (which != ITIMER_REAL) + return -ENOSYS; + + if (!value) + return -EFAULT; + + unsigned long setup_time = DkSystemTimeQuery(); + + unsigned long next_value = value->it_value.tv_sec * 1000000 + + value->it_value.tv_usec; + unsigned long next_reset = value->it_interval.tv_sec * 1000000 + + value->it_interval.tv_usec; + + master_lock(); + + unsigned long current_timeout = real_itimer.timeout > setup_time ? + real_itimer.timeout - setup_time : 0; + unsigned long current_reset = real_itimer.reset; + + int ret = install_async_event(NULL, next_value, &signal_itimer, + (void *) (setup_time + next_value)); + + if (ret < 0) { + master_unlock(); + return ret; + } + + real_itimer.timeout = setup_time + next_value; + real_itimer.reset = next_reset; + + master_unlock(); + + if (ovalue) { + ovalue->it_interval.tv_sec = current_reset / 1000000; + ovalue->it_interval.tv_usec = current_reset % 1000000; + ovalue->it_value.tv_sec = current_timeout / 1000000; + ovalue->it_value.tv_usec = current_timeout % 1000000; + } + + return 0; +} + +int shim_do_getitimer (int which, struct __kernel_itimerval * value) +{ + if (which != ITIMER_REAL) + return -ENOSYS; + + if (!value) + return -EFAULT; + + unsigned long setup_time = DkSystemTimeQuery(); + + master_lock(); + unsigned long current_timeout = real_itimer.timeout > setup_time ? + real_itimer.timeout - setup_time : 0; + unsigned long current_reset = real_itimer.reset; + master_unlock(); + + value->it_interval.tv_sec = current_reset / 1000000; + value->it_interval.tv_usec = current_reset % 1000000; + value->it_value.tv_sec = current_timeout / 1000000; + value->it_value.tv_usec = current_timeout % 1000000; + return 0; +} diff --git a/LibOS/shim/src/sys/shim_clone.c b/LibOS/shim/src/sys/shim_clone.c index 856300a8..ca0d2d41 100644 --- a/LibOS/shim/src/sys/shim_clone.c +++ b/LibOS/shim/src/sys/shim_clone.c @@ -285,13 +285,13 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr, struct clone_args * new_args = __alloca(sizeof(struct clone_args)); memset(new_args, 0, sizeof(struct clone_args)); - new_args->create_event = DkNotificationEventCreate(0); + new_args->create_event = DkNotificationEventCreate(PAL_FALSE); if (!new_args->create_event) { ret = -PAL_ERRNO; goto clone_thread_failed; } - new_args->initialize_event = DkNotificationEventCreate(0); + new_args->initialize_event = DkNotificationEventCreate(PAL_FALSE); if (!new_args->initialize_event) { ret = -PAL_ERRNO; goto clone_thread_failed; diff --git a/LibOS/shim/src/sys/shim_fs.c b/LibOS/shim/src/sys/shim_fs.c index 25813824..284416bb 100644 --- a/LibOS/shim/src/sys/shim_fs.c +++ b/LibOS/shim/src/sys/shim_fs.c @@ -267,6 +267,64 @@ out: return ret; } +int shim_do_chown (const char * path, uid_t uid, gid_t gid) +{ + struct shim_dentry * dent = NULL; + int ret = 0; + + if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent)) < 0) + return ret; + + /* do nothing*/ + +out: + put_dentry(dent); + return ret; +} + +int shim_do_fchownat (int dfd, const char * filename, uid_t uid, gid_t gid, + int flags) +{ + if (!filename) + return -EINVAL; + + if (*filename == '/') + return shim_do_chown(filename, uid, gid); + + struct shim_dentry * dir = NULL, * dent = NULL; + int ret = 0; + + if ((ret = path_startat(dfd, &dir)) < 0) + return ret; + + if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent)) < 0) + goto out; + + /* do nothing */ + +out_dent: + put_dentry(dent); +out: + put_dentry(dir); + return ret; +} + +int shim_do_fchown (int fd, uid_t uid, gid_t gid) +{ + struct shim_handle * hdl = get_fd_handle(fd, NULL, NULL); + if (!hdl) + return -EBADF; + + struct shim_dentry * dent = hdl->dentry; + int ret = 0; + + /* do nothing */ + +out: + put_handle(hdl); + return ret; +} + #define MAP_SIZE (allocsize * 4) #define BUF_SIZE (2048) diff --git a/LibOS/shim/src/sys/shim_futex.c b/LibOS/shim/src/sys/shim_futex.c index 635e1c8f..2973e39b 100644 --- a/LibOS/shim/src/sys/shim_futex.c +++ b/LibOS/shim/src/sys/shim_futex.c @@ -45,6 +45,7 @@ struct futex_waiter { struct shim_thread * thread; + uint32_t bitset; struct list_head list; }; @@ -54,8 +55,11 @@ static LOCKTYPE futex_list_lock; int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime, unsigned int * uaddr2, int val3) { - struct shim_futex_handle * tmp = NULL, * futex = NULL; - struct shim_handle * hdl; + struct shim_futex_handle * tmp = NULL, * futex = NULL, * futex2 = NULL; + struct shim_handle * hdl = NULL, * hdl2 = NULL; + uint32_t futex_op = (op & FUTEX_CMD_MASK); + + uint32_t val2 = 0; int ret = 0; if (!uaddr || ((uintptr_t) uaddr % sizeof(unsigned int))) @@ -88,28 +92,118 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime, list_add_tail(&futex->list, &futex_list); } + if (futex_op == FUTEX_WAKE_OP || futex_op == FUTEX_REQUEUE) { + list_for_each_entry(tmp, &futex_list, list) + if (tmp->uaddr == uaddr2) { + futex2 = tmp; + break; + } + + if (futex2) { + hdl2 = container_of(futex2, struct shim_handle, info.futex); + get_handle(hdl2); + } else { + if (!(hdl2 = get_new_handle())) { + unlock(futex_list_lock); + return -ENOMEM; + } + + hdl2->type = TYPE_FUTEX; + futex2 = &hdl2->info.futex; + futex2->uaddr = uaddr2; + get_handle(hdl2); + INIT_LIST_HEAD(&futex2->waiters); + INIT_LIST_HEAD(&futex2->list); + list_add_tail(&futex2->list, &futex_list); + } + + val2 = (uint32_t)(uint64_t) utime; + } + unlock(futex_list_lock); lock(hdl->lock); - switch (op & FUTEX_CMD_MASK) { + switch (futex_op) { case FUTEX_WAIT: - debug("FUTEX_WAIT: %p (val = %d) vs %d\n", uaddr, *uaddr, val); - if (*uaddr != val) + case FUTEX_WAIT_BITSET: { + uint32_t bitset = (futex_op == FUTEX_WAIT_BITSET) ? val3 : + 0xffffffff; + debug("FUTEX_WAIT: %p (val = %d) vs %d mask = %08x\n", + uaddr, *uaddr, val, bitset); + + if (*uaddr != val) { + ret = -EAGAIN; break; + } struct futex_waiter waiter; thread_setwait(&waiter.thread, NULL); INIT_LIST_HEAD(&waiter.list); + waiter.bitset = (futex_op == FUTEX_WAIT_BITSET) ? val3 : 0xffffffff; list_add_tail(&waiter.list, &futex->waiters); unlock(hdl->lock); thread_sleep(); lock(hdl->lock); break; + } - case FUTEX_WAKE: { - debug("FUTEX_WAKE: %p (val = %d)\n", uaddr, *uaddr); - int cnt; + case FUTEX_WAKE: + case FUTEX_WAKE_BITSET: { + uint32_t bitset = (futex_op == FUTEX_WAKE_BITSET) ? val3 : + 0xffffffff; + debug("FUTEX_WAKE: %p (val = %d) count = %d mask = %08x\n", + uaddr, *uaddr, val, bitset); + int cnt, nwaken = 0; + for (cnt = 0 ; cnt < val ; cnt++) { + if (list_empty(&futex->waiters)) + break; + + struct futex_waiter * waiter = list_entry(futex->waiters.next, + struct futex_waiter, + list); + + if (!(bitset & waiter->bitset)) + continue; + + debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n", + waiter->thread->tid, uaddr, *uaddr); + list_del(&waiter->list); + thread_wakeup(waiter->thread); + nwaken++; + } + + ret = nwaken; + debug("FUTEX_WAKE done: %p (val = %d)\n", uaddr, *uaddr); + break; + } + + case FUTEX_WAKE_OP: { + assert(futex2); + int oldval = *(int *) uaddr2, newval, cmpval; + + newval = (val3 >> 12) & 0xfff; + switch ((val3 >> 28) & 0xf) { + case FUTEX_OP_SET: break; + case FUTEX_OP_ADD: newval = oldval + newval; break; + case FUTEX_OP_OR: newval = oldval | newval; break; + case FUTEX_OP_ANDN: newval = oldval & ~newval; break; + case FUTEX_OP_XOR: newval = oldval ^ newval; break; + } + + cmpval = val3 & 0xfff; + switch ((val3 >> 24) & 0xf) { + case FUTEX_OP_CMP_EQ: cmpval = (oldval == cmpval); break; + case FUTEX_OP_CMP_NE: cmpval = (oldval != cmpval); break; + case FUTEX_OP_CMP_LT: cmpval = (oldval < cmpval); break; + case FUTEX_OP_CMP_LE: cmpval = (oldval <= cmpval); break; + case FUTEX_OP_CMP_GT: cmpval = (oldval > cmpval); break; + case FUTEX_OP_CMP_GE: cmpval = (oldval >= cmpval); break; + } + + *(int *) uaddr2 = newval; + int cnt, nwaken = 0; + debug("FUTEX_WAKE: %p (val = %d) count = %d\n", uaddr, *uaddr, val); for (cnt = 0 ; cnt < val ; cnt++) { if (list_empty(&futex->waiters)) break; @@ -122,9 +216,32 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime, waiter->thread->tid, uaddr, *uaddr); list_del(&waiter->list); thread_wakeup(waiter->thread); + nwaken++; } - ret = cnt; - debug("FUTEX_WAKE done: %p (val = %d)\n", uaddr, *uaddr); + + if (cmpval) { + unlock(hdl->lock); + put_handle(hdl); + hdl = hdl2; + lock(hdl->lock); + debug("FUTEX_WAKE: %p (val = %d) count = %d\n", uaddr2, + *uaddr2, val2); + for (cnt = 0 ; cnt < val2 ; cnt++) { + if (list_empty(&futex2->waiters)) + break; + + struct futex_waiter * waiter = list_entry(futex2->waiters.next, + struct futex_waiter, + list); + + debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n", + waiter->thread->tid, uaddr2, *uaddr2); + list_del(&waiter->list); + thread_wakeup(waiter->thread); + nwaken++; + } + } + ret = nwaken; break; } @@ -135,38 +252,7 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime, } case FUTEX_REQUEUE: { - struct shim_futex_handle * futex2 = NULL; - struct shim_handle * hdl2; - - lock(futex_list_lock); - - list_for_each_entry(tmp, &futex_list, list) - if (tmp->uaddr == uaddr2) { - futex2 = tmp; - break; - } - - if (futex2) { - hdl2 = container_of(futex2, struct shim_handle, info.futex); - get_handle(hdl2); - } else { - if (!(hdl2 = get_new_handle())) { - unlock(futex_list_lock); - ret = -ENOMEM; - goto out; - } - - hdl2->type = TYPE_FUTEX; - futex2 = &hdl2->info.futex; - futex2->uaddr = uaddr2; - get_handle(hdl2); - INIT_LIST_HEAD(&futex2->waiters); - INIT_LIST_HEAD(&futex2->list); - list_add_tail(&futex2->list, &futex_list); - } - - unlock(futex_list_lock); - + assert(futex2); int cnt; for (cnt = 0 ; cnt < val ; cnt++) { if (list_empty(&futex->waiters)) @@ -181,14 +267,7 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime, } lock(hdl2->lock); - while (!list_empty(&futex->waiters)) { - struct futex_waiter * waiter = list_entry(futex->waiters.next, - struct futex_waiter, - list); - - list_del(&waiter->list); - list_add_tail(&waiter->list, &futex2->waiters); - } + list_splice_init(&futex->waiters, &futex2->waiters); unlock(hdl2->lock); put_handle(hdl2); ret = cnt; @@ -206,7 +285,6 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime, } unlock(hdl->lock); -out: put_handle(hdl); return ret; } diff --git a/LibOS/shim/src/sys/shim_getrlimit.c b/LibOS/shim/src/sys/shim_getrlimit.c index 92335082..1ae8c406 100644 --- a/LibOS/shim/src/sys/shim_getrlimit.c +++ b/LibOS/shim/src/sys/shim_getrlimit.c @@ -30,12 +30,14 @@ #include +unsigned int max_fds = DEFAULT_MAX_FDS; + int shim_do_getrlimit (int resource, struct __kernel_rlimit * rlim) { switch (resource) { case RLIMIT_NOFILE: - rlim->rlim_cur = MAX_FDS; - rlim->rlim_max = MAX_FDS; + rlim->rlim_cur = max_fds; + rlim->rlim_max = MAX_MAX_FDS; return 0; case RLIMIT_RSS: @@ -60,5 +62,18 @@ int shim_do_getrlimit (int resource, struct __kernel_rlimit * rlim) int shim_do_setrlimit (int resource, struct __kernel_rlimit * rlim) { - return -EPERM; + switch (resource) { + case RLIMIT_NOFILE: + if (rlim->rlim_cur > MAX_MAX_FDS) + return -EINVAL; + max_fds = rlim->rlim_cur; + return 0; + + case RLIMIT_STACK: + sys_stack_size = rlim->rlim_cur; + return 0; + + default: + return -ENOSYS; + } } diff --git a/LibOS/shim/src/sys/shim_ioctl.c b/LibOS/shim/src/sys/shim_ioctl.c index 487afa1e..d8e217c9 100644 --- a/LibOS/shim/src/sys/shim_ioctl.c +++ b/LibOS/shim/src/sys/shim_ioctl.c @@ -132,8 +132,6 @@ static int ioctl_termios (struct shim_handle * hdl, unsigned int cmd, case TIOCSSERIAL: /* 0x00005420 TIOCPKT const int * */ case TIOCPKT: - /* 0x00005421 FIONBIO const int * */ - case FIONBIO: /* 0x00005422 TIOCNOTTY void */ case TIOCNOTTY: /* 0x00005423 TIOCSETD const int * */ @@ -142,8 +140,6 @@ static int ioctl_termios (struct shim_handle * hdl, unsigned int cmd, case TIOCGETD: /* 0x00005425 TCSBRKP int */ case TCSBRKP: - /* 0x00005452 FIOASYNC const int * */ - case FIOASYNC: /* 0x00005453 TIOCSERCONFIG void */ case TIOCSERCONFIG: /* 0x00005454 TIOCSERGWILD int * */ @@ -294,6 +290,17 @@ static int ioctl_netdevice (struct shim_handle * hdl, unsigned int cmd, return -EAGAIN; } +void signal_io (IDTYPE target, void * arg) +{ + debug("detecting input, signaling thread %u\n", target); + + struct shim_thread * thread = lookup_thread(target); + if (!thread) + return; + + append_signal(thread, SIGIO, NULL, true); +} + int shim_do_ioctl (int fd, int cmd, unsigned long arg) { struct shim_handle * hdl = get_fd_handle(fd, NULL, NULL); @@ -334,13 +341,19 @@ int shim_do_ioctl (int fd, int cmd, unsigned long arg) case TIOCGSERIAL: case TIOCSSERIAL: case TIOCPKT: - case FIONBIO: case TIOCNOTTY: case TIOCSETD: case TIOCGETD: case TCSBRKP: ret = ioctl_termios(hdl, cmd, arg); break; + case FIONBIO: + if (hdl->fs && hdl->fs->fs_ops && + hdl->fs->fs_ops->setflags) + hdl->fs->fs_ops->setflags(hdl, hdl->flags | O_NONBLOCK); + hdl->flags |= O_NONBLOCK; + ret = 0; + break; case FIONCLEX: hdl->flags &= ~FD_CLOEXEC; ret = 0; @@ -350,6 +363,8 @@ int shim_do_ioctl (int fd, int cmd, unsigned long arg) ret = 0; break; case FIOASYNC: + ret = install_async_event(hdl->pal_handle, 0, &signal_io, NULL); + break; case TIOCSERCONFIG: case TIOCSERGWILD: case TIOCSERSWILD: diff --git a/LibOS/shim/src/sys/shim_migrate.c b/LibOS/shim/src/sys/shim_migrate.c index 2443f58c..7a93d41b 100644 --- a/LibOS/shim/src/sys/shim_migrate.c +++ b/LibOS/shim/src/sys/shim_migrate.c @@ -67,7 +67,7 @@ int create_checkpoint (const char * cpdir, IDTYPE * sid) INIT_LIST_HEAD(&cpsession->registered_threads); INIT_LIST_HEAD(&cpsession->list); - cpsession->finish_event = DkNotificationEventCreate(0); + cpsession->finish_event = DkNotificationEventCreate(PAL_FALSE); cpsession->cpfile = NULL; int len = strlen(cpdir); diff --git a/LibOS/shim/src/sys/shim_msgget.c b/LibOS/shim/src/sys/shim_msgget.c index db67d702..a5f16dd2 100644 --- a/LibOS/shim/src/sys/shim_msgget.c +++ b/LibOS/shim/src/sys/shim_msgget.c @@ -100,7 +100,7 @@ static int __add_msg_handle (unsigned long key, IDTYPE msqid, bool owned, msgq->owned = owned; msgq->deleted = false; msgq->currentsize = 0; - msgq->event = DkSynchronizationEventCreate(0); + msgq->event = DkSynchronizationEventCreate(PAL_FALSE); msgq->queue = malloc(MSG_QOBJ_SIZE * DEFAULT_MSG_QUEUE_SIZE); msgq->queuesize = DEFAULT_MSG_QUEUE_SIZE; diff --git a/LibOS/shim/src/sys/shim_poll.c b/LibOS/shim/src/sys/shim_poll.c index 33068dbb..3f174856 100644 --- a/LibOS/shim/src/sys/shim_poll.c +++ b/LibOS/shim/src/sys/shim_poll.c @@ -225,19 +225,20 @@ no_op: if (polled & FS_POLL_ER) { debug("fd %d known to have error\n", p->fd); p->flags |= KNOWN_R|KNOWN_W|RET_E; + do_r = do_w = false; } if ((polled & FS_POLL_RD)) { debug("fd %d known to be readable\n", p->fd); p->flags |= KNOWN_R|RET_R; + do_r = false; } if (polled & FS_POLL_WR) { debug("fd %d known to be writeable\n", p->fd); p->flags |= KNOWN_W|RET_W; + do_w = false; } - - do_r = do_w = false; } } diff --git a/LibOS/shim/src/sys/shim_semget.c b/LibOS/shim/src/sys/shim_semget.c index 7952c82e..cb3bc4bf 100644 --- a/LibOS/shim/src/sys/shim_semget.c +++ b/LibOS/shim/src/sys/shim_semget.c @@ -90,7 +90,7 @@ static int __add_sem_handle (unsigned long key, IDTYPE semid, tmp->semkey = key; tmp->semid = semid; tmp->owned = owned; - tmp->event = DkNotificationEventCreate(0); + tmp->event = DkNotificationEventCreate(PAL_FALSE); if (owned && nsems) { tmp->nsems = nsems; diff --git a/LibOS/shim/src/sys/shim_sigaction.c b/LibOS/shim/src/sys/shim_sigaction.c index 4628c467..984da38c 100644 --- a/LibOS/shim/src/sys/shim_sigaction.c +++ b/LibOS/shim/src/sys/shim_sigaction.c @@ -137,6 +137,30 @@ out: return err; } +int shim_do_sigsuspend (const __sigset_t * mask) +{ + __sigset_t * old, tmp; + struct shim_thread * cur = get_cur_thread(); + int err = 0; + + lock(cur->lock); + + old = get_sig_mask(cur); + memcpy(&tmp, old, sizeof(__sigset_t)); + old = &tmp; + + set_sig_mask(cur, mask); + cur->suspend_on_signal = true; + thread_setwait(NULL, NULL); + thread_sleep(); +out: + unlock(cur->lock); + set_sig_mask(cur, old); + + return err; + +} + struct walk_arg { struct shim_thread * current; IDTYPE sender; diff --git a/LibOS/shim/src/sys/shim_socket.c b/LibOS/shim/src/sys/shim_socket.c index 0150d896..7b5cf442 100644 --- a/LibOS/shim/src/sys/shim_socket.c +++ b/LibOS/shim/src/sys/shim_socket.c @@ -61,6 +61,8 @@ #define TCP_CONGESTION 13 /* Congestion control algorithm. */ #define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ +#define AF_UNSPEC 0 + #define SOCK_URI_SIZE 108 static int rebase_on_lo __attribute_migratable = -1; @@ -316,6 +318,28 @@ static inline void unix_copy_addr (struct sockaddr * saddr, memcpy(un->sun_path, path, size + 1); } +static bool inet_check_addr (int domain, struct sockaddr * addr, int addrlen) +{ + if (domain == AF_INET) { + if (addr->sa_family != AF_INET || + addrlen != sizeof(struct sockaddr_in)) + return false; + return true; + } + + if (domain == AF_INET6) { + if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6) + return false; + if (addrlen != ((addr->sa_family == AF_INET) ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6))) + return false; + return true; + } + + return false; +} + static int inet_copy_addr (int domain, struct sockaddr * saddr, const struct addr_inet * addr) { @@ -349,9 +373,18 @@ static void inet_save_addr (int domain, struct addr_inet * addr, } if (domain == AF_INET6) { - const struct sockaddr_in6 * in6 = (const struct sockaddr_in6 *) saddr; - addr->port = __ntohs(in6->sin6_port); - addr->addr.v6 = in6->sin6_addr; + if (saddr->sa_family == AF_INET) { + const struct sockaddr_in * in = (const struct sockaddr_in *) saddr; + addr->port = __ntohs(in->sin_port); + ((uint32_t *) &addr->addr.v6.s6_addr)[0] = 0; + ((uint32_t *) &addr->addr.v6.s6_addr)[1] = 0; + ((uint32_t *) &addr->addr.v6.s6_addr)[2] = 0xffff0000; + ((uint32_t *) &addr->addr.v6.s6_addr)[3] = in->sin_addr.s_addr; + } else { + const struct sockaddr_in6 * in6 = (const struct sockaddr_in6 *) saddr; + addr->port = __ntohs(in6->sin6_port); + addr->addr.v6 = in6->sin6_addr; + } return; } } @@ -451,12 +484,8 @@ int shim_do_bind (int sockfd, struct sockaddr * addr, socklen_t addrlen) sock->addr.un.dentry = dent; } else if (sock->domain == AF_INET || sock->domain == AF_INET6) { - - if (addrlen != ((sock->domain == AF_INET) ? sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6))) { + if (!inet_check_addr(sock->domain, addr, addrlen)) goto out; - } - inet_save_addr(sock->domain, &sock->addr.in.bind, addr); inet_rebase_port(false, sock->domain, &sock->addr.in.bind, true); } @@ -657,6 +686,18 @@ int shim_do_connect (int sockfd, struct sockaddr * addr, int addrlen) int ret = -EINVAL; if (state == SOCK_CONNECTED) { + if (addr->sa_family == AF_UNSPEC) { + sock->sock_state = SOCK_CREATED; + if (sock->sock_type == SOCK_STREAM && hdl->pal_handle) { + DkStreamDelete(hdl->pal_handle, 0); + DkObjectClose(hdl->pal_handle); + hdl->pal_handle = NULL; + } + debug("shim_connect: reconnect on a stream socket\n"); + ret = 0; + goto out; + } + debug("shim_connect: reconnect on a stream socket\n"); goto out; } @@ -702,14 +743,12 @@ int shim_do_connect (int sockfd, struct sockaddr * addr, int addrlen) hdl->pal_handle = NULL; } - if (sock->domain != AF_UNIX) { - if (addrlen != ((sock->domain == AF_INET) ? sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6))) - goto out; - - inet_save_addr(sock->domain, &sock->addr.in.conn, addr); - inet_rebase_port(false, sock->domain, &sock->addr.in.conn, false); - } + if (sock->domain != AF_UNIX) { + if (!inet_check_addr(sock->domain, addr, addrlen)) + goto out; + inet_save_addr(sock->domain, &sock->addr.in.conn, addr); + inet_rebase_port(false, sock->domain, &sock->addr.in.conn, false); + } sock->sock_state = (state == SOCK_BOUND) ? SOCK_BOUNDCONNECTED : SOCK_CONNECTED; diff --git a/LibOS/shim/src/syscallas.S b/LibOS/shim/src/syscallas.S index d5e4b446..9fa5e3a6 100644 --- a/LibOS/shim/src/syscallas.S +++ b/LibOS/shim/src/syscallas.S @@ -63,9 +63,9 @@ isdef: pushq %r15 movq %rax, %fs:(SHIM_TCB_OFFSET + 24) - leaq 8(%rbp), %rax + leaq 16(%rbp), %rax movq %rax, %fs:(SHIM_TCB_OFFSET + 32) - movq (%rbp), %rax + movq 8(%rbp), %rax movq %rax, %fs:(SHIM_TCB_OFFSET + 40) movq %rsp, %fs:(SHIM_TCB_OFFSET + 48) diff --git a/LibOS/shim/test/Makefile b/LibOS/shim/test/Makefile index 8e960845..172723f7 100644 --- a/LibOS/shim/test/Makefile +++ b/LibOS/shim/test/Makefile @@ -10,12 +10,11 @@ LIBCDIR = $(level)../../glibc-build CC = gcc CXX = g++ CFLAGS = -std=gnu99 -CFLAGS-debug = $(CFLAGS) -I$(PALDIR)/../include/pal -I$(PALDIR)/../lib +CFLAGS-debug = $(CFLAGS) -I$(SHIMDIR)/../include -I$(PALDIR)/../include/pal -I$(PALDIR)/../lib LDFLAGS = -LDFLAGS-debug = $(LDFLAGS) -L$(SHIMDIR) \ +LDFLAGS-debug = $(LDFLAGS) -L$(SHIMDIR) -L$(PALDIR) \ -Wl,-rpath-link=$(abspath $(SHIMDIR)) \ - -Wl,-rpath-link=$(abspath $(PALDIR)) \ - -lpal -lsysdb_debug + -Wl,-rpath-link=$(abspath $(PALDIR)) default: all include $(PALDIR)/Makefile.Test @@ -37,9 +36,11 @@ manifest_rules = \ -e 's:\$$(LIBCDIR):'$$RELDIR'$(LIBCDIR):g' \ $(extra_rules) +relative-to = $(shell python -c "import os.path; print os.path.relpath(\"$(abspath $2)\",\"$(abspath $1)\")") + %manifest: %manifest.template @echo [ $@ ] - RELDIR=$(filter-out ./,$(python -c "import os.path; print os.path.relpath($(abspath $(dir $@)) $(PWD))")) && \ + RELDIR=$(filter-out ./,$(call relative-to,$(dir $@),$(shell pwd))/) && \ sed $(manifest_rules) $< > $@ (grep -q '^#!' $@ && chmod +x $@) || true diff --git a/LibOS/shim/test/apps/lighttpd/Makefile b/LibOS/shim/test/apps/lighttpd/Makefile index 267b6f6f..416c4bd0 100644 --- a/LibOS/shim/test/apps/lighttpd/Makefile +++ b/LibOS/shim/test/apps/lighttpd/Makefile @@ -55,7 +55,7 @@ start-multithreaded-native-server: $(if $(CONF),$(CONF),lighttpd-multithreaded.conf) start-graphene-server: - $(PREFIX) ./lighttpd.manifest -D -m /lighttpd -f \ + $(PREFIX) ./lighttpd.manifest$(if $(SGX_RUN),.sgx,) -D -m /lighttpd -f \ $(if $(CONF),$(CONF),lighttpd.conf) start-multithreaded-graphene-server: diff --git a/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_proc.c b/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_proc.c index 35b17fca..ab80bb52 100644 --- a/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_proc.c +++ b/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_proc.c @@ -180,6 +180,15 @@ main(int ac, char **av) micro("Static Process fork+exit", get_n()); #else micro("Process fork+exit", get_n()); +#endif + } else if (!strcmp("fork-size", av[1])) { + size_t size = bytes(av[2]); + memset(malloc(size), 0, size); + BENCH(do_fork(), 0); +#ifdef STATIC + micro("Static Process fork+exit", get_n()); +#else + micro("Process fork+exit", get_n()); #endif } else if (!strcmp("dfork", av[1])) { BENCH(do_dfork(), 0); diff --git a/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_syscall.c b/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_syscall.c index c266c5b7..4e950c54 100644 --- a/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_syscall.c +++ b/LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_syscall.c @@ -33,6 +33,15 @@ do_read(int fd, char *s) } } +void +do_read_size(int fd, void * buf, size_t size, char *s) +{ + if (read(fd, buf, size) == -1) { + perror(s); + return; + } +} + void do_stat(char *s) { @@ -100,6 +109,18 @@ main(int ac, char **av) BENCH(do_read(fd, file), 0); micro("Simple read", get_n()); close(fd); + } else if (!strcmp("read-size", av[1])) { + size_t size = bytes(av[2]); + void * buf = malloc(size); + file = av[3] ? av[3] : "/dev/zero"; + fd = open(file, 0); + if (fd == -1) { + fprintf(stderr, "Read from %s: %s\n", file, strerror(errno)); + return(1); + } + BENCH(do_read_size(fd, buf, size, file), 0); + micro("Simple read", get_n()); + close(fd); } else if (!strcmp("stat", av[1])) { BENCH(do_stat(file), 0); micro("Simple stat", get_n()); diff --git a/LibOS/shim/test/apps/ltp/BLOCKED b/LibOS/shim/test/apps/ltp/BLOCKED new file mode 100644 index 00000000..eaf69a4f --- /dev/null +++ b/LibOS/shim/test/apps/ltp/BLOCKED @@ -0,0 +1,36 @@ +getresuid02 +getresuid03 +epoll-ltp +epoll_pwait01 +fork06 +fork12 +fork14 +getitimer02 +getresgid02 +getresgid03 +getrlimit02 +getrusage02 +gettimeofday01 +gettimeofday02 +kill02 +kill06 +kill08 +kill10 +kill12 +nosleep04 +nanosleep04 +pipe04 +pipe05 +pipe07 +process_vm_readv02 +process_vm_readv03 +process_vm01 -r +prot_hsymlinks +setitimer02 +set_robust_list01 +signal01 +trace05 +uname02 +waitpid04 +futex_wait01 +futex_wake02 diff --git a/LibOS/shim/test/apps/ltp/Makefile b/LibOS/shim/test/apps/ltp/Makefile new file mode 100644 index 00000000..f21c8baf --- /dev/null +++ b/LibOS/shim/test/apps/ltp/Makefile @@ -0,0 +1,36 @@ +SRCDIR = ltp-master +BUILDDIR = opt/ltp +TESTCASEDIR = $(BUILDDIR)/testcases/bin + +target = $(BUILDDIR)/bin/run_in_graphene.awk $(TESTCASEDIR)/pal_loader $(TESTCASEDIR)/manifest +exec_target = + +clean-extra = clean-build + +level = ../../ +include ../../Makefile + +master.zip: + wget https://github.com/linux-test-project/ltp/archive/master.zip + +$(SRCDIR)/configure: master.zip + unzip master.zip + cd $(SRCDIR) && make autotools + +$(BUILDDIR)/runltp: $(SRCDIR)/configure + cd $(SRCDIR) && ./configure + cd $(SRCDIR) && make all + cd $(SRCDIR) && make "DESTDIR=$(PWD)" SKIP_IDCHECK=1 install + patch -d $(dir $@) < runltp.patch + +$(BUILDDIR)/bin/run_in_graphene.awk: run_in_graphene.awk $(BUILDDIR)/runltp + cp -f $< $@ + +$(TESTCASEDIR)/pal_loader: $(BUILDDIR)/runltp + ln -sf $(call relative-to,$(dir $@),../pal_loader) $@ + +$(TESTCASEDIR)/manifest.template: manifest.template + cp -f $< $@ + +clean-build: + rm -rf $(BUILDDIR) diff --git a/LibOS/shim/test/apps/ltp/PASSED b/LibOS/shim/test/apps/ltp/PASSED new file mode 100644 index 00000000..42dd1818 --- /dev/null +++ b/LibOS/shim/test/apps/ltp/PASSED @@ -0,0 +1,290 @@ +Test,Subtest number +accept01,1 +accept01,2 +alarm01,1 +alarm02,1 +alarm02,2 +alarm02,3 +clone01,1 +clone03,1 +clone04,1 +clone06,1 +clone07,1 +close02,1 +confstr01,1 +confstr01,2 +confstr01,3 +confstr01,4 +confstr01,5 +confstr01,6 +confstr01,7 +confstr01,8 +confstr01,9 +confstr01,10 +confstr01,11 +confstr01,12 +confstr01,13 +confstr01,14 +confstr01,15 +confstr01,16 +confstr01,17 +confstr01,18 +confstr01,19 +fcntl13,6 +fork02,1 +fork03,1 +fork11,1 +fstat05,1 +getcontext01,1 +getdomainname01,1 +getdtablesize01,1 +getegid01,1 +geteuid01,1 +getgid01,1 +gethostbyname_r01,1 +gethostname01,1 +getitimer01,1 +getitimer01,3 +getitimer01,5 +getpagesize01,1 +getpeername01,1 +getpeername01,2 +getpgid01,1 +getpgid01,2 +getpgrp01,1 +getpid01,1 +getpid02,1 +getppid01,1 +getrlimit01,4 +getrlimit01,6 +getrlimit01,8 +getrlimit01,10 +getsid01,1 +getsockopt01,1 +getsockopt01,2 +gettid01,1 +getuid01,1 +kill03,1 +kill09,1 +listen01,1 +listen01,2 +memset01,1 +memset01,2 +memcmp1,1 +memcmp1,2 +memcpy1,1 +memcpy1,2 +memcpy1,3 +mlock03,1 +nanosleep03,1 +pathconf01,1 +pathconf01,2 +pathconf01,3 +pathconf01,4 +pathconf01,5 +pathconf01,6 +pathconf01,7 +personality02,1 +pipe09,1 +pipe10,1 +poll01,1 +poll01,2 +process_vm_writev,2 +process_vm_writev,4 +process_vm_writev,6 +process_vm_writev,8 +process_vm_writev,11 +process_vm_writev,13 +process_vm_writev,15 +process_vm_writev,17 +process_vm_writev,19 +process_vm_writev,21 +ptrace05,1 +sbrk01,1 +sbrk01,2 +sbrk02,1 +sched_yield01,1 +select02,1 +setgid01,1 +setitimer01,1 +setpgid01,1 +setpgid01,2 +setpgrp01,1 +setpgrp02,1 +setrlimit03,1 +setsid01,1 +setsockopt01,1 +setsockopt01,2 +settimeofday01,3 +setuid01,1 +sigaction01,4 +sigaction02,1 +sigaction02,2 +sigaction02,3 +signal02,1 +signal02,2 +signal02,3 +signal03,1 +signal03,2 +signal03,3 +signal03,4 +signal03,5 +signal03,6 +signal03,7 +signal03,8 +signal03,9 +signal03,10 +signal03,11 +signal03,12 +signal03,13 +signal03,14 +signal03,15 +signal03,16 +signal03,17 +signal03,18 +signal03,19 +signal03,20 +signal03,21 +signal03,22 +signal03,23 +signal03,24 +signal03,25 +signal03,26 +signal03,27 +signal03,28 +signal03,29 +signal03,30 +signal03,31 +signal04,1 +signal04,2 +signal04,3 +signal04,4 +signal04,5 +signal04,6 +signal04,7 +signal04,8 +signal04,9 +signal04,10 +signal04,11 +signal04,12 +signal04,13 +signal04,14 +signal04,15 +signal04,16 +signal04,17 +signal04,18 +signal04,19 +signal04,20 +signal04,21 +signal04,22 +signal04,23 +signal04,24 +signal04,25 +signal04,26 +signal04,27 +signal04,28 +signal05,1 +signal05,2 +signal05,3 +signal05,4 +signal05,5 +signal05,6 +signal05,7 +signal05,8 +signal05,9 +signal05,10 +signal05,11 +signal05,12 +signal05,13 +signal05,14 +signal05,15 +signal05,16 +signal05,17 +signal05,18 +signal05,19 +signal05,20 +signal05,21 +signal05,22 +signal05,23 +signal05,24 +signal05,25 +signal05,26 +signal05,27 +signal05,28 +signal05,29 +signal05,30 +signal05,31 +signal06,1 +signal06,2 +signal06,3 +signal06,4 +signal06,5 +socketcall01,1 +socketcall02,1 +socketcall03,1 +socketcall04,1 +splice02,1 +string01,1 +sync01,1 +sysconf01,1 +sysconf01,2 +sysconf01,4 +sysconf01,5 +sysconf01,6 +sysconf01,7 +sysconf01,8 +sysconf01,9 +sysconf01,10 +sysconf01,11 +sysconf01,12 +sysconf01,13 +sysconf01,14 +sysconf01,15 +sysconf01,16 +sysconf01,17 +sysconf01,18 +sysconf01,19 +sysconf01,21 +sysconf01,24 +sysconf01,25 +sysconf01,27 +sysconf01,28 +sysconf01,29 +sysconf01,30 +sysconf01,31 +sysconf01,32 +sysconf01,33 +sysconf01,34 +sysconf01,35 +sysconf01,36 +sysconf01,37 +sysconf01,38 +sysconf01,39 +sysconf01,41 +sysconf01,42 +sysconf01,44 +sysconf01,45 +sysconf01,46 +sysconf01,47 +sysconf01,48 +sysconf01,50 +sysconf01,51 +sysconf01,52 +sysconf01,53 +sysconf01,56 +time01,1 +time02,1 +times01,1 +umask01,1 +umask02,1 +uname01,1 +uname03,1 +ustat02,1 +wait01,1 +wait401,1 +wait401,2 +waitpid01,1 +waitpid02,1 +waitpid02,3 +waitpid03,1 +waitpid03,2 diff --git a/LibOS/shim/test/apps/ltp/block_tests.awk b/LibOS/shim/test/apps/ltp/block_tests.awk new file mode 100644 index 00000000..0e1044b7 --- /dev/null +++ b/LibOS/shim/test/apps/ltp/block_tests.awk @@ -0,0 +1,17 @@ +#!/usr/bin/awk -f +BEGIN{ + while(getline < "BLOCKED") { + test = $1$2$3 + blocked[test] + } +} +NF && ! /^#/ { + test = $2$3 + if(!(test in blocked)) { + s=$1 "_graphene ./pal_loader" + for (i=2; i<=NF; i++) { + s = s " " $i + } + print s + } +} diff --git a/LibOS/shim/test/apps/ltp/manifest.template b/LibOS/shim/test/apps/ltp/manifest.template new file mode 100644 index 00000000..78e82be9 --- /dev/null +++ b/LibOS/shim/test/apps/ltp/manifest.template @@ -0,0 +1,18 @@ +loader.preload = file:$(SHIMPATH) +loader.env.LD_LIBRARY_PATH = /lib:/lib64:/usr/lib:/usr/lib64 +loader.debug_type = none + +fs.mount.tmp1.type = chroot +fs.mount.tmp1.path = /tmp +fs.mount.tmp1.uri = file:/tmp + +fs.mount.lib.type = chroot +fs.mount.lib.path = /lib +fs.mount.lib.uri = file:$(LIBCDIR) + +fs.mount.usr.type = chroot +fs.mount.usr.path = /usr +fs.mount.usr.uri = file:/usr + +sys.brk.size = 32M +sys.stack.size = 4M diff --git a/LibOS/shim/test/apps/ltp/passed_tests_only.awk b/LibOS/shim/test/apps/ltp/passed_tests_only.awk new file mode 100644 index 00000000..557b3a5b --- /dev/null +++ b/LibOS/shim/test/apps/ltp/passed_tests_only.awk @@ -0,0 +1,19 @@ +#!/usr/bin/awk -f +BEGIN{ + getline < "PASSED" + while(getline < "PASSED") { + split($1$2$3, a, ",") + test = a[1] + passed[test] + } +} +NF && ! /^#/ { + test = $2$3 + if(test in passed) { + s=$1 "_graphene ./pal_loader" + for (i=2; i<=NF; i++) { + s = s " " $i + } + print s + } +} diff --git a/LibOS/shim/test/apps/ltp/run_in_graphene.awk b/LibOS/shim/test/apps/ltp/run_in_graphene.awk new file mode 100755 index 00000000..881367e4 --- /dev/null +++ b/LibOS/shim/test/apps/ltp/run_in_graphene.awk @@ -0,0 +1,29 @@ +#!/usr/bin/awk -f +# +# Script for adding necessary valgrind calls before commands. +# +# Copyright (C) 2016, Graphene library OS. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Chia-Che Tsai, Fall 2016 +# +NF && ! /^#/ { + s=$1 "_graphene ./pal_loader" + for (i = 2; i <= NF; i++) { + s = s " " $i + } + print s +} diff --git a/LibOS/shim/test/apps/ltp/runltp.patch b/LibOS/shim/test/apps/ltp/runltp.patch new file mode 100644 index 00000000..1ecb7842 --- /dev/null +++ b/LibOS/shim/test/apps/ltp/runltp.patch @@ -0,0 +1,18 @@ +--- runltp.old 2016-10-24 17:04:25.557950335 -0400 ++++ runltp 2016-10-24 18:20:37.168448299 -0400 +@@ -813,6 +813,15 @@ main() + fi + fi + ++ ## Running all test in Graphene if $GRAPHENE_RUN = 1 ++ if [ $GRAPHENE_RUN ]; then ++ awk -f ${LTPROOT}/bin/run_in_graphene.awk \ ++ ${TMP}/alltests > \ ++ ${TMP}/alltests.tmp ++ cp ${TMP}/alltests.tmp ${TMP}/alltests ++ rm -rf ${TMP}/alltests.tmp ++ fi ++ + ## Valgrind Check will work only when Kernel Fault Injection is not expected, + ## We do not want to test Faults when valgrind is running + if [ $VALGRIND_CHECK ]; then diff --git a/LibOS/shim/test/apps/memcached/Makefile b/LibOS/shim/test/apps/memcached/Makefile new file mode 100644 index 00000000..cd796a4d --- /dev/null +++ b/LibOS/shim/test/apps/memcached/Makefile @@ -0,0 +1,42 @@ +manifests = memcached.manifest +SRCDIR = memcached-master +HOST = $(firstword $(shell ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' -m 1 | cut -d: -f2)) +PORT = 8000 +CORES = 4 +MAXMEM = 256 +MAXTHREADS = 16 + +target = memcached $(manifests) +exec_target = memcached + +clean-extra = clean-build + +extra_rules = \ + -e 's:\$$(PAL):../pal_loader:g' \ + -e 's:\$$(HOST):$(HOST):g' \ + -e 's:\$$(PORT):$(PORT):g' \ + -e 's:\$$(MEMSIZE):$(shell expr $(MAXMEM) + $(MAXMEM))M:g' \ + -e 's:\$$(THREADNUM):$(shell expr 2 + $(MAXTHREADS)):g' + +level = ../../ +include ../../Makefile + +master.zip: + wget https://github.com/memcached/memcached/archive/master.zip + +$(SRCDIR)/configure: master.zip + unzip master.zip + cd $(SRCDIR) && ./autogen.sh + +$(SRCDIR)/memcached: $(SRCDIR)/configure + cd $(SRCDIR) && ./configure + cd $(SRCDIR) && make + +memcached: $(SRCDIR)/memcached + cp -f $< $@ + +clean-build: + rm -rf $(BUILDDIR) + +distclean: clean + rm -rf $(SRCDIR) diff --git a/LibOS/shim/test/apps/memcached/memcached.manifest.template b/LibOS/shim/test/apps/memcached/memcached.manifest.template new file mode 100644 index 00000000..7dbd2fd7 --- /dev/null +++ b/LibOS/shim/test/apps/memcached/memcached.manifest.template @@ -0,0 +1,54 @@ +#!$(PAL) + +loader.preload = file:$(SHIMPATH) +loader.exec = file:memcached +loader.env.LD_LIBRARY_PATH = /lib:/usr/lib:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu +loader.debug_type = none + +fs.mount.lib.type = chroot +fs.mount.lib.path = /lib +fs.mount.lib.uri = file:$(LIBCDIR) + +fs.mount.lib2.type = chroot +fs.mount.lib2.path = /lib/x86_64-linux-gnu +fs.mount.lib2.uri = file:/lib/x86_64-linux-gnu + +fs.mount.usr.type = chroot +fs.mount.usr.path = /usr +fs.mount.usr.uri = file:/usr + +fs.mount.passwd.type = chroot +fs.mount.passwd.path = /etc/passwd +fs.mount.passwd.uri = file:/etc/passwd + +fs.mount.shadow.type = chroot +fs.mount.shadow.path = /etc/shadow +fs.mount.shadow.uri = file:/etc/shadow + +fs.mount.tmp.type = chroot +fs.mount.tmp.path = /tmp +fs.mount.tmp.uri = file:/tmp + +# allow to bind on port for listening +net.allow_bind.1 = $(HOST):$(PORT) + +sys.stack.size = 1m +sys.brk.size = 64M +glibc.heap_size = 16M + +sgx.enclave_size = $(MEMSIZE) +sgx.thread_num = $(THREADNUM) + +sgx.trusted_files.ld = file:$(LIBCDIR)/ld-linux-x86-64.so.2 +sgx.trusted_files.libc = file:$(LIBCDIR)/libc.so.6 +sgx.trusted_files.libdl = file:$(LIBCDIR)/libdl.so.2 +sgx.trusted_files.libm = file:$(LIBCDIR)/libm.so.6 +sgx.trusted_files.libpthread = file:$(LIBCDIR)/libpthread.so.0 +sgx.trusted_files.libnss1 = file:/lib/x86_64-linux-gnu/libnss_compat.so.2 +sgx.trusted_files.libnss2 = file:/lib/x86_64-linux-gnu/libnss_files.so.2 +sgx.trusted_files.libnss3 = file:/lib/x86_64-linux-gnu/libnss_nis.so.2 +sgx.trusted_files.libnsl = file:/lib/x86_64-linux-gnu/libnsl.so.1 +sgx.trusted_files.libevent = file:/usr/lib/x86_64-linux-gnu/libevent-2.0.so.5 + +sgx.allowed_files.passwd = file:/etc/passwd +sgx.allowed_files.shadow = file:/etc/shadow diff --git a/LibOS/shim/test/inline/Makefile b/LibOS/shim/test/inline/Makefile index 86b67284..7f220b4d 100644 --- a/LibOS/shim/test/inline/Makefile +++ b/LibOS/shim/test/inline/Makefile @@ -11,11 +11,12 @@ CFLAGS-debug += -fno-builtin -nostdlib ifeq ($(SYS),x86_64-linux-gnu) $(c_executables): %: %.c $(libs) $(level)../../../Pal/src/user_start.o @echo [ $@ ] - @$(CC) $(CFLAGS-debug) $(LDFLAGS-debug) -o $@ $^ + $(CC) $(CFLAGS-debug) $(LDFLAGS-debug) -o $@ $^ -lpal -lsysdb_debug + $(cxx_executables): %: %.cpp $(libs) $(level)../../../Pal/src/user_start.o @echo [ $@ ] - @$(CXX) $(CFLAGS-debug) $(LDFLAGS-debug) -o $@ $^ + $(CXX) $(CFLAGS-debug) $(LDFLAGS-debug) -o $@ $^ -lpal -lsysdb_debug .PHONY: pack pack: $(c_executables) $(cxx_executables) diff --git a/Pal/src/host/Linux-SGX/Makefile b/Pal/src/host/Linux-SGX/Makefile index 92d7f3f5..85cf9cc4 100644 --- a/Pal/src/host/Linux-SGX/Makefile +++ b/Pal/src/host/Linux-SGX/Makefile @@ -6,7 +6,7 @@ LD = ld include Makefile.am CFLAGS = -Wall -fPIC -O2 -std=gnu99 -fgnu89-inline -U_FORTIFY_SOURCE \ - -fno-omit-frame-pointer \ + -fno-omit-frame-pointer -maes \ -fno-stack-protector -fno-builtin \ -I. -Iinclude -I../.. -I../../../include -I../../../lib ASFLAGS = -DPIC -DSHARED -fPIC -DASSEMBLER -Wa,--noexecstack \ @@ -23,7 +23,7 @@ enclave-objs = $(addprefix db_,files devices pipes sockets streams memory \ exception misc ipc spinlock) \ $(addprefix enclave_,ocalls ecalls framework pages untrusted) \ $(patsubst %.c,%,$(wildcard crypto/*.c)) -enclave-asm-objs = enclave_entry +enclave-asm-objs = enclave_entry $(patsubst %.S,%,$(wildcard crypto/*.S)) urts-objs = $(addprefix sgx_,enclave framework main rtld thread process exception graphene) urts-asm-objs = sgx_entry graphene_lib = ../../.lib/graphene-lib.a diff --git a/Pal/src/host/Linux-SGX/crypto/aes.c b/Pal/src/host/Linux-SGX/crypto/aes.c index a5a282f6..9aed75bc 100644 --- a/Pal/src/host/Linux-SGX/crypto/aes.c +++ b/Pal/src/host/Linux-SGX/crypto/aes.c @@ -25,6 +25,7 @@ #include "aes.h" #include "error-crypt.h" #include "api.h" +#include "pal_linux_defs.h" #define XMEMSET memset #define XMEMCPY memcpy @@ -756,6 +757,105 @@ static const word32 Td[5][256] = { #define GETBYTE(x, y) (word32)((byte)((x) >> (8 *(y)))) +#if USE_AES_NI == 1 + +#include + +/* tell C compiler these are asm functions in case any mix up of ABI underscore + prefix between clang/gcc/llvm etc */ +void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr); + + +void AES_CBC_decrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr); + +void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr); + + +void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr); + +void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule); + +void AES_192_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule); + +void AES_256_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule); + + +static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES* aes) +{ + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (bits == 128) { + AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; + return 0; + } + else if (bits == 192) { + AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; + return 0; + } + else if (bits == 256) { + AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; + return 0; + } + return BAD_FUNC_ARG; +} + + +static int AES_set_decrypt_key(const unsigned char* userKey, const int bits, + AES* aes) +{ + int nr; + AES temp_key; + __m128i *Key_Schedule = (__m128i*)aes->key; + __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) + return BAD_FUNC_ARG; + + nr = temp_key.rounds; + aes->rounds = nr; + + Key_Schedule[nr] = Temp_Key_Schedule[0]; + Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); + Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); + Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); + Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); + Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); + Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); + Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); + Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); + Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); + + if(nr>10) { + Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); + Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); + } + + if(nr>12) { + Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); + Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); + } + + Key_Schedule[0] = Temp_Key_Schedule[nr]; + + return 0; +} + +#endif /* USE_AES_NI == 1 */ + void AESEncrypt(AES *aes, const byte *inBlock, byte *outBlock) { word32 s0, s1, s2, s3; @@ -766,6 +866,14 @@ void AESEncrypt(AES *aes, const byte *inBlock, byte *outBlock) if (r > 7 || r == 0) return; /* stop instead of segfaulting, set up your keys! */ +#if USE_AES_NI == 1 + /* check alignment, decrypt doesn't need alignment */ + if (!((uint64_t) inBlock % 16)) { + AES_ECB_encrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key, + aes->rounds); + return; + } +#endif /* *map byte array block to cipher state *and add initial round key: @@ -898,6 +1006,14 @@ void AESDecrypt(AES *aes, const byte *inBlock, byte *outBlock) if (r > 7 || r == 0) return; /* stop instead of segfaulting, set up your keys! */ +#if USE_AES_NI == 1 + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, inBlock, AES_BLOCK_SIZE); + AES_ECB_decrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key, + aes->rounds); + return; +#endif + /* *map byte array block to cipher state *and add initial round key: diff --git a/Pal/src/host/Linux-SGX/crypto/aes_ni.S b/Pal/src/host/Linux-SGX/crypto/aes_ni.S new file mode 100644 index 00000000..b5f5bc9c --- /dev/null +++ b/Pal/src/host/Linux-SGX/crypto/aes_ni.S @@ -0,0 +1,816 @@ +/* aes_asm.s + * + * Copyright (C) 2006-2014 wolfSSL Inc. + * + * This file is part of CyaSSL. + * + * CyaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * CyaSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +/* See IntelĀ® Advanced Encryption Standard (AES) Instructions Set White Paper + * by Intel Mobility Group, Israel Development Center, Israel Shay Gueron + */ + +/* This file is in at&t asm syntax, see .asm for intel syntax */ + + +/* +AES_CBC_encrypt (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +.globl AES_CBC_encrypt +AES_CBC_encrypt: +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8 +# parameter 6: %r9d +movq %rcx, %r10 +shrq $4, %rcx +shlq $60, %r10 +je NO_PARTS +addq $1, %rcx +NO_PARTS: +subq $16, %rsi +movdqa (%rdx), %xmm1 +LOOP: +pxor (%rdi), %xmm1 +pxor (%r8), %xmm1 +addq $16,%rsi +addq $16,%rdi +cmpl $12, %r9d +aesenc 16(%r8),%xmm1 +aesenc 32(%r8),%xmm1 +aesenc 48(%r8),%xmm1 +aesenc 64(%r8),%xmm1 +aesenc 80(%r8),%xmm1 +aesenc 96(%r8),%xmm1 +aesenc 112(%r8),%xmm1 +aesenc 128(%r8),%xmm1 +aesenc 144(%r8),%xmm1 +movdqa 160(%r8),%xmm2 +jb LAST +cmpl $14, %r9d + +aesenc 160(%r8),%xmm1 +aesenc 176(%r8),%xmm1 +movdqa 192(%r8),%xmm2 +jb LAST +aesenc 192(%r8),%xmm1 +aesenc 208(%r8),%xmm1 +movdqa 224(%r8),%xmm2 +LAST: +decq %rcx +aesenclast %xmm2,%xmm1 +movdqu %xmm1,(%rsi) +jne LOOP +ret + + + + +/* +AES_CBC_decrypt (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +.globl AES_CBC_decrypt +AES_CBC_decrypt: +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8 +# parameter 6: %r9d + +movq %rcx, %r10 +shrq $4, %rcx +shlq $60, %r10 +je DNO_PARTS_4 +addq $1, %rcx +DNO_PARTS_4: +movq %rcx, %r10 +shlq $62, %r10 +shrq $62, %r10 +shrq $2, %rcx +movdqu (%rdx),%xmm5 +je DREMAINDER_4 +subq $64, %rsi +DLOOP_4: +movdqu (%rdi), %xmm1 +movdqu 16(%rdi), %xmm2 +movdqu 32(%rdi), %xmm3 +movdqu 48(%rdi), %xmm4 +movdqa %xmm1, %xmm6 +movdqa %xmm2, %xmm7 +movdqa %xmm3, %xmm8 +movdqa %xmm4, %xmm15 +movdqa (%r8), %xmm9 +movdqa 16(%r8), %xmm10 +movdqa 32(%r8), %xmm11 +movdqa 48(%r8), %xmm12 +pxor %xmm9, %xmm1 +pxor %xmm9, %xmm2 +pxor %xmm9, %xmm3 + +pxor %xmm9, %xmm4 +aesdec %xmm10, %xmm1 +aesdec %xmm10, %xmm2 +aesdec %xmm10, %xmm3 +aesdec %xmm10, %xmm4 +aesdec %xmm11, %xmm1 +aesdec %xmm11, %xmm2 +aesdec %xmm11, %xmm3 +aesdec %xmm11, %xmm4 +aesdec %xmm12, %xmm1 +aesdec %xmm12, %xmm2 +aesdec %xmm12, %xmm3 +aesdec %xmm12, %xmm4 +movdqa 64(%r8), %xmm9 +movdqa 80(%r8), %xmm10 +movdqa 96(%r8), %xmm11 +movdqa 112(%r8), %xmm12 +aesdec %xmm9, %xmm1 +aesdec %xmm9, %xmm2 +aesdec %xmm9, %xmm3 +aesdec %xmm9, %xmm4 +aesdec %xmm10, %xmm1 +aesdec %xmm10, %xmm2 +aesdec %xmm10, %xmm3 +aesdec %xmm10, %xmm4 +aesdec %xmm11, %xmm1 +aesdec %xmm11, %xmm2 +aesdec %xmm11, %xmm3 +aesdec %xmm11, %xmm4 +aesdec %xmm12, %xmm1 +aesdec %xmm12, %xmm2 +aesdec %xmm12, %xmm3 +aesdec %xmm12, %xmm4 +movdqa 128(%r8), %xmm9 +movdqa 144(%r8), %xmm10 +movdqa 160(%r8), %xmm11 +cmpl $12, %r9d +aesdec %xmm9, %xmm1 +aesdec %xmm9, %xmm2 +aesdec %xmm9, %xmm3 +aesdec %xmm9, %xmm4 +aesdec %xmm10, %xmm1 +aesdec %xmm10, %xmm2 +aesdec %xmm10, %xmm3 +aesdec %xmm10, %xmm4 +jb DLAST_4 +movdqa 160(%r8), %xmm9 +movdqa 176(%r8), %xmm10 +movdqa 192(%r8), %xmm11 +cmpl $14, %r9d +aesdec %xmm9, %xmm1 +aesdec %xmm9, %xmm2 +aesdec %xmm9, %xmm3 +aesdec %xmm9, %xmm4 +aesdec %xmm10, %xmm1 +aesdec %xmm10, %xmm2 +aesdec %xmm10, %xmm3 +aesdec %xmm10, %xmm4 +jb DLAST_4 + +movdqa 192(%r8), %xmm9 +movdqa 208(%r8), %xmm10 +movdqa 224(%r8), %xmm11 +aesdec %xmm9, %xmm1 +aesdec %xmm9, %xmm2 +aesdec %xmm9, %xmm3 +aesdec %xmm9, %xmm4 +aesdec %xmm10, %xmm1 +aesdec %xmm10, %xmm2 +aesdec %xmm10, %xmm3 +aesdec %xmm10, %xmm4 +DLAST_4: +addq $64, %rdi +addq $64, %rsi +decq %rcx +aesdeclast %xmm11, %xmm1 +aesdeclast %xmm11, %xmm2 +aesdeclast %xmm11, %xmm3 +aesdeclast %xmm11, %xmm4 +pxor %xmm5 ,%xmm1 +pxor %xmm6 ,%xmm2 +pxor %xmm7 ,%xmm3 +pxor %xmm8 ,%xmm4 +movdqu %xmm1, (%rsi) +movdqu %xmm2, 16(%rsi) +movdqu %xmm3, 32(%rsi) +movdqu %xmm4, 48(%rsi) +movdqa %xmm15,%xmm5 +jne DLOOP_4 +addq $64, %rsi +DREMAINDER_4: +cmpq $0, %r10 +je DEND_4 +DLOOP_4_2: +movdqu (%rdi), %xmm1 +movdqa %xmm1 ,%xmm15 +addq $16, %rdi +pxor (%r8), %xmm1 +movdqu 160(%r8), %xmm2 +cmpl $12, %r9d +aesdec 16(%r8), %xmm1 +aesdec 32(%r8), %xmm1 +aesdec 48(%r8), %xmm1 +aesdec 64(%r8), %xmm1 +aesdec 80(%r8), %xmm1 +aesdec 96(%r8), %xmm1 +aesdec 112(%r8), %xmm1 +aesdec 128(%r8), %xmm1 +aesdec 144(%r8), %xmm1 +jb DLAST_4_2 +movdqu 192(%r8), %xmm2 +cmpl $14, %r9d +aesdec 160(%r8), %xmm1 +aesdec 176(%r8), %xmm1 +jb DLAST_4_2 +movdqu 224(%r8), %xmm2 +aesdec 192(%r8), %xmm1 +aesdec 208(%r8), %xmm1 +DLAST_4_2: +aesdeclast %xmm2, %xmm1 +pxor %xmm5, %xmm1 +movdqa %xmm15, %xmm5 +movdqu %xmm1, (%rsi) + +addq $16, %rsi +decq %r10 +jne DLOOP_4_2 +DEND_4: +ret + + +/* +AES_ECB_encrypt (const unsigned char *in, + unsigned char *out, + unsigned long length, + const unsigned char *KS, + int nr) +*/ +.globl AES_ECB_encrypt +AES_ECB_encrypt: +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8d + movq %rdx, %r10 + shrq $4, %rdx + shlq $60, %r10 + je EECB_NO_PARTS_4 + addq $1, %rdx +EECB_NO_PARTS_4: + movq %rdx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rdx + je EECB_REMAINDER_4 + subq $64, %rsi +EECB_LOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa (%rcx), %xmm9 + movdqa 16(%rcx), %xmm10 + movdqa 32(%rcx), %xmm11 + movdqa 48(%rcx), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + aesenc %xmm11, %xmm1 + aesenc %xmm11, %xmm2 + aesenc %xmm11, %xmm3 + aesenc %xmm11, %xmm4 + aesenc %xmm12, %xmm1 + aesenc %xmm12, %xmm2 + aesenc %xmm12, %xmm3 + aesenc %xmm12, %xmm4 + movdqa 64(%rcx), %xmm9 + movdqa 80(%rcx), %xmm10 + movdqa 96(%rcx), %xmm11 + movdqa 112(%rcx), %xmm12 + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + aesenc %xmm11, %xmm1 + aesenc %xmm11, %xmm2 + aesenc %xmm11, %xmm3 + aesenc %xmm11, %xmm4 + aesenc %xmm12, %xmm1 + aesenc %xmm12, %xmm2 + aesenc %xmm12, %xmm3 + aesenc %xmm12, %xmm4 + movdqa 128(%rcx), %xmm9 + movdqa 144(%rcx), %xmm10 + movdqa 160(%rcx), %xmm11 + cmpl $12, %r8d + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + jb EECB_LAST_4 + movdqa 160(%rcx), %xmm9 + movdqa 176(%rcx), %xmm10 + movdqa 192(%rcx), %xmm11 + cmpl $14, %r8d + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + jb EECB_LAST_4 + movdqa 192(%rcx), %xmm9 + movdqa 208(%rcx), %xmm10 + movdqa 224(%rcx), %xmm11 + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 +EECB_LAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rdx + aesenclast %xmm11, %xmm1 + aesenclast %xmm11, %xmm2 + aesenclast %xmm11, %xmm3 + aesenclast %xmm11, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + jne EECB_LOOP_4 + addq $64, %rsi +EECB_REMAINDER_4: + cmpq $0, %r10 + je EECB_END_4 +EECB_LOOP_4_2: + movdqu (%rdi), %xmm1 + addq $16, %rdi + pxor (%rcx), %xmm1 + movdqu 160(%rcx), %xmm2 + aesenc 16(%rcx), %xmm1 + aesenc 32(%rcx), %xmm1 + aesenc 48(%rcx), %xmm1 + aesenc 64(%rcx), %xmm1 + aesenc 80(%rcx), %xmm1 + aesenc 96(%rcx), %xmm1 + aesenc 112(%rcx), %xmm1 + aesenc 128(%rcx), %xmm1 + aesenc 144(%rcx), %xmm1 + cmpl $12, %r8d + jb EECB_LAST_4_2 + movdqu 192(%rcx), %xmm2 + aesenc 160(%rcx), %xmm1 + aesenc 176(%rcx), %xmm1 + cmpl $14, %r8d + jb EECB_LAST_4_2 + movdqu 224(%rcx), %xmm2 + aesenc 192(%rcx), %xmm1 + aesenc 208(%rcx), %xmm1 +EECB_LAST_4_2: + aesenclast %xmm2, %xmm1 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne EECB_LOOP_4_2 +EECB_END_4: + ret + + +/* +AES_ECB_decrypt (const unsigned char *in, + unsigned char *out, + unsigned long length, + const unsigned char *KS, + int nr) +*/ +.globl AES_ECB_decrypt +AES_ECB_decrypt: +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8d + + movq %rdx, %r10 + shrq $4, %rdx + shlq $60, %r10 + je DECB_NO_PARTS_4 + addq $1, %rdx +DECB_NO_PARTS_4: + movq %rdx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rdx + je DECB_REMAINDER_4 + subq $64, %rsi +DECB_LOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa (%rcx), %xmm9 + movdqa 16(%rcx), %xmm10 + movdqa 32(%rcx), %xmm11 + movdqa 48(%rcx), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 64(%rcx), %xmm9 + movdqa 80(%rcx), %xmm10 + movdqa 96(%rcx), %xmm11 + movdqa 112(%rcx), %xmm12 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 128(%rcx), %xmm9 + movdqa 144(%rcx), %xmm10 + movdqa 160(%rcx), %xmm11 + cmpl $12, %r8d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DECB_LAST_4 + movdqa 160(%rcx), %xmm9 + movdqa 176(%rcx), %xmm10 + movdqa 192(%rcx), %xmm11 + cmpl $14, %r8d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DECB_LAST_4 + movdqa 192(%rcx), %xmm9 + movdqa 208(%rcx), %xmm10 + movdqa 224(%rcx), %xmm11 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 +DECB_LAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rdx + aesdeclast %xmm11, %xmm1 + aesdeclast %xmm11, %xmm2 + aesdeclast %xmm11, %xmm3 + aesdeclast %xmm11, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + jne DECB_LOOP_4 + addq $64, %rsi +DECB_REMAINDER_4: + cmpq $0, %r10 + je DECB_END_4 +DECB_LOOP_4_2: + movdqu (%rdi), %xmm1 + addq $16, %rdi + pxor (%rcx), %xmm1 + movdqu 160(%rcx), %xmm2 + cmpl $12, %r8d + aesdec 16(%rcx), %xmm1 + aesdec 32(%rcx), %xmm1 + aesdec 48(%rcx), %xmm1 + aesdec 64(%rcx), %xmm1 + aesdec 80(%rcx), %xmm1 + aesdec 96(%rcx), %xmm1 + aesdec 112(%rcx), %xmm1 + aesdec 128(%rcx), %xmm1 + aesdec 144(%rcx), %xmm1 + jb DECB_LAST_4_2 + cmpl $14, %r8d + movdqu 192(%rcx), %xmm2 + aesdec 160(%rcx), %xmm1 + aesdec 176(%rcx), %xmm1 + jb DECB_LAST_4_2 + movdqu 224(%rcx), %xmm2 + aesdec 192(%rcx), %xmm1 + aesdec 208(%rcx), %xmm1 +DECB_LAST_4_2: + aesdeclast %xmm2, %xmm1 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DECB_LOOP_4_2 +DECB_END_4: + ret + + + + +/* +void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule); +*/ +.align 16,0x90 +.globl AES_128_Key_Expansion +AES_128_Key_Expansion: +# parameter 1: %rdi +# parameter 2: %rsi +movl $10, 240(%rsi) + +movdqu (%rdi), %xmm1 +movdqa %xmm1, (%rsi) + + +ASSISTS: +aeskeygenassist $1, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 16(%rsi) +aeskeygenassist $2, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 32(%rsi) +aeskeygenassist $4, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 48(%rsi) +aeskeygenassist $8, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 64(%rsi) +aeskeygenassist $16, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 80(%rsi) +aeskeygenassist $32, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 96(%rsi) +aeskeygenassist $64, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 112(%rsi) +aeskeygenassist $0x80, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 128(%rsi) +aeskeygenassist $0x1b, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 144(%rsi) +aeskeygenassist $0x36, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 160(%rsi) +ret + +PREPARE_ROUNDKEY_128: +pshufd $255, %xmm2, %xmm2 +movdqa %xmm1, %xmm3 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pxor %xmm2, %xmm1 +ret + + +/* +void AES_192_Key_Expansion (const unsigned char *userkey, + unsigned char *key) +*/ +.globl AES_192_Key_Expansion +AES_192_Key_Expansion: +# parameter 1: %rdi +# parameter 2: %rsi + +movdqu (%rdi), %xmm1 +movdqu 16(%rdi), %xmm3 +movdqa %xmm1, (%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x1, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 16(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 32(%rsi) + +aeskeygenassist $0x2, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 48(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x4, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 64(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 80(%rsi) + +aeskeygenassist $0x8, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 96(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x10, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 112(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 128(%rsi) + +aeskeygenassist $0x20, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 144(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x40, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 160(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 176(%rsi) + +aeskeygenassist $0x80, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 192(%rsi) +movdqa %xmm3, 208(%rsi) +ret + +PREPARE_ROUNDKEY_192: +pshufd $0x55, %xmm2, %xmm2 +movdqu %xmm1, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 + +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pxor %xmm2, %xmm1 +pshufd $0xff, %xmm1, %xmm2 +movdqu %xmm3, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pxor %xmm2, %xmm3 +ret + + +/* +void AES_256_Key_Expansion (const unsigned char *userkey, + unsigned char *key) +*/ +.globl AES_256_Key_Expansion +AES_256_Key_Expansion: +# parameter 1: %rdi +# parameter 2: %rsi + +movdqu (%rdi), %xmm1 +movdqu 16(%rdi), %xmm3 +movdqa %xmm1, (%rsi) +movdqa %xmm3, 16(%rsi) + +aeskeygenassist $0x1, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 32(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 48(%rsi) +aeskeygenassist $0x2, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 64(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 80(%rsi) +aeskeygenassist $0x4, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 96(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 112(%rsi) +aeskeygenassist $0x8, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 128(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 144(%rsi) +aeskeygenassist $0x10, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 160(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 176(%rsi) +aeskeygenassist $0x20, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 192(%rsi) + +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 208(%rsi) +aeskeygenassist $0x40, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 224(%rsi) + +ret + +MAKE_RK256_a: +pshufd $0xff, %xmm2, %xmm2 +movdqa %xmm1, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pxor %xmm2, %xmm1 +ret + +MAKE_RK256_b: +pshufd $0xaa, %xmm2, %xmm2 +movdqa %xmm3, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pxor %xmm2, %xmm3 +ret + diff --git a/Pal/src/host/Linux-SGX/db_exception.c b/Pal/src/host/Linux-SGX/db_exception.c index debd466d..aec4d741 100644 --- a/Pal/src/host/Linux-SGX/db_exception.c +++ b/Pal/src/host/Linux-SGX/db_exception.c @@ -102,7 +102,7 @@ static struct pal_frame * get_frame (sgx_context_t * uc) struct pal_frame * frame = (struct pal_frame *) rbp - 1; for (int i = 0 ; i < 8 ; i++) { - if (frame->self == frame) + if (frame->identifier == PAL_FRAME_IDENTIFIER) return frame; frame = (struct pal_frame *) ((void *) frame - 8); @@ -136,7 +136,7 @@ void _DkExceptionRealHandler (int event, PAL_NUM arg, struct pal_frame * frame, { if (frame) { frame = __alloca(sizeof(struct pal_frame)); - frame->self = frame; + frame->identifier = PAL_FRAME_IDENTIFIER; frame->func = &_DkExceptionRealHandler; frame->funcname = "_DkExceptionRealHandler"; @@ -351,9 +351,13 @@ void _DkCheckExternalEvent (void) ENCLAVE_TLS(external_event) = 0; struct pal_frame * frame = get_frame(NULL); + if (event == PAL_EVENT_RESUME && + frame && frame->func == DkObjectsWaitAny) + return; + if (!frame) { frame = __alloca(sizeof(struct pal_frame)); - frame->self = frame; + frame->identifier = PAL_FRAME_IDENTIFIER; frame->func = &_DkCheckExternalEvent; frame->funcname = "DkCheckExternalEvent"; arch_store_frame(&frame->arch); diff --git a/Pal/src/host/Linux-SGX/db_files.c b/Pal/src/host/Linux-SGX/db_files.c index 455cfa20..ac254ba7 100644 --- a/Pal/src/host/Linux-SGX/db_files.c +++ b/Pal/src/host/Linux-SGX/db_files.c @@ -65,11 +65,11 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri, get_norm_path(uri, path, 0, len + 1); hdl->file.realpath = (PAL_STR) path; - sgx_checksum_t * stubs; + sgx_arch_mac_t * stubs; uint64_t total; int ret = load_trusted_file(hdl, &stubs, &total); if (ret < 0) { - SGX_DBG(DBG_E, "Accessing file:%s is denied. (%d)" + SGX_DBG(DBG_E, "Accessing file:%s is denied. (%e) " "This file is not trusted or allowed.\n", hdl->file.realpath, ret); free(hdl); return -PAL_ERROR_DENIED; @@ -85,7 +85,7 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri, static int file_read (PAL_HANDLE handle, int offset, int count, void * buffer) { - sgx_checksum_t * stubs = (sgx_checksum_t *) handle->file.stubs; + sgx_arch_mac_t * stubs = (sgx_arch_mac_t *) handle->file.stubs; unsigned int total = handle->file.total; int ret; @@ -178,7 +178,7 @@ static int file_delete (PAL_HANDLE handle, int access) static int file_map (PAL_HANDLE handle, void ** addr, int prot, uint64_t offset, uint64_t size) { - sgx_checksum_t * stubs = (sgx_checksum_t *) handle->file.stubs; + sgx_arch_mac_t * stubs = (sgx_arch_mac_t *) handle->file.stubs; unsigned int total = handle->file.total; void * mem = *addr; void * umem; diff --git a/Pal/src/host/Linux-SGX/db_main.c b/Pal/src/host/Linux-SGX/db_main.c index 2b35f5ca..5aec1e73 100644 --- a/Pal/src/host/Linux-SGX/db_main.c +++ b/Pal/src/host/Linux-SGX/db_main.c @@ -84,6 +84,7 @@ static struct link_map pal_map; int init_untrusted_slab_mgr (int pagesize); int init_enclave (void); +int init_enclave_key (void); int init_child_process (PAL_HANDLE * parent_handle); static PAL_HANDLE setup_file_handle (const char * name, int fd) @@ -139,6 +140,7 @@ void pal_linux_main(const char ** arguments, const char ** environments, init_slab_mgr(pagesz); init_untrusted_slab_mgr(pagesz); init_pages(); + init_enclave_key(); /* now we can add a link map for PAL itself */ setup_pal_map(&pal_map); diff --git a/Pal/src/host/Linux-SGX/db_mutex.c b/Pal/src/host/Linux-SGX/db_mutex.c index 3a7818db..397b4a65 100644 --- a/Pal/src/host/Linux-SGX/db_mutex.c +++ b/Pal/src/host/Linux-SGX/db_mutex.c @@ -39,127 +39,133 @@ #include #include -#define MUTEX_SPINLOCK_TIMES 20 +#ifdef __i386__ +# define barrier() asm volatile("" ::: "memory"); +# define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") +# define cpu_relax() asm volatile("rep; nop" ::: "memory"); +#endif -int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout) +#ifdef __x86_64__ +# include +# define barrier() asm volatile("" ::: "memory"); +# define rmb() asm volatile("lfence" ::: "memory") +# define cpu_relax() asm volatile("rep; nop" ::: "memory"); +#endif + +#define MUTEX_SPINLOCK_TIMES 100 + +int _DkMutexLockTimeout (struct mutex_handle * m, int timeout) { - int i, c = 0; + int ret = 0; +#ifdef DEBUG_MUTEX + int tid = INLINE_SYSCALL(gettid, 0); +#endif if (timeout == -1) - return -_DkMutexLock(mut); + return -_DkMutexLock(m); - struct atomic_int * m = &mut->value; - - /* Spin and try to take lock */ - for (i = 0 ; i < MUTEX_SPINLOCK_TIMES ; i++) - { - c = atomic_dec_and_test(m); - if (c) - goto success; - cpu_relax(); - } - - /* The lock is now contended */ - - int ret; + if (!xchg(&m->b.locked, 1)) + goto success; if (timeout == 0) { - ret = c ? 0 : -PAL_ERROR_TRYAGAIN; + ret = -PAL_ERROR_TRYAGAIN; goto out; } unsigned long waittime = timeout; - while (!c) { - int val = atomic_read(m); - if (val == 1) - goto again; - - ret = ocall_futex((int *) &m->counter, FUTEX_WAIT, 2, timeout ? &waittime : NULL); - if (ret < 0) + while (xchg(&m->u, 257) & 1) { + ret = ocall_futex((int *) m, FUTEX_WAIT, 257, timeout ? &waittime : NULL); + if (ret < 0) { + if (ret == -PAL_ERROR_TRYAGAIN) { + xchg(&m->b.contended, 0); + goto out; + } +#ifdef DEBUG_MUTEX + printf("futex failed (err = %d)\n", ERRNO(ret)); +#endif goto out; - -again: - /* Upon wakeup, we still need to check whether mutex is unlocked or - * someone else took it. - * If c==0 upon return from xchg (i.e., the older value of m==0), we - * will exit the loop. Else, we sleep again (through a futex call). - */ - c = atomic_dec_and_test(m); + } } success: +#ifdef DEBUG_MUTEX + m->owner = tid; +#endif ret = 0; out: +#ifdef DEBUG_MUTEX + if (ret < 0) + printf("mutex failed (%e, tid = %d)\n", -ret, tid); +#endif return ret; } -int _DkMutexLock (struct mutex_handle * mut) +int _DkMutexLock (struct mutex_handle * m) { - int i, c = 0; - int ret; - struct atomic_int * m = &mut->value; + int ret = 0, i; +#ifdef DEBUG_MUTEX + int tid = INLINE_SYSCALL(gettid, 0); +#endif /* Spin and try to take lock */ for (i = 0; i < MUTEX_SPINLOCK_TIMES; i++) { - c = atomic_dec_and_test(m); - if (c) + if (!xchg(&m->b.locked, 1)) goto success; cpu_relax(); } - /* The lock is now contended */ - - while (!c) { - int val = atomic_read(m); - if (val == 1) - goto again; - - ret = ocall_futex((int *) &m->counter, FUTEX_WAIT, 2, NULL); - if (ret < 0) + while (xchg(&m->u, 257) & 1) { + ret = ocall_futex((int *) m, FUTEX_WAIT, 257, NULL); + if (ret < 0 && + ret != -PAL_ERROR_TRYAGAIN) { +#ifdef DEBUG_MUTEX + printf("futex failed (err = %d)\n", ERRNO(ret)); +#endif goto out; - -again: - /* Upon wakeup, we still need to check whether mutex is unlocked or - * someone else took it. - * If c==0 upon return from xchg (i.e., the older value of m==0), we - * will exit the loop. Else, we sleep again (through a futex call). - */ - c = atomic_dec_and_test(m); + } } +success: +#ifdef DEBUG_MUTEX + m->owner = tid; +#endif + ret = 0; +out: +#ifdef DEBUG_MUTEX + if (ret < 0) + printf("mutex failed (%e, tid = %d)\n", -ret, tid); +#endif + return ret; +} + +int _DkMutexUnlock (struct mutex_handle * m) +{ + int ret = 0, i; + +#ifdef DEBUG_MUTEX + m->owner = 0; +#endif + + /* Unlock, and if not contended then exit. */ + if ((m->u == 1) && (cmpxchg(&m->u, 1, 0) == 1)) return 0; + m->b.locked = 0; + barrier(); + + /* Spin and try to take lock */ + for (i = 0; i < MUTEX_SPINLOCK_TIMES * 2; i++) { + if (m->b.locked) + goto success; + cpu_relax(); + } + + m->b.contended = 0; + + /* We need to wake someone up */ + ocall_futex((int *) m, FUTEX_WAKE, 1, NULL); success: ret = 0; out: return ret; } - -int _DkMutexUnlock (struct mutex_handle * mut) -{ - int ret = 0; - int must_wake = 0; - struct atomic_int * m = &mut->value; - - /* Unlock, and if not contended then exit. */ - if (atomic_read(m) < 0) - must_wake = 1; - - atomic_set(m, 1); - - if (must_wake) { - /* We need to wake someone up */ - ret = ocall_futex((int *) &m->counter, FUTEX_WAKE, 1, NULL); - if (ret < 0) - goto out; - } - - if (ret < 0) { - ret = -PAL_ERROR_TRYAGAIN; - goto out; - } - - ret = 0; -out: - return ret; -} diff --git a/Pal/src/host/Linux-SGX/db_semaphore.c b/Pal/src/host/Linux-SGX/db_semaphore.c index ca07fefb..d38ef1b4 100644 --- a/Pal/src/host/Linux-SGX/db_semaphore.c +++ b/Pal/src/host/Linux-SGX/db_semaphore.c @@ -68,7 +68,7 @@ _DkSemaphoreCreate (PAL_HANDLE handle, int initialCount, int maxCount) /* optimization: if maxCount == 1, we make it into mutex */ if (handle->semaphore.max_value == 1) { - atomic_set(&handle->semaphore.value.mut.value, 1 - initialCount); + handle->semaphore.value.mut.u = initialCount; } else { atomic_set(&handle->semaphore.value.i, maxCount - initialCount); } @@ -246,9 +246,8 @@ void _DkSemaphoreRelease (PAL_HANDLE sem, int count) int _DkSemaphoreGetCurrentCount (PAL_HANDLE sem) { if (sem->semaphore.max_value == 1) { - struct mutex_handle * mut = - &sem->semaphore.value.mut; - return atomic_read(&mut->value); + struct mutex_handle * m = &sem->semaphore.value.mut; + return m->b.locked; } int c = atomic_read(&sem->semaphore.value.i); diff --git a/Pal/src/host/Linux-SGX/db_sockets.c b/Pal/src/host/Linux-SGX/db_sockets.c index 09985d7d..054f044a 100644 --- a/Pal/src/host/Linux-SGX/db_sockets.c +++ b/Pal/src/host/Linux-SGX/db_sockets.c @@ -42,6 +42,18 @@ typedef __kernel_pid_t pid_t; #include #include +#ifndef SOL_TCP +# define SOL_TCP 6 +#endif + +#ifndef TCP_NODELAY +# define TCP_NODELAY 1 +#endif + +#ifndef TCP_CORK +# define TCP_CORK 3 +#endif + /* 96 bytes is the minimal size of buffer to store a IPv4/IPv6 address */ #define PAL_SOCKADDR_SIZE 96 @@ -755,7 +767,14 @@ static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) int fd = handle->sock.fd, ret; - if (handle->sock.conn) { + if (IS_HANDLE_TYPE(handle, tcpsrv)) { + struct pollfd pfd = { .fd = fd, .events = POLLIN, .revents = 0 }; + unsigned long waittime = 0; + int ret = ocall_poll(&pfd, 1, &waittime); + if (ret < 0) + return ret; + attr->readable = (ret == 1 && pfd.revents == POLLIN); + } else { /* try use ioctl FIONEAD to get the size of socket */ ret = ocall_fionread(fd); if (ret < 0) @@ -763,25 +782,11 @@ static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) attr->pending_size = ret; attr->readable = !!attr->pending_size > 0; - } else { - attr->readable = !attr->disconnected; } return 0; } -#ifndef SOL_TCP -# define SOL_TCP 6 -#endif - -#ifndef TCP_NODELAY -# define TCP_NODELAY 1 -#endif - -#ifndef TCP_CORK -# define TCP_CORK 3 -#endif - static int socket_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) { if (handle->sock.fd == PAL_IDX_POISON) diff --git a/Pal/src/host/Linux-SGX/enclave_framework.c b/Pal/src/host/Linux-SGX/enclave_framework.c index 7970a99f..ff6ecb01 100644 --- a/Pal/src/host/Linux-SGX/enclave_framework.c +++ b/Pal/src/host/Linux-SGX/enclave_framework.c @@ -71,6 +71,8 @@ int sgx_get_report (sgx_arch_hash_t * mrenclave, #include "crypto/cmac.h" +static sgx_arch_key128_t enclave_key; + int sgx_verify_report (sgx_arch_report_t * report) { sgx_arch_keyrequest_t keyrequest; @@ -78,19 +80,30 @@ int sgx_verify_report (sgx_arch_report_t * report) keyrequest.keyname = REPORT_KEY; memcpy(keyrequest.keyid, report->keyid, sizeof(keyrequest.keyid)); - sgx_arch_key128_t key; - int ret = sgx_getkey(&keyrequest, &key); + int ret = sgx_getkey(&keyrequest, &enclave_key); if (ret) { SGX_DBG(DBG_S, "Can't get report key\n"); return -PAL_ERROR_DENIED; } - SGX_DBG(DBG_S, "Get report key for verification: %s\n", hex2str(key)); - sgx_arch_mac_t mac; - AES_CMAC((void *) &key, (void *) report, SGX_REPORT_SIGNED_SIZE, mac); - SGX_DBG(DBG_S, "Generated mac: %s\n", hex2str(mac)); + SGX_DBG(DBG_S, "Get report key for verification: %s\n", hex2str(enclave_key)); + return 0; +} - return memcmp(mac, report->mac, sizeof(sgx_arch_mac_t)) ? 1 : 0; +int init_enclave_key (void) +{ + sgx_arch_keyrequest_t keyrequest; + memset(&keyrequest, 0, sizeof(sgx_arch_keyrequest_t)); + keyrequest.keyname = SEAL_KEY; + + int ret = sgx_getkey(&keyrequest, &enclave_key); + if (ret) { + SGX_DBG(DBG_S, "Can't get report key\n"); + return -PAL_ERROR_DENIED; + } + + SGX_DBG(DBG_S, "Get sealing key: %s\n", hex2str(enclave_key)); + return 0; } struct trusted_file { @@ -99,7 +112,8 @@ struct trusted_file { uint64_t size; int uri_len; char uri[URI_MAX]; - sgx_checksum_t checksum, * stubs; + sgx_checksum_t checksum; + sgx_arch_mac_t * stubs; }; static LIST_HEAD(trusted_file_list); @@ -108,7 +122,7 @@ static int trusted_file_indexes = 0; #include -int load_trusted_file (PAL_HANDLE file, sgx_checksum_t ** stubptr, +int load_trusted_file (PAL_HANDLE file, sgx_arch_mac_t ** stubptr, uint64_t * sizeptr) { struct trusted_file * tf = NULL, * tmp; @@ -149,11 +163,13 @@ int load_trusted_file (PAL_HANDLE file, sgx_checksum_t ** stubptr, if (tf->index < 0) return tf->index; +#if CACHE_FILE_STUBS == 1 if (tf->index && tf->stubs) { *stubptr = tf->stubs; *sizeptr = tf->size; return 0; } +#endif if (!tf->index) { *stubptr = NULL; @@ -169,10 +185,11 @@ int load_trusted_file (PAL_HANDLE file, sgx_checksum_t ** stubptr, int nstubs = tf->size / TRUSTED_STUB_SIZE + (tf->size % TRUSTED_STUB_SIZE ? 1 : 0); - sgx_checksum_t * stubs = malloc(sizeof(sgx_checksum_t) * nstubs); - if (!tf) + sgx_arch_mac_t * stubs = malloc(sizeof(sgx_arch_mac_t) * nstubs); + if (!tf) return -PAL_ERROR_NOMEM; + sgx_arch_mac_t * s = stubs; uint64_t offset = 0; SHA256 sha; void * umem; @@ -181,7 +198,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_checksum_t ** stubptr, if (ret < 0) goto failed; - for (; offset < tf->size ; offset += TRUSTED_STUB_SIZE) { + for (; offset < tf->size ; offset += TRUSTED_STUB_SIZE, s++) { uint64_t mapping_size = tf->size - offset; if (mapping_size > TRUSTED_STUB_SIZE) mapping_size = TRUSTED_STUB_SIZE; @@ -190,20 +207,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_checksum_t ** stubptr, if (ret < 0) goto unmap; - /* calculate stub checksum */ - SHA256 stub_sha; - ret = SHA256Init(&stub_sha); - if (ret < 0) - goto unmap; - - ret = SHA256Update(&stub_sha, umem, mapping_size); - if (ret < 0) - goto unmap; - - ret = SHA256Final(&stub_sha, - (uint8_t *) stubs[offset / TRUSTED_STUB_SIZE].bytes); - if (ret < 0) - goto unmap; + AES_CMAC((void *) &enclave_key, umem, mapping_size, (uint8_t *) s); /* update the file checksum */ ret = SHA256Update(&sha, umem, mapping_size); @@ -226,12 +230,9 @@ unmap: } _DkSpinLock(&trusted_file_lock); - if (tf->stubs || tf->index == -PAL_ERROR_DENIED) { - free(stubs); - *stubptr = tf->stubs; - } else { - *stubptr = tf->stubs = stubs; - } + if (tf->stubs || tf->index == -PAL_ERROR_DENIED) + free(tf->stubs); + *stubptr = tf->stubs = stubs; *sizeptr = tf->size; ret = tf->index; _DkSpinUnlock(&trusted_file_lock); @@ -255,12 +256,11 @@ failed: int verify_trusted_file (const char * uri, void * mem, unsigned int offset, unsigned int size, - sgx_checksum_t * stubs, + sgx_arch_mac_t * stubs, unsigned int total_size) { unsigned long checking = offset; - sgx_checksum_t * s = stubs + checking / TRUSTED_STUB_SIZE; - char checksum_text[sizeof(sgx_checksum_t) * 2 + 1] = "\0"; + sgx_arch_mac_t * s = stubs + checking / TRUSTED_STUB_SIZE; int ret; for (; checking < offset + size ; checking += TRUSTED_STUB_SIZE, s++) { @@ -268,29 +268,13 @@ int verify_trusted_file (const char * uri, void * mem, if (checking_size > total_size - checking) checking_size = total_size - checking; - /* calculate stub checksum */ - sgx_checksum_t checksum; - SHA256 stub_sha; - ret = SHA256Init(&stub_sha); - if (ret < 0) - return -PAL_ERROR_DENIED; + sgx_arch_mac_t mac; + AES_CMAC((void *) &enclave_key, mem + checking - offset, + checking_size, (uint8_t *) &mac); - ret = SHA256Update(&stub_sha, mem + checking - offset, - checking_size); - if (ret < 0) - return -PAL_ERROR_DENIED; - - ret = SHA256Final(&stub_sha, (uint8_t *) checksum.bytes); - if (ret < 0) - return -PAL_ERROR_DENIED; - - for (int i = 0 ; i < sizeof(sgx_checksum_t) ; i++) - snprintf(checksum_text + i * 2, 3, "%02x", - checksum.bytes[i]); - - if (memcmp(s, &checksum, sizeof(sgx_checksum_t))) { + if (memcmp(s, &mac, sizeof(sgx_arch_mac_t))) { SGX_DBG(DBG_E, "Accesing file:%s is denied. " - "Does not match with its checksum.\n", uri); + "Does not match with its MAC.\n", uri); return -PAL_ERROR_DENIED; } } diff --git a/Pal/src/host/Linux-SGX/pal_host.h b/Pal/src/host/Linux-SGX/pal_host.h index d39fe6e6..3dbced5d 100644 --- a/Pal/src/host/Linux-SGX/pal_host.h +++ b/Pal/src/host/Linux-SGX/pal_host.h @@ -53,9 +53,19 @@ void free_untrusted (void * mem); because it is required by futex call. If DEBUG_MUTEX is defined, mutex_handle will record the owner of mutex locking. */ struct mutex_handle { - struct atomic_int value; + union { + unsigned int u; + struct { + unsigned char locked; + unsigned char contended; + } b; + }; }; +/* Initializer of Mutexes */ +#define MUTEX_HANDLE_INIT { .u = 0 } +#define INIT_MUTEX_HANDLE(m) do { m->u = 0; } while (0) + typedef union pal_handle { /* TSAI: Here we define the internal types of PAL_HANDLE @@ -228,8 +238,10 @@ struct arch_frame { # error "unsupported architecture" #endif +#define PAL_FRAME_IDENTIFIER (0xdeaddeadbeefbeef) + struct pal_frame { - volatile struct pal_frame * self; + volatile uint64_t identifier; void * func; const char * funcname; struct arch_frame arch; @@ -239,10 +251,11 @@ static inline void __store_frame (struct pal_frame * frame, void * func, const char * funcname) { - *(volatile void **) &frame->self = frame; + arch_store_frame(&frame->arch) frame->func = func; frame->funcname = funcname; - arch_store_frame(&frame->arch) + asm volatile ("nop" ::: "memory"); + frame->identifier = PAL_FRAME_IDENTIFIER; } #define ENTER_PAL_CALL(name) \ @@ -253,9 +266,9 @@ void __store_frame (struct pal_frame * frame, static inline void __clear_frame (struct pal_frame * frame) { - if (*(volatile void **) &frame->self == frame) { + if (frame->identifier == PAL_FRAME_IDENTIFIER) { asm volatile ("nop" ::: "memory"); - *(volatile void **) &frame->self = NULL; + frame->identifier = 0; } } diff --git a/Pal/src/host/Linux-SGX/pal_linux.h b/Pal/src/host/Linux-SGX/pal_linux.h index 0e0a0aa5..8eac9c3f 100644 --- a/Pal/src/host/Linux-SGX/pal_linux.h +++ b/Pal/src/host/Linux-SGX/pal_linux.h @@ -97,10 +97,10 @@ typedef struct { unsigned char bytes[32]; } sgx_checksum_t; int init_trusted_files (void); int load_trusted_file - (PAL_HANDLE file, sgx_checksum_t ** stubptr, uint64_t * sizeptr); + (PAL_HANDLE file, sgx_arch_mac_t ** stubptr, uint64_t * sizeptr); int verify_trusted_file (const char * uri, void * mem, unsigned int offset, unsigned int size, - sgx_checksum_t * stubs, unsigned int total_size); + sgx_arch_mac_t * stubs, unsigned int total_size); int init_trusted_children (void); int register_trusted_child (const char * uri, const char * mrenclave_str); diff --git a/Pal/src/host/Linux-SGX/pal_linux_defs.h b/Pal/src/host/Linux-SGX/pal_linux_defs.h index 9fb79e8d..d0919f82 100644 --- a/Pal/src/host/Linux-SGX/pal_linux_defs.h +++ b/Pal/src/host/Linux-SGX/pal_linux_defs.h @@ -18,4 +18,8 @@ #define TRUSTED_STUB_SIZE (PRESET_PAGESIZE * 32) +#define CACHE_FILE_STUBS (1) + +#define USE_AES_NI (1) + #endif /* PAL_LINUX_DEFS_H */ diff --git a/Pal/src/host/Linux-SGX/sgx-driver/gsgx_main.c b/Pal/src/host/Linux-SGX/sgx-driver/gsgx_main.c index e85d2e60..fb5f3bad 100644 --- a/Pal/src/host/Linux-SGX/sgx-driver/gsgx_main.c +++ b/Pal/src/host/Linux-SGX/sgx-driver/gsgx_main.c @@ -28,6 +28,13 @@ MODULE_VERSION(DRV_VERSION); IMPORT_KSYM(dac_mmap_min_addr); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) +static void __enable_fsgsbase(void *v) +{ + write_cr4(read_cr4() | X86_CR4_FSGSBASE); +} +#endif + static long gsgx_ioctl_enclave_create(struct file *filep, unsigned int cmd, unsigned long arg) { @@ -43,7 +50,8 @@ static long gsgx_ioctl_enclave_create(struct file *filep, unsigned int cmd, } #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) - write_cr4(read_cr4() | X86_CR4_FSGSBASE); + __enable_fsgsbase(NULL); + smp_call_function(__enable_fsgsbase, NULL, 1); #endif isgx_create.src = createp->src; diff --git a/Pal/src/host/Linux-SGX/sgx_enclave.c b/Pal/src/host/Linux-SGX/sgx_enclave.c index 659f0578..28c13e12 100644 --- a/Pal/src/host/Linux-SGX/sgx_enclave.c +++ b/Pal/src/host/Linux-SGX/sgx_enclave.c @@ -13,9 +13,14 @@ #include #include #include +#include #include #include +#ifndef SOL_IPV6 +# define SOL_IPV6 41 +#endif + #define PAL_SEC() (¤t_enclave->pal_sec) #define ODEBUG(code, ms) do {} while (0) @@ -294,6 +299,11 @@ static int sgx_ocall_sock_listen(void * pms) } fd = ret; + if (ms->ms_addr->sa_family == AF_INET6) { + int ipv6only = 1; + INLINE_SYSCALL(setsockopt, 5, fd, SOL_IPV6, IPV6_V6ONLY, &ipv6only, + sizeof(int)); + } /* must set the socket to be reuseable */ int reuseaddr = 1; INLINE_SYSCALL(setsockopt, 5, fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, @@ -368,6 +378,12 @@ static int sgx_ocall_sock_connect(void * pms) } fd = ret; + if (ms->ms_addr->sa_family == AF_INET6) { + int ipv6only = 1; + INLINE_SYSCALL(setsockopt, 5, fd, SOL_IPV6, IPV6_V6ONLY, &ipv6only, + sizeof(int)); + } + if (ms->ms_bind_addr && ms->ms_bind_addr->sa_family) { ret = INLINE_SYSCALL(bind, 3, fd, ms->ms_bind_addr, ms->ms_bind_addrlen); diff --git a/Pal/src/host/Linux-SGX/sgx_framework.c b/Pal/src/host/Linux-SGX/sgx_framework.c index 774afc8b..53dda41e 100644 --- a/Pal/src/host/Linux-SGX/sgx_framework.c +++ b/Pal/src/host/Linux-SGX/sgx_framework.c @@ -150,23 +150,28 @@ int create_enclave(sgx_arch_secs_t * secs, struct gsgx_enclave_create param; if (baseaddr) { - secs->baseaddr = (unsigned long) baseaddr & ~(secs->size - 1); + secs->baseaddr = (uint64_t) baseaddr & ~(secs->size - 1); flags |= MAP_FIXED; - } else + } else { secs->baseaddr = 0ULL; + } - secs->baseaddr = INLINE_SYSCALL(mmap, 6, secs->baseaddr, size, - PROT_READ|PROT_WRITE|PROT_EXEC, flags, - isgx_device, 0); + uint64_t addr = INLINE_SYSCALL(mmap, 6, secs->baseaddr, size, + PROT_READ|PROT_WRITE|PROT_EXEC, flags, + isgx_device, 0); - if (IS_ERR_P(secs->baseaddr)) { - if (ERRNO_P(secs->baseaddr) == 1 && (flags | MAP_FIXED)) - pal_printf("Permission denied on mapping enclave. You may need to set sysctl vm.mmap_min_addr to zero\n"); - SGX_DBG(DBG_I, "enclave ECREATE failed in allocating EPC memory - %d\n", ERRNO_P(secs->baseaddr)); + if (IS_ERR_P(addr)) { + if (ERRNO_P(addr) == 1 && (flags | MAP_FIXED)) + pal_printf("Permission denied on mapping enclave. " + "You may need to set sysctl vm.mmap_min_addr to zero\n"); + + SGX_DBG(DBG_I, "enclave ECREATE failed in allocating EPC memory " + "(errno = %d)\n", ERRNO_P(addr)); return -ENOMEM; } - param.src = (unsigned long) secs; + secs->baseaddr = addr; + param.src = (uint64_t) secs; int ret = INLINE_SYSCALL(ioctl, 3, gsgx_device, GSGX_IOCTL_ENCLAVE_CREATE, ¶m); diff --git a/Pal/src/host/Linux/db_exception.c b/Pal/src/host/Linux/db_exception.c index 7b1b07b6..26270b2b 100644 --- a/Pal/src/host/Linux/db_exception.c +++ b/Pal/src/host/Linux/db_exception.c @@ -197,7 +197,7 @@ static struct pal_frame * get_frame (ucontext_t * uc) { unsigned long rip = uc->uc_mcontext.gregs[REG_RIP]; unsigned long rbp = uc->uc_mcontext.gregs[REG_RBP]; - unsigned long last_rbp = rbp - 1024; + unsigned long last_rbp = rbp - 64; if (!ADDR_IN_PAL(rip)) return NULL; @@ -211,7 +211,7 @@ static struct pal_frame * get_frame (ucontext_t * uc) for (unsigned long ptr = rbp - sizeof(unsigned long) ; ptr > last_rbp ; ptr -= 8) { struct pal_frame * frame = (struct pal_frame *) ptr; - if (frame->self == frame) + if (frame->identifier == PAL_FRAME_IDENTIFIER) return frame; } @@ -245,12 +245,16 @@ static void _DkGenericSighandler (int signum, siginfo_t * info, msg[20] = '0' + (pid / 10) % 10; msg[21] = '0' + pid % 10; INLINE_SYSCALL(write, 3, 1, msg, 24); + while(1); } #endif struct pal_frame * frame = get_frame(uc); void * eframe; + if (signum == SIGCONT && frame && frame->func == DkObjectsWaitAny) + return; + asm volatile ("movq %%rbp, %0" : "=r"(eframe)); if (frame && frame->func != &_DkGenericSighandler && diff --git a/Pal/src/host/Linux/db_mutex.c b/Pal/src/host/Linux/db_mutex.c index 6138ab87..eaae165b 100644 --- a/Pal/src/host/Linux/db_mutex.c +++ b/Pal/src/host/Linux/db_mutex.c @@ -42,167 +42,140 @@ #include #ifdef __i386__ +# define barrier() asm volatile("" ::: "memory"); # define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") # define cpu_relax() asm volatile("rep; nop" ::: "memory"); #endif #ifdef __x86_64__ # include +# define barrier() asm volatile("" ::: "memory"); # define rmb() asm volatile("lfence" ::: "memory") # define cpu_relax() asm volatile("rep; nop" ::: "memory"); #endif -#define MUTEX_SPINLOCK_TIMES 20 +#define MUTEX_SPINLOCK_TIMES 100 -int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout) +int _DkMutexLockTimeout (struct mutex_handle * m, int timeout) { - int i, c = 0; + int ret = 0; +#ifdef DEBUG_MUTEX + int tid = INLINE_SYSCALL(gettid, 0); +#endif if (timeout == -1) - return -_DkMutexLock(mut); + return -_DkMutexLock(m); - struct atomic_int * m = &mut->value; - - /* Spin and try to take lock */ - for (i = 0 ; i < MUTEX_SPINLOCK_TIMES ; i++) - { - c = atomic_dec_and_test(m); - if (c) - goto success; - cpu_relax(); - } - - /* The lock is now contended */ - - int ret; + if (!xchg(&m->b.locked, 1)) + goto success; if (timeout == 0) { - ret = c ? 0 : -PAL_ERROR_TRYAGAIN; + ret = -PAL_ERROR_TRYAGAIN; goto out; } - while (!c) { - int val = atomic_read(m); - if (val == 1) - goto again; - + while (xchg(&m->u, 257) & 1) { struct timespec waittime; long sec = timeout / 1000000; long microsec = timeout - (sec * 1000000); waittime.tv_sec = sec; waittime.tv_nsec = microsec * 1000; - ret = INLINE_SYSCALL(futex, 6, m, FUTEX_WAIT, val, &waittime, NULL, 0); + ret = INLINE_SYSCALL(futex, 6, m, FUTEX_WAIT, 257, &waittime, NULL, 0); - if (IS_ERR(ret) && - ERRNO(ret) != EWOULDBLOCK && - ERRNO(ret) != EINTR) { + if (IS_ERR(ret)) { + if (ERRNO(ret) == EWOULDBLOCK) { + xchg(&m->b.contended, 0); + ret = -PAL_ERROR_TRYAGAIN; + goto out; + } +#ifdef DEBUG_MUTEX + printf("futex failed (err = %d)\n", ERRNO(ret)); +#endif ret = unix_to_pal_error(ERRNO(ret)); goto out; } - -#ifdef DEBUG_MUTEX - if (IS_ERR(ret)) - printf("mutex held by thread %d\n", mut->owner); -#endif - -again: - /* Upon wakeup, we still need to check whether mutex is unlocked or - * someone else took it. - * If c==0 upon return from xchg (i.e., the older value of m==0), we - * will exit the loop. Else, we sleep again (through a futex call). - */ - c = atomic_dec_and_test(m); } success: #ifdef DEBUG_MUTEX - mut->owner = INLINE_SYSCALL(gettid, 0); + m->owner = tid; #endif ret = 0; out: +#ifdef DEBUG_MUTEX + if (ret < 0) + printf("mutex failed (%e, tid = %d)\n", -ret, tid); +#endif return ret; } -int _DkMutexLock (struct mutex_handle * mut) +int _DkMutexLock (struct mutex_handle * m) { - int i, c = 0; - int ret; - struct atomic_int * m = &mut->value; + int ret = 0, i; +#ifdef DEBUG_MUTEX + int tid = INLINE_SYSCALL(gettid, 0); +#endif /* Spin and try to take lock */ for (i = 0; i < MUTEX_SPINLOCK_TIMES; i++) { - c = atomic_dec_and_test(m); - if (c) + if (!xchg(&m->b.locked, 1)) goto success; cpu_relax(); } - /* The lock is now contended */ - - while (!c) { - int val = atomic_read(m); - if (val == 1) - goto again; - - ret = INLINE_SYSCALL(futex, 6, m, FUTEX_WAIT, val, NULL, NULL, 0); + while (xchg(&m->u, 257) & 1) { + ret = INLINE_SYSCALL(futex, 6, m, FUTEX_WAIT, 257, NULL, NULL, 0); if (IS_ERR(ret) && - ERRNO(ret) != EWOULDBLOCK && - ERRNO(ret) != EINTR) { + ERRNO(ret) != EWOULDBLOCK) { +#ifdef DEBUG_MUTEX + printf("futex failed (err = %d)\n", ERRNO(ret)); +#endif ret = unix_to_pal_error(ERRNO(ret)); goto out; } - -#ifdef DEBUG_MUTEX - if (IS_ERR(ret)) - printf("mutex held by thread %d\n", mut->owner); -#endif - -again: - /* Upon wakeup, we still need to check whether mutex is unlocked or - * someone else took it. - * If c==0 upon return from xchg (i.e., the older value of m==0), we - * will exit the loop. Else, we sleep again (through a futex call). - */ - c = atomic_dec_and_test(m); } success: #ifdef DEBUG_MUTEX - mut->owner = INLINE_SYSCALL(gettid, 0); + m->owner = tid; #endif ret = 0; out: +#ifdef DEBUG_MUTEX + if (ret < 0) + printf("mutex failed (%e, tid = %d)\n", -ret, tid); +#endif return ret; } -int _DkMutexUnlock (struct mutex_handle * mut) +int _DkMutexUnlock (struct mutex_handle * m) { - int ret = 0; - int must_wake = 0; - struct atomic_int * m = &mut->value; + int ret = 0, i; #ifdef DEBUG_MUTEX - mut->owner = 0; + m->owner = 0; #endif /* Unlock, and if not contended then exit. */ - if (atomic_read(m) < 0) - must_wake = 1; + if ((m->u == 1) && (cmpxchg(&m->u, 1, 0) == 1)) return 0; + m->b.locked = 0; + barrier(); - atomic_set(m, 1); - - if (must_wake) { - /* We need to wake someone up */ - ret = INLINE_SYSCALL(futex, 6, m, FUTEX_WAKE, 1, NULL, NULL, 0); + /* Spin and try to take lock */ + for (i = 0; i < MUTEX_SPINLOCK_TIMES * 2; i++) { + if (m->b.locked) + goto success; + cpu_relax(); } - if (IS_ERR(ret)) { - ret = -PAL_ERROR_TRYAGAIN; - goto out; - } + m->b.contended = 0; + /* We need to wake someone up */ + INLINE_SYSCALL(futex, 6, m, FUTEX_WAKE, 1, NULL, NULL, 0); + +success: ret = 0; out: return ret; diff --git a/Pal/src/host/Linux/db_pipes.c b/Pal/src/host/Linux/db_pipes.c index 58be943f..85fcb18d 100644 --- a/Pal/src/host/Linux/db_pipes.c +++ b/Pal/src/host/Linux/db_pipes.c @@ -529,22 +529,29 @@ static int pipe_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) attr->handle_type = PAL_GET_TYPE(handle); - if (attr->handle_type == pal_type_pipe) { + if (attr->handle_type != pal_type_pipesrv) { ret = INLINE_SYSCALL(ioctl, 3, HANDLE_HDR(handle)->fds[0], FIONREAD, &val); if (IS_ERR(ret)) { return unix_to_pal_error(ERRNO(ret)); } + + attr->readable = val > 0; + attr->pending_size = val; + attr->writeable = HANDLE_HDR(handle)->flags & ( + (PAL_GET_TYPE(handle) == pal_type_pipeprv) ? WRITEABLE(1) : + WRITEABLE(0)); + } else { + struct pollfd pfd = { .fd = HANDLE_HDR(handle)->fds[0], .events = POLLIN, .revents = 0 }; + struct timespec tp = { 0, 0 }; + ret = INLINE_SYSCALL(ppoll, 5, &pfd, 1, &tp, NULL, 0); + attr->readable = (ret == 1 && pfd.revents == POLLIN); + attr->pending_size = 0; + attr->writeable = PAL_FALSE; } attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0); - attr->nonblocking = (HANDLE_HDR(handle)->type == pal_type_pipeprv) ? + attr->nonblocking = (PAL_GET_TYPE(handle) == pal_type_pipeprv) ? handle->pipeprv.nonblocking : handle->pipe.nonblocking; - attr->readable = val > 0; - if (PAL_GET_TYPE(handle) == pal_type_pipeprv) - attr->writeable = HANDLE_HDR(handle)->flags & WRITEABLE(1); - else - attr->writeable = HANDLE_HDR(handle)->flags & WRITEABLE(0); - attr->pending_size = val; return 0; } diff --git a/Pal/src/host/Linux/db_semaphore.c b/Pal/src/host/Linux/db_semaphore.c index 56a717fd..e7390ad6 100644 --- a/Pal/src/host/Linux/db_semaphore.c +++ b/Pal/src/host/Linux/db_semaphore.c @@ -69,7 +69,7 @@ _DkSemaphoreCreate (PAL_HANDLE handle, int initialCount, int maxCount) /* optimization: if maxCount == 1, we make it into mutex */ if (handle->semaphore.max_value == 1) { - atomic_set(&handle->semaphore.value.mut.value, 1 - initialCount); + handle->semaphore.value.mut.u = initialCount; } else { atomic_set(&handle->semaphore.value.i, maxCount - initialCount); } @@ -255,9 +255,8 @@ void _DkSemaphoreRelease (PAL_HANDLE sem, int count) int _DkSemaphoreGetCurrentCount (PAL_HANDLE sem) { if (sem->semaphore.max_value == 1) { - struct mutex_handle * mut = - &sem->semaphore.value.mut; - return atomic_read(&mut->value); + struct mutex_handle * m = &sem->semaphore.value.mut; + return m->b.locked; } int c = atomic_read(&sem->semaphore.value.i); diff --git a/Pal/src/host/Linux/db_sockets.c b/Pal/src/host/Linux/db_sockets.c index d3dd44f2..22f80633 100644 --- a/Pal/src/host/Linux/db_sockets.c +++ b/Pal/src/host/Linux/db_sockets.c @@ -45,6 +45,22 @@ typedef __kernel_pid_t pid_t; #include #include +#ifndef SOL_TCP +# define SOL_TCP 6 +#endif + +#ifndef TCP_NODELAY +# define TCP_NODELAY 1 +#endif + +#ifndef TCP_CORK +# define TCP_CORK 3 +#endif + +#ifndef SOL_IPV6 +# define SOL_IPV6 41 +#endif + /* 96 bytes is the minimal size of buffer to store a IPv4/IPv6 address */ #define PAL_SOCKADDR_SIZE 96 @@ -345,6 +361,12 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options) if (IS_ERR(fd)) return -PAL_ERROR_DENIED; + if (bind_addr->sa_family == AF_INET6) { + int ipv6only = 1; + INLINE_SYSCALL(setsockopt, 5, fd, SOL_IPV6, IPV6_V6ONLY, &ipv6only, + sizeof(int)); + } + /* must set the socket to be reuseable */ int reuseaddr = 1; INLINE_SYSCALL(setsockopt, 5, fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, @@ -474,6 +496,12 @@ static int tcp_connect (PAL_HANDLE * handle, char * uri, int options) } } + if (dest_addr->sa_family == AF_INET6) { + int ipv6only = 1; + INLINE_SYSCALL(setsockopt, 5, fd, SOL_IPV6, IPV6_V6ONLY, &ipv6only, + sizeof(int)); + } + ret = INLINE_SYSCALL(connect, 3, fd, dest_addr, dest_addrlen); if (IS_ERR(ret)) { @@ -629,6 +657,12 @@ static int udp_bind (PAL_HANDLE * handle, char * uri, int options) if (IS_ERR(fd)) return -PAL_ERROR_DENIED; + if (bind_addr->sa_family == AF_INET6) { + int ipv6only = 1; + INLINE_SYSCALL(setsockopt, 5, fd, SOL_IPV6, IPV6_V6ONLY, &ipv6only, + sizeof(int)); + } + ret = INLINE_SYSCALL(bind, 3, fd, bind_addr, bind_addrlen); if (IS_ERR(ret)) { @@ -678,6 +712,12 @@ static int udp_connect (PAL_HANDLE * handle, char * uri, int options) if (IS_ERR(fd)) return -PAL_ERROR_DENIED; + if (dest_addr->sa_family == AF_INET6) { + int ipv6only = 1; + INLINE_SYSCALL(setsockopt, 5, fd, SOL_IPV6, IPV6_V6ONLY, &ipv6only, + sizeof(int)); + } + if (bind_addr) { ret = INLINE_SYSCALL(bind, 3, fd, bind_addr, bind_addrlen); @@ -1000,7 +1040,12 @@ static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) int fd = handle->sock.fd, ret, val; - if (handle->sock.conn) { + if (IS_HANDLE_TYPE(handle, tcpsrv)) { + struct pollfd pfd = { .fd = fd, .events = POLLIN, .revents = 0 }; + struct timespec tp = { 0, 0 }; + ret = INLINE_SYSCALL(ppoll, 5, &pfd, 1, &tp, NULL, 0); + attr->readable = (ret == 1 && pfd.revents == POLLIN); + } else { /* try use ioctl FIONEAD to get the size of socket */ ret = INLINE_SYSCALL(ioctl, 3, fd, FIONREAD, &val); if (IS_ERR(ret)) @@ -1008,8 +1053,6 @@ static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) attr->pending_size = val; attr->readable = !!attr->pending_size > 0; - } else { - attr->readable = !attr->disconnected; } return 0; diff --git a/Pal/src/host/Linux/pal_host.h b/Pal/src/host/Linux/pal_host.h index 3b667cb4..f767e0ca 100644 --- a/Pal/src/host/Linux/pal_host.h +++ b/Pal/src/host/Linux/pal_host.h @@ -30,20 +30,27 @@ # error "cannot be included outside PAL" #endif +#define DEBUG_MUTEX 1 + /* internal Mutex design, the structure has to align at integer boundary because it is required by futex call. If DEBUG_MUTEX is defined, mutex_handle will record the owner of mutex locking. */ typedef struct mutex_handle { - struct atomic_int value; + union { + unsigned int u; + struct { + unsigned char locked; + unsigned char contended; + } b; + }; #ifdef DEBUG_MUTEX int owner; #endif } PAL_LOCK; /* Initializer of Mutexes */ -#define MUTEX_HANDLE_INIT { .value = { .counter = 1 } } -#define INIT_MUTEX_HANDLE(mut) \ - do { atomic_set(&(mut)->value, 1); } while (0) +#define MUTEX_HANDLE_INIT { .u = 0 } +#define INIT_MUTEX_HANDLE(m) do { m->u = 0; } while (0) #define LOCK_INIT MUTEX_HANDLE_INIT #define INIT_LOCK(lock) INIT_MUTEX_HANDLE(lock); @@ -224,8 +231,10 @@ struct arch_frame { # error "unsupported architecture" #endif +#define PAL_FRAME_IDENTIFIER (0xdeaddeadbeefbeef) + struct pal_frame { - volatile struct pal_frame * self; + volatile uint64_t identifier; void * func; const char * funcname; struct arch_frame arch; @@ -236,9 +245,10 @@ void __store_frame (struct pal_frame * frame, void * func, const char * funcname) { arch_store_frame(&frame->arch) - *(volatile void **) &frame->self = frame; frame->func = func; frame->funcname = funcname; + asm volatile ("nop" ::: "memory"); + frame->identifier = PAL_FRAME_IDENTIFIER; } #define ENTER_PAL_CALL(name) \ @@ -249,9 +259,9 @@ void __store_frame (struct pal_frame * frame, static inline void __clear_frame (struct pal_frame * frame) { - if (*(volatile void **) &frame->self == frame) { + if (frame->identifier == PAL_FRAME_IDENTIFIER) { asm volatile ("nop" ::: "memory"); - *(volatile void **) &frame->self = NULL; + frame->identifier = 0; } }