uti: Replace data types represented as arrays with C structures
Defining C structures for the following objects: (1) Remote and local context (2) Stack of system call arguments / return values Change-Id: Iafbb6c795bd765e3c78c54a255d8a1e4d4536288
This commit is contained in:
@@ -1,15 +1,22 @@
|
||||
/*
|
||||
arg: rdi, rsi, rdx, rcx, r8, r9
|
||||
ret: rax
|
||||
Calling convention:
|
||||
arg: rdi, rsi, rdx, rcx, r8, r9
|
||||
ret: rax
|
||||
|
||||
rax syscall number
|
||||
syscall: (rax:num) rdi rsi rdx r10 r8 r9 (rcx:ret addr)
|
||||
fd, cmd, param
|
||||
rdi: fd
|
||||
rsi: cmd
|
||||
rdx: param
|
||||
rcx: save area
|
||||
r8: new thread context
|
||||
rdi: fd
|
||||
rsi: cmd
|
||||
rdx: param
|
||||
rcx: save area
|
||||
r8: new thread context
|
||||
|
||||
Syscam call convention:
|
||||
syscall number: rax
|
||||
arg: rdi, rsi, rdx, r10, r8, r9
|
||||
return addr: rcx
|
||||
|
||||
rdi: fd
|
||||
rsi: cmd
|
||||
rdx: param
|
||||
*/
|
||||
|
||||
.global switch_ctx
|
||||
@@ -91,6 +98,7 @@ switch_ctx:
|
||||
|
||||
1:
|
||||
mov $0xffffffffffffffff,%eax
|
||||
retq
|
||||
2:
|
||||
pushq %rax
|
||||
movq $158,%rax /* arch_prctl */
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
extern int switch_ctx(int fd, unsigned long cmd, void **param, void *lctx, void *rctx);
|
||||
#include "../include/uprotocol.h"
|
||||
|
||||
extern int switch_ctx(int fd, unsigned long cmd, struct uti_save_fs_desc *desc, void *lctx, void *rctx);
|
||||
extern unsigned long compare_and_swap(unsigned long *addr, unsigned long old, unsigned long new);
|
||||
extern unsigned int compare_and_swap_int(unsigned int *addr, unsigned int old, unsigned int new);
|
||||
extern int archdep_syscall(struct syscall_wait_desc *w, long *ret);
|
||||
|
||||
@@ -2881,18 +2881,18 @@ static void kill_thread(unsigned long tid, int sig)
|
||||
}
|
||||
}
|
||||
|
||||
static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa, int remote_tid, unsigned long pattr, unsigned long uti_clv, unsigned long _uti_desc)
|
||||
static long util_thread(struct thread_data_s *my_thread, unsigned long rp_rctx, int remote_tid, unsigned long pattr, unsigned long uti_clv, unsigned long _uti_desc)
|
||||
{
|
||||
int i;
|
||||
void *lctx;
|
||||
void *rctx;
|
||||
void *param[7];
|
||||
struct uti_get_ctx_desc get_ctx_desc;
|
||||
struct uti_save_fs_desc save_fs_desc;
|
||||
int rc = 0;
|
||||
void *uti_wp = (void*)-1;
|
||||
|
||||
struct thread_data_s *tp;
|
||||
|
||||
pthread_barrier_init(&uti_init_ready, NULL, 2);
|
||||
if ((rc = create_worker_thread(&tp, &uti_init_ready))) {
|
||||
printf("%s: Error: create_worker_thread failed (%d)\n", __FUNCTION__, rc);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pthread_barrier_wait(&uti_init_ready);
|
||||
@@ -2900,18 +2900,12 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
||||
|
||||
uti_desc = (struct uti_desc *)_uti_desc;
|
||||
if (!uti_desc) {
|
||||
fprintf(stderr, "%s: ERROR: uti_desc isn't set. Use mcexec.sh instead of mcexec\n", __FUNCTION__);
|
||||
exit(1);
|
||||
printf("%s: ERROR: uti_desc isn't set. Use mcexec.sh instead of mcexec\n", __FUNCTION__);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Initialize uti related variables for syscall_intercept */
|
||||
|
||||
uti_wp = mmap(NULL, PAGE_SIZE * 3, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
if (uti_wp == (void *)-1) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uti_desc->fd = fd;
|
||||
|
||||
rc = syscall(888);
|
||||
@@ -2919,42 +2913,21 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
||||
fprintf(stderr, "%s: WARNING: syscall_intercept returned %x\n", __FUNCTION__, rc);
|
||||
}
|
||||
|
||||
/* Get the context of the thread migrating to Linux */
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_35
|
||||
lctx = (char *)uti_wp + page_size;
|
||||
rctx = (char *)lctx + page_size;
|
||||
#else
|
||||
lctx = (char *)uti_wp + PAGE_SIZE;
|
||||
rctx = (char *)lctx + PAGE_SIZE;
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_35 */
|
||||
/* Get the remote context, record refill tid */
|
||||
get_ctx_desc.rp_rctx = rp_rctx;
|
||||
get_ctx_desc.rctx = uti_desc->rctx;
|
||||
get_ctx_desc.lctx = uti_desc->lctx;
|
||||
get_ctx_desc.uti_refill_tid = tp->tid;
|
||||
|
||||
param[0] = (void *)uctx_pa; /* Source address, kernel space */
|
||||
param[1] = rctx; /* Destination address, user space */
|
||||
param[2] = lctx;
|
||||
param[4] = uti_desc->wp;
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_35
|
||||
param[5] = (void *)(page_size * 3);
|
||||
#else /* POSTK_DEBUG_ARCH_DEP_35 */
|
||||
param[5] = (void *)(PAGE_SIZE * 3);
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_35 */
|
||||
param[6] = (void *)tp->tid;
|
||||
printf("%s: param[6]=%ld,tid=%ld\n", __FUNCTION__, (long)param[6], (long)((void *)tp->tid));
|
||||
|
||||
__dprintf("%s: before MCEXEC_UP_UTIL_THREAD1\n", __FUNCTION__);
|
||||
|
||||
/* 1. Copy context from kernel space to user space
|
||||
2. Write uti_wp addr, its size for McKernel to uctx_pa
|
||||
Note that this overwrites context */
|
||||
if ((rc = ioctl(fd, MCEXEC_UP_UTIL_THREAD1, param)) == -1) {
|
||||
fprintf(stderr, "util_thread1: %d errno=%d\n", rc, errno);
|
||||
if ((rc = ioctl(fd, MCEXEC_UP_UTI_GET_CTX, &get_ctx_desc))) {
|
||||
fprintf(stderr, "%s: Error: MCEXEC_UP_UTI_GET_CTX failed (%d)\n", __FUNCTION__, errno);
|
||||
rc = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Record the info of the thread migrating to Linux */
|
||||
uti_desc->wp = uti_wp;
|
||||
/* Initialize uti thread info */
|
||||
uti_desc->mck_tid = remote_tid;
|
||||
uti_desc->key = (unsigned long)param[3]; /* key to find thread, i.e. struct task_struct * */
|
||||
uti_desc->key = get_ctx_desc.key;
|
||||
uti_desc->pid = getpid();
|
||||
uti_desc->tid = gettid();
|
||||
uti_desc->uti_clv = uti_clv;
|
||||
@@ -2965,12 +2938,6 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
for (i = 1; i <= 10; i++) {
|
||||
uti_desc->syscall_param = (struct syscall_struct *)uti_desc->wp + i;
|
||||
*(void **)uti_desc->syscall_param = uti_desc->syscall_param_top;
|
||||
uti_desc->syscall_param_top = uti_desc->syscall_param;
|
||||
}
|
||||
memset(uti_desc->wp, '\0', sizeof(long));
|
||||
|
||||
if (pattr) {
|
||||
struct uti_attr_desc desc;
|
||||
@@ -2979,30 +2946,22 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
||||
ioctl(fd, MCEXEC_UP_UTI_ATTR, &desc);
|
||||
}
|
||||
|
||||
/* McKernel would create the thread detached, so detach myself */
|
||||
if ((rc = pthread_detach(my_thread->thread_id)) < 0) {
|
||||
fprintf(stderr, "%s: ERROR pthread_detach returned %d\n", __FUNCTION__, rc);
|
||||
goto out;
|
||||
}
|
||||
my_thread->detached = 1;
|
||||
|
||||
/* Start intercepting syscalls. Note that it dereferences pointers in uti_desc. */
|
||||
uti_desc->start_syscall_intercept = 1;
|
||||
|
||||
if ((rc = switch_ctx(fd, MCEXEC_UP_UTIL_THREAD2, param, lctx, rctx))
|
||||
/* Save remote and local FS and then contex-switch */
|
||||
save_fs_desc.rctx = uti_desc->rctx;
|
||||
save_fs_desc.lctx = uti_desc->lctx;
|
||||
|
||||
if ((rc = switch_ctx(fd, MCEXEC_UP_UTI_SAVE_FS, &save_fs_desc, uti_desc->lctx, uti_desc->rctx))
|
||||
< 0) {
|
||||
fprintf(stderr, "%s: ERROR switch_ctx returned %d\n", __FUNCTION__, rc);
|
||||
fprintf(stderr, "%s: ERROR switch_ctx failed (%d)\n", __FUNCTION__, rc);
|
||||
goto out;
|
||||
}
|
||||
fprintf(stderr, "return from util_thread2 rc=%d\n", rc);
|
||||
pthread_exit(NULL);
|
||||
fprintf(stderr, "%s: ERROR: Returned from switch_ctx (%d)\n", __FUNCTION__, rc);
|
||||
rc = -EINVAL;
|
||||
|
||||
out:
|
||||
if (uti_desc != (void*)-1 && uti_desc->wp != (void*)-1)
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_35
|
||||
munmap(uti_desc->wp, page_size * 3);
|
||||
#else /* POSTK_DEBUG_ARCH_DEP_35 */
|
||||
munmap(uti_desc->wp, PAGE_SIZE * 3);
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_35 */
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4078,10 +4037,8 @@ return_execve2:
|
||||
w.sr.args[2], w.sr.args[3], w.sr.args[4]);
|
||||
}
|
||||
else {
|
||||
ret = munmap((void *)w.sr.args[1],
|
||||
w.sr.args[2]);
|
||||
if (ret == -1)
|
||||
ret = -errno;
|
||||
__eprintf("__NR_sched_setaffinity: invalid argument (%lx)\n", w.sr.args[0]);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
@@ -24,6 +24,7 @@ hook(long syscall_number,
|
||||
int tid = uti_syscall0(__NR_gettid);
|
||||
struct terminate_thread_desc term_desc;
|
||||
unsigned long code;
|
||||
int stack_top;
|
||||
|
||||
if (!uti_desc.start_syscall_intercept) {
|
||||
return 1; /* System call isn't taken over */
|
||||
@@ -50,34 +51,40 @@ hook(long syscall_number,
|
||||
case __NR_munmap:
|
||||
case __NR_mprotect:
|
||||
case __NR_mremap:
|
||||
if (!uti_desc.syscall_param_top) {
|
||||
/* Overflow check */
|
||||
if (uti_desc.syscall_stack_top == -1) {
|
||||
*result = -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* Pop syscall_struct list for reentrant safety */
|
||||
uti_desc.syscall_param = uti_desc.syscall_param_top;
|
||||
uti_desc.syscall_param_top = *(void **)uti_desc.syscall_param;
|
||||
|
||||
uti_desc.syscall_param->number = syscall_number;
|
||||
uti_desc.syscall_param->args[0] = arg0;
|
||||
uti_desc.syscall_param->args[1] = arg1;
|
||||
uti_desc.syscall_param->args[2] = arg2;
|
||||
uti_desc.syscall_param->args[3] = arg3;
|
||||
uti_desc.syscall_param->args[4] = arg4;
|
||||
uti_desc.syscall_param->args[5] = arg5;
|
||||
uti_desc.syscall_param->uti_clv = uti_desc.uti_clv;
|
||||
uti_desc.syscall_param->ret = -EINVAL;
|
||||
uti_syscall3(__NR_ioctl, uti_desc.fd, MCEXEC_UP_SYSCALL_THREAD, (long)uti_desc.syscall_param);
|
||||
*result = uti_desc.syscall_param->ret;
|
||||
|
||||
/* push syscall_struct list */
|
||||
*(void **)uti_desc.syscall_param = uti_desc.syscall_param_top;
|
||||
uti_desc.syscall_param_top = uti_desc.syscall_param;
|
||||
|
||||
return 0; /* System call is taken over */
|
||||
|
||||
/* Sanity check */
|
||||
if (uti_desc.syscall_stack_top < 0 || uti_desc.syscall_stack_top >= UTI_SZ_SYSCALL_STACK) {
|
||||
*result = -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Store the return value in the stack to prevent it from getting corrupted
|
||||
when an interrupt happens just after ioctl() and before copying the return
|
||||
value to *result */
|
||||
stack_top = __sync_fetch_and_sub(&uti_desc.syscall_stack_top, 1);
|
||||
|
||||
uti_desc.syscall_stack[stack_top].number = syscall_number;
|
||||
uti_desc.syscall_stack[stack_top].args[0] = arg0;
|
||||
uti_desc.syscall_stack[stack_top].args[1] = arg1;
|
||||
uti_desc.syscall_stack[stack_top].args[2] = arg2;
|
||||
uti_desc.syscall_stack[stack_top].args[3] = arg3;
|
||||
uti_desc.syscall_stack[stack_top].args[4] = arg4;
|
||||
uti_desc.syscall_stack[stack_top].args[5] = arg5;
|
||||
uti_desc.syscall_stack[stack_top].uti_clv = uti_desc.uti_clv;
|
||||
uti_desc.syscall_stack[stack_top].ret = -EINVAL;
|
||||
|
||||
uti_syscall3(__NR_ioctl, uti_desc.fd, MCEXEC_UP_SYSCALL_THREAD, (long)(uti_desc.syscall_stack + stack_top));
|
||||
*result = uti_desc.syscall_stack[stack_top].ret;
|
||||
|
||||
/* push syscall_struct list */
|
||||
__sync_fetch_and_add(&uti_desc.syscall_stack_top, 1);
|
||||
|
||||
return 0; /* System call is taken over */
|
||||
case __NR_exit_group:
|
||||
code = 0x100000000;
|
||||
goto make_remote_thread_exit;
|
||||
@@ -116,9 +123,13 @@ hook(long syscall_number,
|
||||
static __attribute__((constructor)) void
|
||||
init(void)
|
||||
{
|
||||
// Set up the callback function
|
||||
/* Set up the callback function */
|
||||
intercept_hook_point = hook;
|
||||
|
||||
|
||||
/* Initialize uti_desc */
|
||||
uti_desc.syscall_stack_top = UTI_SZ_SYSCALL_STACK - 1;
|
||||
|
||||
/* Pass address of uti_desc to McKernel */
|
||||
uti_syscall1(733, (unsigned long)&uti_desc);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user