diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 6995e7dc9da6ae2c9af517779ca3bc54e475efc1..88e8f7c33c9bfbe8cc545eafd6fa08aa69a90e4a 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef ARCH_MM_MMU @@ -1312,12 +1313,22 @@ rt_err_t sys_rt_timer_control(rt_timer_t timer, int cmd, void *arg) return rt_timer_control(timer, cmd, arg); } +/* MUSL compatible */ +struct ksigevent +{ + union sigval sigev_value; + int sigev_signo; + int sigev_notify; + int sigev_tid; +}; + rt_err_t sys_timer_create(clockid_t clockid, struct sigevent *restrict sevp, timer_t *restrict timerid) { int ret = 0; #ifdef ARCH_MM_MMU struct sigevent sevp_k; timer_t timerid_k; + int utimer; if (sevp == NULL) { @@ -1326,12 +1337,28 @@ rt_err_t sys_timer_create(clockid_t clockid, struct sigevent *restrict sevp, tim sevp = &sevp_k; } else - lwp_get_from_user(&sevp_k, (void *)sevp, sizeof sevp_k); - lwp_get_from_user(&timerid_k, (void *)timerid, sizeof timerid_k); + { + /* clear extra bytes if any */ + if (sizeof(struct ksigevent) < sizeof(struct sigevent)) + memset(&sevp_k, 0, sizeof(sevp_k)); + + /* musl passes `struct ksigevent` to kernel, we shoule only get size of that bytes */ + lwp_get_from_user(&sevp_k, (void *)sevp, sizeof(struct ksigevent)); + } + lwp_get_from_user(&timerid_k, (void *)timerid, sizeof(timerid_k)); + + /* to protect unsafe implementation in current rt-smart toolchain */ + RT_ASSERT(((struct ksigevent *)sevp)->sigev_tid == (rt_ubase_t)sevp_k.sigev_notify_function); + ret = timer_create(clockid, &sevp_k, &timerid_k); + + /* ID should not extend 32-bits size for libc */ + RT_ASSERT((rt_ubase_t)timerid_k < UINT32_MAX); + utimer = (rt_ubase_t)timerid_k; + if (ret != -RT_ERROR){ - lwp_put_to_user(sevp, (void *)&sevp_k, sizeof sevp_k); - lwp_put_to_user(timerid, (void *)&timerid_k, sizeof timerid_k); + lwp_put_to_user(sevp, (void *)&sevp_k, sizeof(struct ksigevent)); + lwp_put_to_user(timerid, (void *)&utimer, sizeof(utimer)); } #else ret = timer_create(clockid, sevp, timerid); @@ -1354,8 +1381,12 @@ rt_err_t sys_timer_settime(timer_t timerid, int flags, struct itimerspec new_value_k; struct itimerspec old_value_k; - lwp_get_from_user(&new_value_k, (void *)new_value, sizeof new_value_k); - lwp_get_from_user(&old_value_k, (void *)timerid, sizeof old_value_k); + if (!lwp_get_from_user(&new_value_k, (void *)new_value, sizeof(*new_value)) || + (old_value && !lwp_get_from_user(&old_value_k, (void *)old_value, sizeof(*old_value)))) + { + return -EFAULT; + } + ret = timer_settime(timerid, flags, &new_value_k, &old_value_k); lwp_put_to_user(old_value, (void *)&old_value_k, sizeof old_value_k);