git: 800b5aafa3a8 - stable/13 - linux(4): Fixed offset miscalculation in the preadv/pwritev syscalls.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Jun 2022 19:40:13 UTC
The branch stable/13 has been updated by dchagin:
URL: https://cgit.FreeBSD.org/src/commit/?id=800b5aafa3a801fe3a7bf3f0dd78fbc33e7e6ba1
commit 800b5aafa3a801fe3a7bf3f0dd78fbc33e7e6ba1
Author: Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-09 18:11:37 +0000
Commit: Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:35:06 +0000
linux(4): Fixed offset miscalculation in the preadv/pwritev syscalls.
MFC after: 2 weeks
(cherry picked from commit b17446281d21311cc4f9d522c5d18337a9f786bc)
---
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