Skip to content

Commit dfd948e

Browse files
heicarsttorvalds
authored andcommitted
fs/compat: fix parameter handling for compat readv/writev syscalls
We got a report that the pwritev syscall does not work correctly in compat mode on s390. It turned out that with commit 72ec351 ("switch compat readv/writev variants to COMPAT_SYSCALL_DEFINE") we lost the zero extension of a couple of syscall parameters because the some parameter types haven't been converted from unsigned long to compat_ulong_t. This is needed for architectures where the ABI requires that the caller of a function performed zero and/or sign extension to 64 bit of all parameters. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Ingo Molnar <mingo@kernel.org> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: <stable@vger.kernel.org> [v3.10+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 4a404be commit dfd948e

File tree

2 files changed

+16
-16
lines changed

2 files changed

+16
-16
lines changed

fs/read_write.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -964,9 +964,9 @@ static size_t compat_readv(struct file *file,
964964
return ret;
965965
}
966966

967-
COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
967+
COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
968968
const struct compat_iovec __user *,vec,
969-
unsigned long, vlen)
969+
compat_ulong_t, vlen)
970970
{
971971
struct fd f = fdget(fd);
972972
ssize_t ret;
@@ -1001,9 +1001,9 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
10011001
return ret;
10021002
}
10031003

1004-
COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
1004+
COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
10051005
const struct compat_iovec __user *,vec,
1006-
unsigned long, vlen, u32, pos_low, u32, pos_high)
1006+
compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
10071007
{
10081008
loff_t pos = ((loff_t)pos_high << 32) | pos_low;
10091009
return compat_sys_preadv64(fd, vec, vlen, pos);
@@ -1031,9 +1031,9 @@ static size_t compat_writev(struct file *file,
10311031
return ret;
10321032
}
10331033

1034-
COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
1034+
COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
10351035
const struct compat_iovec __user *, vec,
1036-
unsigned long, vlen)
1036+
compat_ulong_t, vlen)
10371037
{
10381038
struct fd f = fdget(fd);
10391039
ssize_t ret;
@@ -1068,9 +1068,9 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
10681068
return ret;
10691069
}
10701070

1071-
COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
1071+
COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
10721072
const struct compat_iovec __user *,vec,
1073-
unsigned long, vlen, u32, pos_low, u32, pos_high)
1073+
compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
10741074
{
10751075
loff_t pos = ((loff_t)pos_high << 32) | pos_low;
10761076
return compat_sys_pwritev64(fd, vec, vlen, pos);

include/linux/compat.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -327,16 +327,16 @@ asmlinkage long compat_sys_keyctl(u32 option,
327327
u32 arg2, u32 arg3, u32 arg4, u32 arg5);
328328
asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);
329329

330-
asmlinkage ssize_t compat_sys_readv(unsigned long fd,
331-
const struct compat_iovec __user *vec, unsigned long vlen);
332-
asmlinkage ssize_t compat_sys_writev(unsigned long fd,
333-
const struct compat_iovec __user *vec, unsigned long vlen);
334-
asmlinkage ssize_t compat_sys_preadv(unsigned long fd,
330+
asmlinkage ssize_t compat_sys_readv(compat_ulong_t fd,
331+
const struct compat_iovec __user *vec, compat_ulong_t vlen);
332+
asmlinkage ssize_t compat_sys_writev(compat_ulong_t fd,
333+
const struct compat_iovec __user *vec, compat_ulong_t vlen);
334+
asmlinkage ssize_t compat_sys_preadv(compat_ulong_t fd,
335335
const struct compat_iovec __user *vec,
336-
unsigned long vlen, u32 pos_low, u32 pos_high);
337-
asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
336+
compat_ulong_t vlen, u32 pos_low, u32 pos_high);
337+
asmlinkage ssize_t compat_sys_pwritev(compat_ulong_t fd,
338338
const struct compat_iovec __user *vec,
339-
unsigned long vlen, u32 pos_low, u32 pos_high);
339+
compat_ulong_t vlen, u32 pos_low, u32 pos_high);
340340
asmlinkage long comat_sys_lseek(unsigned int, compat_off_t, unsigned int);
341341

342342
asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,

0 commit comments

Comments
 (0)