Last active
June 9, 2020 10:33
-
-
Save Skirmisher/02891c1a8cafa0ff18b2460933ef4f3c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 98014e4b27063ed74313878233e91b7b52b2a031 Mon Sep 17 00:00:00 2001 | |
From: Will Springer <skirmisher@protonmail.com> | |
Date: Tue, 9 Jun 2020 02:11:36 -0700 | |
Subject: [PATCH] powerpc/compat32: swap hi/lo parts of 64-bit syscall args on | |
32LE | |
This allows compat_sys calls with 64-bit args to function correctly | |
when called by ppcle userlands on ppc64le. | |
Tested with `file /bin/bash` (pread64) and `truncate -s 5G test` (ftruncate64). | |
--- | |
arch/powerpc/kernel/sys_ppc32.c | 49 +++++++++++++++++++-------------- | |
1 file changed, 28 insertions(+), 21 deletions(-) | |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c | |
index d36c6391eaf5..16ff0399a257 100644 | |
--- a/arch/powerpc/kernel/sys_ppc32.c | |
+++ b/arch/powerpc/kernel/sys_ppc32.c | |
@@ -59,57 +59,64 @@ unsigned long compat_sys_mmap2(unsigned long addr, size_t len, | |
/* | |
* long long munging: | |
* The 32 bit ABI passes long longs in an odd even register pair. | |
+ * High and low parts are swapped depending on endian mode, | |
+ * so define a macro (similar to mips linux32) to handle that. | |
*/ | |
+#ifdef __LITTLE_ENDIAN__ | |
+#define merge_64(low, high) ((u64)high << 32) | low | |
+#else | |
+#define merge_64(high, low) ((u64)high << 32) | low | |
+#endif | |
compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, | |
- u32 reg6, u32 poshi, u32 poslo) | |
+ u32 reg6, u32 pos1, u32 pos2) | |
{ | |
- return ksys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo); | |
+ return ksys_pread64(fd, ubuf, count, merge_64(pos1, pos2)); | |
} | |
compat_ssize_t compat_sys_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count, | |
- u32 reg6, u32 poshi, u32 poslo) | |
+ u32 reg6, u32 pos1, u32 pos2) | |
{ | |
- return ksys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo); | |
+ return ksys_pwrite64(fd, ubuf, count, merge_64(pos1, pos2)); | |
} | |
-compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count) | |
+compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offset1, u32 offset2, u32 count) | |
{ | |
- return ksys_readahead(fd, ((loff_t)offhi << 32) | offlo, count); | |
+ return ksys_readahead(fd, merge_64(offset1, offset2), count); | |
} | |
asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4, | |
- unsigned long high, unsigned long low) | |
+ unsigned long len1, unsigned long len2) | |
{ | |
- return ksys_truncate(path, (high << 32) | low); | |
+ return ksys_truncate(path, merge_64(len1, len2)); | |
} | |
-asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo, | |
- u32 lenhi, u32 lenlo) | |
+asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offset1, u32 offset2, | |
+ u32 len1, u32 len2) | |
{ | |
- return ksys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo, | |
- ((loff_t)lenhi << 32) | lenlo); | |
+ return ksys_fallocate(fd, mode, ((loff_t)offset1 << 32) | offset2, | |
+ merge_64(len1, len2)); | |
} | |
-asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, | |
- unsigned long low) | |
+asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long len1, | |
+ unsigned long len2) | |
{ | |
- return ksys_ftruncate(fd, (high << 32) | low); | |
+ return ksys_ftruncate(fd, merge_64(len1, len2)); | |
} | |
-long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low, | |
+long ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2, | |
size_t len, int advice) | |
{ | |
- return ksys_fadvise64_64(fd, (u64)offset_high << 32 | offset_low, len, | |
+ return ksys_fadvise64_64(fd, merge_64(offset1, offset2), len, | |
advice); | |
} | |
asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags, | |
- unsigned offset_hi, unsigned offset_lo, | |
- unsigned nbytes_hi, unsigned nbytes_lo) | |
+ unsigned offset1, unsigned offset2, | |
+ unsigned nbytes1, unsigned nbytes2) | |
{ | |
- loff_t offset = ((loff_t)offset_hi << 32) | offset_lo; | |
- loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo; | |
+ loff_t offset = merge_64(offset1, offset2); | |
+ loff_t nbytes = merge_64(nbytes1, nbytes2); | |
return ksys_sync_file_range(fd, offset, nbytes, flags); | |
} | |
-- | |
2.26.2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment