diff --git a/fs/compat.c b/fs/compat.c index 1c859dae758f8a..3f84d5f1588960 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1236,7 +1236,7 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, asmlinkage ssize_t compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, - unsigned long vlen, u32 pos_high, u32 pos_low) + unsigned long vlen, u32 pos_low, u32 pos_high) { loff_t pos = ((loff_t)pos_high << 32) | pos_low; struct file *file; @@ -1293,7 +1293,7 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, - unsigned long vlen, u32 pos_high, u32 pos_low) + unsigned long vlen, u32 pos_low, u32 pos_high) { loff_t pos = ((loff_t)pos_high << 32) | pos_low; struct file *file; diff --git a/fs/read_write.c b/fs/read_write.c index 6d5d8ff238aa50..9d1e76bb9ee147 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -731,10 +731,16 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, return ret; } +static inline loff_t pos_from_hilo(unsigned long high, unsigned long low) +{ +#define HALF_LONG_BITS (BITS_PER_LONG / 2) + return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; +} + SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, - unsigned long, vlen, u32, pos_high, u32, pos_low) + unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) { - loff_t pos = ((loff_t)pos_high << 32) | pos_low; + loff_t pos = pos_from_hilo(pos_h, pos_l); struct file *file; ssize_t ret = -EBADF; int fput_needed; @@ -757,9 +763,9 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, } SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, - unsigned long, vlen, u32, pos_high, u32, pos_low) + unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) { - loff_t pos = ((loff_t)pos_high << 32) | pos_low; + loff_t pos = pos_from_hilo(pos_h, pos_l); struct file *file; ssize_t ret = -EBADF; int fput_needed; diff --git a/include/linux/compat.h b/include/linux/compat.h index 9723edd6455cb8..f2ded21f9a3c37 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -193,10 +193,10 @@ asmlinkage ssize_t compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen); asmlinkage ssize_t compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, - unsigned long vlen, u32 pos_high, u32 pos_low); + unsigned long vlen, u32 pos_low, u32 pos_high); asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, - unsigned long vlen, u32 pos_high, u32 pos_low); + unsigned long vlen, u32 pos_low, u32 pos_high); int compat_do_execve(char * filename, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs * regs); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index b299a82a05e7ab..18771cac2f8513 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -462,9 +462,9 @@ asmlinkage long sys_pread64(unsigned int fd, char __user *buf, asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, size_t count, loff_t pos); asmlinkage long sys_preadv(unsigned long fd, const struct iovec __user *vec, - unsigned long vlen, u32 pos_high, u32 pos_low); + unsigned long vlen, unsigned long pos_l, unsigned long pos_h); asmlinkage long sys_pwritev(unsigned long fd, const struct iovec __user *vec, - unsigned long vlen, u32 pos_high, u32 pos_low); + unsigned long vlen, unsigned long pos_l, unsigned long pos_h); asmlinkage long sys_getcwd(char __user *buf, unsigned long size); asmlinkage long sys_mkdir(const char __user *pathname, int mode); asmlinkage long sys_chdir(const char __user *filename);