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

Commit 431dc804 authored by Ralf Baechle's avatar Ralf Baechle
Browse files

[MIPS] Fix sigset_t endianess swapping issues in 32-bit compat code.

parent 366d6aef
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <net/sock.h>
#include <net/scm.h>

#include <asm/compat-signal.h>
#include <asm/ipc.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
@@ -736,3 +737,49 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
	return do_fork(clone_flags, newsp, &regs, 0,
	               parent_tidptr, child_tidptr);
}

/*
 * Implement the event wait interface for the eventpoll file. It is the kernel
 * part of the user space epoll_pwait(2).
 */
asmlinkage long compat_sys_epoll_pwait(int epfd,
	struct epoll_event __user *events, int maxevents, int timeout,
	const compat_sigset_t __user *sigmask, size_t sigsetsize)
{
	int error;
	sigset_t ksigmask, sigsaved;

	/*
	 * If the caller wants a certain signal mask to be set during the wait,
	 * we apply it here.
	 */
	if (sigmask) {
		if (sigsetsize != sizeof(sigset_t))
			return -EINVAL;
		if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask)))
			return -EFAULT;
		if (__copy_conv_sigset_from_user(&ksigmask, sigmask))
			return -EFAULT;
		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
	}

	error = sys_epoll_wait(epfd, events, maxevents, timeout);

	/*
	 * If we changed the signal mask, we need to restore the original one.
	 * In case we've got a signal while waiting, we do not restore the
	 * signal mask yet, and we allow do_signal() to deliver the signal on
	 * the way back to userspace, before the signal mask is restored.
	 */
	if (sigmask) {
		if (error == -EINTR) {
			memcpy(&current->saved_sigmask, &sigsaved,
				sizeof(sigsaved));
			set_thread_flag(TIF_RESTORE_SIGMASK);
		} else
			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
	}

	return error;
}
+1 −1
Original line number Diff line number Diff line
@@ -470,4 +470,4 @@ sys_call_table:
	PTR	sys_get_robust_list
	PTR	sys_kexec_load			/* 5270 */
	PTR	sys_getcpu
	PTR	sys_epoll_pwait
	PTR	compat_sys_epoll_pwait
+1 −1
Original line number Diff line number Diff line
@@ -396,4 +396,4 @@ EXPORT(sysn32_call_table)
	PTR	compat_sys_get_robust_list
	PTR	compat_sys_kexec_load
	PTR	sys_getcpu
	PTR	sys_epoll_pwait
	PTR	compat_sys_epoll_pwait
+7 −4
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
 */
#include <linux/cache.h>
#include <linux/compat.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -24,6 +25,7 @@

#include <asm/abi.h>
#include <asm/asm.h>
#include <asm/compat-signal.h>
#include <linux/bitops.h>
#include <asm/cacheflush.h>
#include <asm/sim.h>
@@ -517,7 +519,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
	frame = (struct sigframe32 __user *) regs.regs[29];
	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
		goto badframe;
	if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
	if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
		goto badframe;

	sigdelsetmask(&blocked, ~_BLOCKABLE);
@@ -554,7 +556,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
	frame = (struct rt_sigframe32 __user *) regs.regs[29];
	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
		goto badframe;
	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
	if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
		goto badframe;

	sigdelsetmask(&set, ~_BLOCKABLE);
@@ -609,7 +611,8 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
	err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);

	err |= setup_sigcontext32(regs, &frame->sf_sc);
	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
	err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);

	if (err)
		goto give_sigsegv;

@@ -668,7 +671,7 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
	err |= __put_user(current->sas_ss_size,
	                  &frame->rs_uc.uc_stack.ss_size);
	err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);

	if (err)
		goto give_sigsegv;
+4 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@

#include <asm/asm.h>
#include <asm/cacheflush.h>
#include <asm/compat-signal.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
#include <asm/ucontext.h>
@@ -63,7 +64,7 @@ struct ucontextn32 {
	s32                 uc_link;
	stack32_t           uc_stack;
	struct sigcontext   uc_mcontext;
	sigset_t            uc_sigmask;   /* mask last for extensibility */
	compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
};

#if ICACHE_REFILLS_WORKAROUND_WAR == 0
@@ -129,7 +130,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
	frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
		goto badframe;
	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
	if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
		goto badframe;

	sigdelsetmask(&set, ~_BLOCKABLE);
@@ -195,7 +196,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
	err |= __put_user(current->sas_ss_size,
	                  &frame->rs_uc.uc_stack.ss_size);
	err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);

	if (err)
		goto give_sigsegv;
Loading