There is a pointer to ssize_t part of the ABI. The pointer itself is autocorrected by the syscall enter machinery, but when reading/writing we have to care about different sizes between compat and native case.
Signed-off-by: Florian Bezdeka <[email protected]> --- .../x86/include/asm/xenomai/syscall32-table.h | 1 + kernel/cobalt/posix/mqueue.c | 26 +++++++++---------- kernel/cobalt/posix/mqueue.h | 2 +- kernel/cobalt/posix/syscall32.c | 17 ++++++++++-- kernel/cobalt/posix/syscall32.h | 3 ++- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h b/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h index fb55d8863..3c9c287e1 100644 --- a/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h @@ -63,5 +63,6 @@ __COBALT_CALL32emu_THUNK(recvmsg) __COBALT_CALL32emu_THUNK(sendmsg) __COBALT_CALL32emu_THUNK(mmap) __COBALT_CALL32emu_THUNK(backtrace) +__COBALT_CALL32emu_THUNK(mq_timedreceive64) #endif /* !_COBALT_X86_ASM_SYSCALL32_TABLE_H */ diff --git a/kernel/cobalt/posix/mqueue.c b/kernel/cobalt/posix/mqueue.c index d0a6d4e31..3514ba1b0 100644 --- a/kernel/cobalt/posix/mqueue.c +++ b/kernel/cobalt/posix/mqueue.c @@ -1048,21 +1048,12 @@ fail: } int __cobalt_mq_timedreceive64(mqd_t uqd, void __user *u_buf, - ssize_t __user *u_len, + ssize_t *len, unsigned int __user *u_prio, const void __user *u_ts) { - ssize_t len; - int ret; - - ret = cobalt_copy_from_user(&len, u_len, sizeof(len)); - if (ret) - return ret; - - ret = __cobalt_mq_timedreceive(uqd, u_buf, &len, u_prio, u_ts, - u_ts ? mq_fetch_timeout64 : NULL); - - return ret ?: cobalt_copy_to_user(u_len, &len, sizeof(*u_len)); + return __cobalt_mq_timedreceive(uqd, u_buf, len, u_prio, u_ts, + u_ts ? mq_fetch_timeout64 : NULL); } COBALT_SYSCALL(mq_timedreceive, primary, @@ -1089,5 +1080,14 @@ COBALT_SYSCALL(mq_timedreceive64, primary, unsigned int __user *u_prio, const struct __kernel_timespec __user *u_ts)) { - return __cobalt_mq_timedreceive64(uqd, u_buf, u_len, u_prio, u_ts); + ssize_t len; + int ret; + + ret = cobalt_copy_from_user(&len, u_len, sizeof(len)); + if (ret) + return ret; + + ret = __cobalt_mq_timedreceive64(uqd, u_buf, &len, u_prio, u_ts); + + return ret ?: cobalt_copy_to_user(u_len, &len, sizeof(*u_len)); } diff --git a/kernel/cobalt/posix/mqueue.h b/kernel/cobalt/posix/mqueue.h index b4b263158..d9223866a 100644 --- a/kernel/cobalt/posix/mqueue.h +++ b/kernel/cobalt/posix/mqueue.h @@ -51,7 +51,7 @@ int __cobalt_mq_timedreceive(mqd_t uqd, void __user *u_buf, const void __user *u_ts)); int __cobalt_mq_timedreceive64(mqd_t uqd, void __user *u_buf, - ssize_t __user *u_len, + ssize_t *len, unsigned int __user *u_prio, const void __user *u_ts); diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c index 0c3f50a81..b65a0a760 100644 --- a/kernel/cobalt/posix/syscall32.c +++ b/kernel/cobalt/posix/syscall32.c @@ -367,11 +367,24 @@ COBALT_SYSCALL32emu(mq_timedreceive, primary, } COBALT_SYSCALL32emu(mq_timedreceive64, primary, - (mqd_t uqd, void __user *u_buf, ssize_t __user *u_len, + (mqd_t uqd, void __user *u_buf, + compat_ssize_t __user *u_len, unsigned int __user *u_prio, const struct __kernel_timespec __user *u_ts)) { - return __cobalt_mq_timedreceive64(uqd, u_buf, u_len, u_prio, u_ts); + compat_ssize_t clen; + ssize_t len; + int ret; + + ret = cobalt_copy_from_user(&clen, u_len, sizeof(*u_len)); + if (ret) + return ret; + + len = clen; + ret = __cobalt_mq_timedreceive64(uqd, u_buf, &len, u_prio, u_ts); + clen = len; + + return ret ?: cobalt_copy_to_user(u_len, &clen, sizeof(*u_len)); } static inline int mq_fetch_timeout(struct timespec64 *ts, diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h index a64d100e7..55f08121c 100644 --- a/kernel/cobalt/posix/syscall32.h +++ b/kernel/cobalt/posix/syscall32.h @@ -140,7 +140,8 @@ COBALT_SYSCALL32emu_DECL(mq_timedreceive, const struct old_timespec32 __user *u_ts)); COBALT_SYSCALL32emu_DECL(mq_timedreceive64, - (mqd_t uqd, void __user *u_buf, ssize_t __user *u_len, + (mqd_t uqd, void __user *u_buf, + compat_ssize_t __user *u_len, unsigned int __user *u_prio, const struct __kernel_timespec __user *u_ts)); -- 2.35.1
