Commit 121b32a5 authored by Brian Gerst's avatar Brian Gerst Committed by Thomas Gleixner
Browse files

x86/entry/32: Use IA32-specific wrappers for syscalls taking 64-bit arguments



For the 32-bit syscall interface, 64-bit arguments (loff_t) are passed via
a pair of 32-bit registers.  These register pairs end up in consecutive stack
slots, which matches the C ABI for 64-bit arguments.  But when accessing the
registers directly from pt_regs, the wrapper needs to manually reassemble the
64-bit value.  These wrappers already exist for 32-bit compat, so make them
available to 32-bit native in preparation for enabling pt_regs-based syscalls.

Signed-off-by: default avatarBrian Gerst <brgerst@gmail.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
Link: https://lkml.kernel.org/r/20200313195144.164260-16-brgerst@gmail.com
parent 866128a9
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -191,8 +191,8 @@
177	i386	rt_sigtimedwait		sys_rt_sigtimedwait_time32	compat_sys_rt_sigtimedwait_time32
178	i386	rt_sigqueueinfo		sys_rt_sigqueueinfo		compat_sys_rt_sigqueueinfo
179	i386	rt_sigsuspend		sys_rt_sigsuspend		compat_sys_rt_sigsuspend
180	i386	pread64			sys_pread64			compat_sys_ia32_pread64
181	i386	pwrite64		sys_pwrite64			compat_sys_ia32_pwrite64
180	i386	pread64			sys_ia32_pread64
181	i386	pwrite64		sys_ia32_pwrite64
182	i386	chown			sys_chown16
183	i386	getcwd			sys_getcwd
184	i386	capget			sys_capget
@@ -204,8 +204,8 @@
190	i386	vfork			sys_vfork
191	i386	ugetrlimit		sys_getrlimit			compat_sys_getrlimit
192	i386	mmap2			sys_mmap_pgoff
193	i386	truncate64		sys_truncate64			compat_sys_ia32_truncate64
194	i386	ftruncate64		sys_ftruncate64			compat_sys_ia32_ftruncate64
193	i386	truncate64		sys_ia32_truncate64
194	i386	ftruncate64		sys_ia32_ftruncate64
195	i386	stat64			sys_stat64			compat_sys_ia32_stat64
196	i386	lstat64			sys_lstat64			compat_sys_ia32_lstat64
197	i386	fstat64			sys_fstat64			compat_sys_ia32_fstat64
@@ -236,7 +236,7 @@
# 222 is unused
# 223 is unused
224	i386	gettid			sys_gettid
225	i386	readahead		sys_readahead			compat_sys_ia32_readahead
225	i386	readahead		sys_ia32_readahead
226	i386	setxattr		sys_setxattr
227	i386	lsetxattr		sys_lsetxattr
228	i386	fsetxattr		sys_fsetxattr
@@ -261,7 +261,7 @@
247	i386	io_getevents		sys_io_getevents_time32
248	i386	io_submit		sys_io_submit			compat_sys_io_submit
249	i386	io_cancel		sys_io_cancel
250	i386	fadvise64		sys_fadvise64			compat_sys_ia32_fadvise64
250	i386	fadvise64		sys_ia32_fadvise64
# 251 is available for reuse (was briefly sys_set_zone_reclaim)
252	i386	exit_group		sys_exit_group
253	i386	lookup_dcookie		sys_lookup_dcookie		compat_sys_lookup_dcookie
@@ -283,7 +283,7 @@
269	i386	fstatfs64		sys_fstatfs64			compat_sys_fstatfs64
270	i386	tgkill			sys_tgkill
271	i386	utimes			sys_utimes_time32
272	i386	fadvise64_64		sys_fadvise64_64		compat_sys_ia32_fadvise64_64
272	i386	fadvise64_64		sys_ia32_fadvise64_64
273	i386	vserver
274	i386	mbind			sys_mbind
275	i386	get_mempolicy		sys_get_mempolicy		compat_sys_get_mempolicy
@@ -325,7 +325,7 @@
311	i386	set_robust_list		sys_set_robust_list		compat_sys_set_robust_list
312	i386	get_robust_list		sys_get_robust_list		compat_sys_get_robust_list
313	i386	splice			sys_splice
314	i386	sync_file_range		sys_sync_file_range		compat_sys_ia32_sync_file_range
314	i386	sync_file_range		sys_ia32_sync_file_range
315	i386	tee			sys_tee
316	i386	vmsplice		sys_vmsplice			compat_sys_vmsplice
317	i386	move_pages		sys_move_pages			compat_sys_move_pages
@@ -335,7 +335,7 @@
321	i386	signalfd		sys_signalfd			compat_sys_signalfd
322	i386	timerfd_create		sys_timerfd_create
323	i386	eventfd			sys_eventfd
324	i386	fallocate		sys_fallocate			compat_sys_ia32_fallocate
324	i386	fallocate		sys_ia32_fallocate
325	i386	timerfd_settime		sys_timerfd_settime32
326	i386	timerfd_gettime		sys_timerfd_gettime32
327	i386	signalfd4		sys_signalfd4			compat_sys_signalfd4
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
# Makefile for the ia32 kernel emulation subsystem.
#

obj-$(CONFIG_IA32_EMULATION) := sys_ia32.o ia32_signal.o
obj-$(CONFIG_IA32_EMULATION) := ia32_signal.o

obj-$(CONFIG_IA32_AOUT) += ia32_aout.o

+2 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ obj-y += setup.o x86_init.o i8259.o irqinit.o
obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
obj-$(CONFIG_IRQ_WORK)  += irq_work.o
obj-y			+= probe_roms.o
obj-$(CONFIG_X86_32)	+= sys_ia32.o
obj-$(CONFIG_IA32_EMULATION)	+= sys_ia32.o
obj-$(CONFIG_X86_64)	+= sys_x86_64.o
obj-$(CONFIG_X86_ESPFIX64)	+= espfix_64.o
obj-$(CONFIG_SYSFS)	+= ksysfs.o
+66 −65
Original line number Diff line number Diff line
@@ -51,20 +51,80 @@

#define AA(__x)		((unsigned long)(__x))


COMPAT_SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
		unsigned long, offset_low, unsigned long, offset_high)
{
	return ksys_truncate(filename,
			    ((loff_t) offset_high << 32) | offset_low);
}

COMPAT_SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
		unsigned long, offset_low, unsigned long, offset_high)
{
	return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
}

/* warning: next two assume little endian */
SYSCALL_DEFINE5(ia32_pread64, unsigned int, fd, char __user *, ubuf,
		u32, count, u32, poslo, u32, poshi)
{
	return ksys_pread64(fd, ubuf, count,
			    ((loff_t)AA(poshi) << 32) | AA(poslo));
}

SYSCALL_DEFINE5(ia32_pwrite64, unsigned int, fd, const char __user *, ubuf,
		u32, count, u32, poslo, u32, poshi)
{
	return ksys_pwrite64(fd, ubuf, count,
			     ((loff_t)AA(poshi) << 32) | AA(poslo));
}


/*
 * Some system calls that need sign extended arguments. This could be
 * done by a generic wrapper.
 */
SYSCALL_DEFINE6(ia32_fadvise64_64, int, fd, __u32, offset_low,
		__u32, offset_high, __u32, len_low, __u32, len_high,
		int, advice)
{
	return ksys_fadvise64_64(fd,
				 (((u64)offset_high)<<32) | offset_low,
				 (((u64)len_high)<<32) | len_low,
				 advice);
}

SYSCALL_DEFINE4(ia32_readahead, int, fd, unsigned int, off_lo,
		unsigned int, off_hi, size_t, count)
{
	return ksys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
}

SYSCALL_DEFINE6(ia32_sync_file_range, int, fd, unsigned int, off_low,
		unsigned int, off_hi, unsigned int, n_low,
		unsigned int, n_hi, int, flags)
{
	return ksys_sync_file_range(fd,
				    ((u64)off_hi << 32) | off_low,
				    ((u64)n_hi << 32) | n_low, flags);
}

SYSCALL_DEFINE5(ia32_fadvise64, int, fd, unsigned int, offset_lo,
		unsigned int, offset_hi, size_t, len, int, advice)
{
	return ksys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
				 len, advice);
}

SYSCALL_DEFINE6(ia32_fallocate, int, fd, int, mode,
		unsigned int, offset_lo, unsigned int, offset_hi,
		unsigned int, len_lo, unsigned int, len_hi)
{
	return ksys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
			      ((u64)len_hi << 32) | len_lo);
}

#ifdef CONFIG_IA32_EMULATION
/*
 * Another set for IA32/LFS -- x86_64 struct stat is different due to
 * support for 64bit inode numbers.
@@ -170,66 +230,6 @@ COMPAT_SYSCALL_DEFINE1(ia32_mmap, struct mmap_arg_struct32 __user *, arg)
			       a.offset>>PAGE_SHIFT);
}

/* warning: next two assume little endian */
COMPAT_SYSCALL_DEFINE5(ia32_pread64, unsigned int, fd, char __user *, ubuf,
		       u32, count, u32, poslo, u32, poshi)
{
	return ksys_pread64(fd, ubuf, count,
			    ((loff_t)AA(poshi) << 32) | AA(poslo));
}

COMPAT_SYSCALL_DEFINE5(ia32_pwrite64, unsigned int, fd, const char __user *, ubuf,
		       u32, count, u32, poslo, u32, poshi)
{
	return ksys_pwrite64(fd, ubuf, count,
			     ((loff_t)AA(poshi) << 32) | AA(poslo));
}


/*
 * Some system calls that need sign extended arguments. This could be
 * done by a generic wrapper.
 */
COMPAT_SYSCALL_DEFINE6(ia32_fadvise64_64, int, fd, __u32, offset_low,
		       __u32, offset_high, __u32, len_low, __u32, len_high,
		       int, advice)
{
	return ksys_fadvise64_64(fd,
				 (((u64)offset_high)<<32) | offset_low,
				 (((u64)len_high)<<32) | len_low,
				 advice);
}

COMPAT_SYSCALL_DEFINE4(ia32_readahead, int, fd, unsigned int, off_lo,
		       unsigned int, off_hi, size_t, count)
{
	return ksys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
}

COMPAT_SYSCALL_DEFINE6(ia32_sync_file_range, int, fd, unsigned int, off_low,
		       unsigned int, off_hi, unsigned int, n_low,
		       unsigned int, n_hi, int, flags)
{
	return ksys_sync_file_range(fd,
				    ((u64)off_hi << 32) | off_low,
				    ((u64)n_hi << 32) | n_low, flags);
}

COMPAT_SYSCALL_DEFINE5(ia32_fadvise64, int, fd, unsigned int, offset_lo,
		       unsigned int, offset_hi, size_t, len, int, advice)
{
	return ksys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
				 len, advice);
}

COMPAT_SYSCALL_DEFINE6(ia32_fallocate, int, fd, int, mode,
		       unsigned int, offset_lo, unsigned int, offset_hi,
		       unsigned int, len_lo, unsigned int, len_hi)
{
	return ksys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
			      ((u64)len_hi << 32) | len_lo);
}

/*
 * The 32-bit clone ABI is CONFIG_CLONE_BACKWARDS
 */
@@ -252,3 +252,4 @@ COMPAT_SYSCALL_DEFINE5(ia32_clone, unsigned long, clone_flags,

	return _do_fork(&args);
}
#endif /* CONFIG_IA32_EMULATION */
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ obj-y += checksum_32.o syscalls_32.o
obj-$(CONFIG_ELF_CORE) += elfcore.o

subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
subarch-y += ../kernel/sys_ia32.o

else