Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0bfd26e authored by Brian Gerst's avatar Brian Gerst Committed by Ingo Molnar
Browse files

x86/compat: Move copy_siginfo_*_user32() to signal_compat.c



copy_siginfo_to_user32() and copy_siginfo_from_user32() are used
by both the 32-bit compat and x32 ABIs.  Move them to
signal_compat.c.

Signed-off-by: default avatarBrian Gerst <brgerst@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1434974121-32575-2-git-send-email-brgerst@gmail.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 5a33fcb8
Loading
Loading
Loading
Loading
+0 −93
Original line number Diff line number Diff line
@@ -34,99 +34,6 @@
#include <asm/sys_ia32.h>
#include <asm/smap.h>

int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
{
	int err = 0;
	bool ia32 = test_thread_flag(TIF_IA32);

	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
		return -EFAULT;

	put_user_try {
		/* If you change siginfo_t structure, please make sure that
		   this code is fixed accordingly.
		   It should never copy any pad contained in the structure
		   to avoid security leaks, but must copy the generic
		   3 ints plus the relevant union member.  */
		put_user_ex(from->si_signo, &to->si_signo);
		put_user_ex(from->si_errno, &to->si_errno);
		put_user_ex((short)from->si_code, &to->si_code);

		if (from->si_code < 0) {
			put_user_ex(from->si_pid, &to->si_pid);
			put_user_ex(from->si_uid, &to->si_uid);
			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
		} else {
			/*
			 * First 32bits of unions are always present:
			 * si_pid === si_band === si_tid === si_addr(LS half)
			 */
			put_user_ex(from->_sifields._pad[0],
					  &to->_sifields._pad[0]);
			switch (from->si_code >> 16) {
			case __SI_FAULT >> 16:
				break;
			case __SI_SYS >> 16:
				put_user_ex(from->si_syscall, &to->si_syscall);
				put_user_ex(from->si_arch, &to->si_arch);
				break;
			case __SI_CHLD >> 16:
				if (ia32) {
					put_user_ex(from->si_utime, &to->si_utime);
					put_user_ex(from->si_stime, &to->si_stime);
				} else {
					put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
					put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
				}
				put_user_ex(from->si_status, &to->si_status);
				/* FALL THROUGH */
			default:
			case __SI_KILL >> 16:
				put_user_ex(from->si_uid, &to->si_uid);
				break;
			case __SI_POLL >> 16:
				put_user_ex(from->si_fd, &to->si_fd);
				break;
			case __SI_TIMER >> 16:
				put_user_ex(from->si_overrun, &to->si_overrun);
				put_user_ex(ptr_to_compat(from->si_ptr),
					    &to->si_ptr);
				break;
				 /* This is not generated by the kernel as of now.  */
			case __SI_RT >> 16:
			case __SI_MESGQ >> 16:
				put_user_ex(from->si_uid, &to->si_uid);
				put_user_ex(from->si_int, &to->si_int);
				break;
			}
		}
	} put_user_catch(err);

	return err;
}

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	int err = 0;
	u32 ptr32;

	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
		return -EFAULT;

	get_user_try {
		get_user_ex(to->si_signo, &from->si_signo);
		get_user_ex(to->si_errno, &from->si_errno);
		get_user_ex(to->si_code, &from->si_code);

		get_user_ex(to->si_pid, &from->si_pid);
		get_user_ex(to->si_uid, &from->si_uid);
		get_user_ex(ptr32, &from->si_ptr);
		to->si_ptr = compat_ptr(ptr32);
	} get_user_catch(err);

	return err;
}

/*
 * Do a signal return; undo the signal stack.
 */
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ KASAN_SANITIZE_dumpstack_$(BITS).o := n
CFLAGS_irq.o := -I$(src)/../include/asm/trace

obj-y			:= process_$(BITS).o signal.o
obj-$(CONFIG_COMPAT)	+= signal_compat.o
obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-y			+= time.o ioport.o ldt.o dumpstack.o nmi.o
obj-y			+= setup.o x86_init.o i8259.o irqinit.o jump_label.o
+95 −0
Original line number Diff line number Diff line
#include <linux/compat.h>
#include <linux/uaccess.h>

int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
{
	int err = 0;
	bool ia32 = test_thread_flag(TIF_IA32);

	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
		return -EFAULT;

	put_user_try {
		/* If you change siginfo_t structure, please make sure that
		   this code is fixed accordingly.
		   It should never copy any pad contained in the structure
		   to avoid security leaks, but must copy the generic
		   3 ints plus the relevant union member.  */
		put_user_ex(from->si_signo, &to->si_signo);
		put_user_ex(from->si_errno, &to->si_errno);
		put_user_ex((short)from->si_code, &to->si_code);

		if (from->si_code < 0) {
			put_user_ex(from->si_pid, &to->si_pid);
			put_user_ex(from->si_uid, &to->si_uid);
			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
		} else {
			/*
			 * First 32bits of unions are always present:
			 * si_pid === si_band === si_tid === si_addr(LS half)
			 */
			put_user_ex(from->_sifields._pad[0],
					  &to->_sifields._pad[0]);
			switch (from->si_code >> 16) {
			case __SI_FAULT >> 16:
				break;
			case __SI_SYS >> 16:
				put_user_ex(from->si_syscall, &to->si_syscall);
				put_user_ex(from->si_arch, &to->si_arch);
				break;
			case __SI_CHLD >> 16:
				if (ia32) {
					put_user_ex(from->si_utime, &to->si_utime);
					put_user_ex(from->si_stime, &to->si_stime);
				} else {
					put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
					put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
				}
				put_user_ex(from->si_status, &to->si_status);
				/* FALL THROUGH */
			default:
			case __SI_KILL >> 16:
				put_user_ex(from->si_uid, &to->si_uid);
				break;
			case __SI_POLL >> 16:
				put_user_ex(from->si_fd, &to->si_fd);
				break;
			case __SI_TIMER >> 16:
				put_user_ex(from->si_overrun, &to->si_overrun);
				put_user_ex(ptr_to_compat(from->si_ptr),
					    &to->si_ptr);
				break;
				 /* This is not generated by the kernel as of now.  */
			case __SI_RT >> 16:
			case __SI_MESGQ >> 16:
				put_user_ex(from->si_uid, &to->si_uid);
				put_user_ex(from->si_int, &to->si_int);
				break;
			}
		}
	} put_user_catch(err);

	return err;
}

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	int err = 0;
	u32 ptr32;

	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
		return -EFAULT;

	get_user_try {
		get_user_ex(to->si_signo, &from->si_signo);
		get_user_ex(to->si_errno, &from->si_errno);
		get_user_ex(to->si_code, &from->si_code);

		get_user_ex(to->si_pid, &from->si_pid);
		get_user_ex(to->si_uid, &from->si_uid);
		get_user_ex(ptr32, &from->si_ptr);
		to->si_ptr = compat_ptr(ptr32);
	} get_user_catch(err);

	return err;
}