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 72ec35163f ("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>
	
	
This commit is contained in:
		
					parent
					
						
							
								4a404bea94
							
						
					
				
			
			
				commit
				
					
						dfd948e32a
					
				
			
		
					 2 changed files with 16 additions and 16 deletions
				
			
		| 
						 | 
					@ -964,9 +964,9 @@ out:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
 | 
					COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
 | 
				
			||||||
		const struct compat_iovec __user *,vec,
 | 
							const struct compat_iovec __user *,vec,
 | 
				
			||||||
		unsigned long, vlen)
 | 
							compat_ulong_t, vlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fd f = fdget(fd);
 | 
						struct fd f = fdget(fd);
 | 
				
			||||||
	ssize_t ret;
 | 
						ssize_t ret;
 | 
				
			||||||
| 
						 | 
					@ -1001,9 +1001,9 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
 | 
					COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
 | 
				
			||||||
		const struct compat_iovec __user *,vec,
 | 
							const struct compat_iovec __user *,vec,
 | 
				
			||||||
		unsigned long, vlen, u32, pos_low, u32, pos_high)
 | 
							compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
 | 
						loff_t pos = ((loff_t)pos_high << 32) | pos_low;
 | 
				
			||||||
	return compat_sys_preadv64(fd, vec, vlen, pos);
 | 
						return compat_sys_preadv64(fd, vec, vlen, pos);
 | 
				
			||||||
| 
						 | 
					@ -1031,9 +1031,9 @@ out:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
 | 
					COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
 | 
				
			||||||
		const struct compat_iovec __user *, vec,
 | 
							const struct compat_iovec __user *, vec,
 | 
				
			||||||
		unsigned long, vlen)
 | 
							compat_ulong_t, vlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fd f = fdget(fd);
 | 
						struct fd f = fdget(fd);
 | 
				
			||||||
	ssize_t ret;
 | 
						ssize_t ret;
 | 
				
			||||||
| 
						 | 
					@ -1068,9 +1068,9 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
 | 
					COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
 | 
				
			||||||
		const struct compat_iovec __user *,vec,
 | 
							const struct compat_iovec __user *,vec,
 | 
				
			||||||
		unsigned long, vlen, u32, pos_low, u32, pos_high)
 | 
							compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
 | 
						loff_t pos = ((loff_t)pos_high << 32) | pos_low;
 | 
				
			||||||
	return compat_sys_pwritev64(fd, vec, vlen, pos);
 | 
						return compat_sys_pwritev64(fd, vec, vlen, pos);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,16 +327,16 @@ asmlinkage long compat_sys_keyctl(u32 option,
 | 
				
			||||||
			      u32 arg2, u32 arg3, u32 arg4, u32 arg5);
 | 
								      u32 arg2, u32 arg3, u32 arg4, u32 arg5);
 | 
				
			||||||
asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);
 | 
					asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
asmlinkage ssize_t compat_sys_readv(unsigned long fd,
 | 
					asmlinkage ssize_t compat_sys_readv(compat_ulong_t fd,
 | 
				
			||||||
		const struct compat_iovec __user *vec, unsigned long vlen);
 | 
							const struct compat_iovec __user *vec, compat_ulong_t vlen);
 | 
				
			||||||
asmlinkage ssize_t compat_sys_writev(unsigned long fd,
 | 
					asmlinkage ssize_t compat_sys_writev(compat_ulong_t fd,
 | 
				
			||||||
		const struct compat_iovec __user *vec, unsigned long vlen);
 | 
							const struct compat_iovec __user *vec, compat_ulong_t vlen);
 | 
				
			||||||
asmlinkage ssize_t compat_sys_preadv(unsigned long fd,
 | 
					asmlinkage ssize_t compat_sys_preadv(compat_ulong_t fd,
 | 
				
			||||||
		const struct compat_iovec __user *vec,
 | 
							const struct compat_iovec __user *vec,
 | 
				
			||||||
		unsigned long vlen, u32 pos_low, u32 pos_high);
 | 
							compat_ulong_t vlen, u32 pos_low, u32 pos_high);
 | 
				
			||||||
asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
 | 
					asmlinkage ssize_t compat_sys_pwritev(compat_ulong_t fd,
 | 
				
			||||||
		const struct compat_iovec __user *vec,
 | 
							const struct compat_iovec __user *vec,
 | 
				
			||||||
		unsigned long vlen, u32 pos_low, u32 pos_high);
 | 
							compat_ulong_t vlen, u32 pos_low, u32 pos_high);
 | 
				
			||||||
asmlinkage long comat_sys_lseek(unsigned int, compat_off_t, unsigned int);
 | 
					asmlinkage long comat_sys_lseek(unsigned int, compat_off_t, unsigned int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
 | 
					asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue