From 170407825fafe2f06f7406d5262dc113462dd834 Mon Sep 17 00:00:00 2001 From: Wentong Wu Date: Mon, 26 Oct 2020 10:25:37 -0400 Subject: [PATCH 1/2] arch: arm: push ssf to thread privileged stack to complete stack frame All system call handlers have the same prototype: u32_t _handler_APINAME(u32_t arg1, u32_t arg2, u32_t arg3, u32_t arg4, u32_t arg5, u32_t arg6, void *ssf); This commit pushes the seventh argument named ssf to thread's privileged stack to avoid mis-understanding the stack layout with compiler. Fixes: #29386. Signed-off-by: Wentong Wu --- arch/arm/core/userspace.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/core/userspace.S b/arch/arm/core/userspace.S index 60888c08cba7..3996a25654cf 100644 --- a/arch/arm/core/userspace.S +++ b/arch/arm/core/userspace.S @@ -232,8 +232,9 @@ SECTION_FUNC(TEXT, z_arm_do_syscall) b dispatch_syscall valid_syscall: + mov ip, sp /* push args to complete stack frame */ - push {r4,r5} + push {r4,r5,ip} dispatch_syscall: ldr ip, =_k_syscall_table @@ -244,7 +245,7 @@ dispatch_syscall: blx ip /* restore LR */ - ldr lr, [sp,#12] + ldr lr, [sp,#16] #if defined(CONFIG_BUILTIN_STACK_GUARD) /* clear stack limit (stack protection not required in user mode) */ @@ -253,7 +254,7 @@ dispatch_syscall: #endif /* set stack back to unprivileged stack */ - ldr ip, [sp,#8] + ldr ip, [sp,#12] msr PSP, ip push {r0, r1} From cc6ac9d07e5351395de4333f613114627c9ee3b6 Mon Sep 17 00:00:00 2001 From: Wentong Wu Date: Mon, 26 Oct 2020 20:47:44 +0800 Subject: [PATCH 2/2] tests: kernel: syscalls: add more than 6 arguments syscall test case Add more than 6 arguments syscall test case. Signed-off-by: Wentong Wu --- tests/kernel/mem_protect/syscalls/src/main.c | 33 +++++++++++++++++++ .../mem_protect/syscalls/src/test_syscalls.h | 5 +++ 2 files changed, 38 insertions(+) diff --git a/tests/kernel/mem_protect/syscalls/src/main.c b/tests/kernel/mem_protect/syscalls/src/main.c index ddf6a384630b..45880cdb7ac8 100644 --- a/tests/kernel/mem_protect/syscalls/src/main.c +++ b/tests/kernel/mem_protect/syscalls/src/main.c @@ -94,6 +94,31 @@ Z_SYSCALL_HANDLER(to_copy, dest) return z_user_to_copy((char *)dest, user_string, BUF_SIZE); } +unsigned int z_impl_more_args(unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int arg4, + unsigned int arg5, unsigned int arg6, + unsigned int arg7) +{ + unsigned int ret = 0x4ef464cc; + unsigned int args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }; + + for (int i = 0; i < ARRAY_SIZE(args); i++) { + ret += args[i]; + ret = (ret << 11) | (ret >> 5); + } + + return ret; +} + +Z_SYSCALL_HANDLER(more_args, arg1, arg2, arg3, arg4, arg5, more_args_ptr) +{ + struct _syscall_7_args *margs = + (struct _syscall_7_args *)more_args_ptr; + + return z_impl_more_args(arg1, arg2, arg3, arg4, + arg5, margs->arg6, margs->arg7); +} + /** * @brief Test to demonstrate usage of z_user_string_nlen() * @@ -199,6 +224,13 @@ void test_to_copy(void) zassert_equal(ret, 0, "string should have matched"); } +void test_more_args(void) +{ + zassert_equal(more_args(1, 2, 3, 4, 5, 6, 7), + z_impl_more_args(1, 2, 3, 4, 5, 6, 7), + "syscall didn't match impl"); +} + K_MEM_POOL_DEFINE(test_pool, BUF_SIZE, BUF_SIZE, 4, 4); void test_main(void) @@ -211,6 +243,7 @@ void test_main(void) ztest_unit_test(test_string_nlen), ztest_user_unit_test(test_string_nlen), ztest_user_unit_test(test_to_copy), + ztest_user_unit_test(test_more_args), ztest_user_unit_test(test_user_string_copy), ztest_user_unit_test(test_user_string_alloc_copy)); ztest_run_test_suite(syscalls); diff --git a/tests/kernel/mem_protect/syscalls/src/test_syscalls.h b/tests/kernel/mem_protect/syscalls/src/test_syscalls.h index 9c0645b0088e..88677288e7cc 100644 --- a/tests/kernel/mem_protect/syscalls/src/test_syscalls.h +++ b/tests/kernel/mem_protect/syscalls/src/test_syscalls.h @@ -16,6 +16,11 @@ __syscall int to_copy(char *dest); __syscall size_t string_nlen(char *src, size_t maxlen, int *err); +__syscall unsigned int more_args(unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int arg4, + unsigned int arg5, unsigned int arg6, + unsigned int arg7); + #include #endif /* _TEST_SYSCALLS_H_ */