git: b17446281d21 - main - linux(4): Fixed offset miscalculation in the preadv/pwritev syscalls.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 09 May 2022 18:17:10 UTC
The branch main has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=b17446281d21311cc4f9d522c5d18337a9f786bc commit b17446281d21311cc4f9d522c5d18337a9f786bc Author: Dmitry Chagin <dchagin@FreeBSD.org> AuthorDate: 2022-05-09 18:11:37 +0000 Commit: Dmitry Chagin <dchagin@FreeBSD.org> CommitDate: 2022-05-09 18:11:37 +0000 linux(4): Fixed offset miscalculation in the preadv/pwritev syscalls. MFC after: 2 weeks --- sys/compat/linux/linux_file.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 8926e760fc39..199bed80d92a 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -1268,6 +1268,15 @@ linux_pwrite(struct thread *td, struct linux_pwrite_args *uap) return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte, offset)); } +#define HALF_LONG_BITS ((sizeof(l_long) * NBBY / 2)) + +static inline off_t +pos_from_hilo(unsigned long high, unsigned long low) +{ + + return (((off_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; +} + int linux_preadv(struct thread *td, struct linux_preadv_args *uap) { @@ -1280,8 +1289,7 @@ linux_preadv(struct thread *td, struct linux_preadv_args *uap) * pos_l and pos_h, respectively, contain the * low order and high order 32 bits of offset. */ - offset = (((off_t)uap->pos_h << (sizeof(offset) * 4)) << - (sizeof(offset) * 4)) | uap->pos_l; + offset = pos_from_hilo(uap->pos_h, uap->pos_l); if (offset < 0) return (EINVAL); #ifdef COMPAT_LINUX32 @@ -1308,8 +1316,7 @@ linux_pwritev(struct thread *td, struct linux_pwritev_args *uap) * pos_l and pos_h, respectively, contain the * low order and high order 32 bits of offset. */ - offset = (((off_t)uap->pos_h << (sizeof(offset) * 4)) << - (sizeof(offset) * 4)) | uap->pos_l; + offset = pos_from_hilo(uap->pos_h, uap->pos_l); if (offset < 0) return (EINVAL); #ifdef COMPAT_LINUX32