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

Commit 08d32fe5 authored by Al Viro's avatar Al Viro
Browse files

generic sys_compat_rt_sigaction()



Again, protected by a temporary config symbol (GENERIC_COMPAT_RT_SIGACTION);
will be gone by the end of series.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 574c4866
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -368,6 +368,9 @@ config GENERIC_COMPAT_RT_SIGPENDING
config GENERIC_COMPAT_RT_SIGQUEUEINFO
	bool

config GENERIC_COMPAT_RT_SIGACTION
	bool

#
# ABI hall of shame
#
+24 −0
Original line number Diff line number Diff line
@@ -142,6 +142,22 @@ typedef struct {
	compat_sigset_word	sig[_COMPAT_NSIG_WORDS];
} compat_sigset_t;

#ifdef CONFIG_GENERIC_COMPAT_RT_SIGACTION
struct compat_sigaction {
#ifndef __ARCH_HAS_ODD_SIGACTION
	compat_uptr_t			sa_handler;
	compat_ulong_t			sa_flags;
#else
	compat_ulong_t			sa_flags;
	compat_uptr_t			sa_handler;
#endif
#ifdef __ARCH_HAS_SA_RESTORER
	compat_uptr_t			sa_restorer;
#endif
	compat_sigset_t			sa_mask __packed;
};
#endif

/*
 * These functions operate strictly on struct compat_time*
 */
@@ -602,6 +618,14 @@ asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set,
asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset,
					 compat_size_t sigsetsize);
#endif
#ifndef CONFIG_ODD_RT_SIGACTION
#ifdef CONFIG_GENERIC_COMPAT_RT_SIGACTION
asmlinkage long compat_sys_rt_sigaction(int,
				 const struct compat_sigaction __user *,
				 struct compat_sigaction __user *,
				 compat_size_t);
#endif
#endif
#ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO
asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig,
				struct compat_siginfo __user *uinfo);
+49 −0
Original line number Diff line number Diff line
@@ -3358,6 +3358,55 @@ SYSCALL_DEFINE4(rt_sigaction, int, sig,
out:
	return ret;
}
#ifdef CONFIG_COMPAT
#ifdef CONFIG_GENERIC_COMPAT_RT_SIGACTION
COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
		const struct compat_sigaction __user *, act,
		struct compat_sigaction __user *, oact,
		compat_size_t, sigsetsize)
{
	struct k_sigaction new_ka, old_ka;
	compat_sigset_t mask;
#ifdef __ARCH_HAS_SA_RESTORER
	compat_uptr_t restorer;
#endif
	int ret;

	/* XXX: Don't preclude handling different sized sigset_t's.  */
	if (sigsetsize != sizeof(compat_sigset_t))
		return -EINVAL;

	if (act) {
		compat_uptr_t handler;
		ret = get_user(handler, &act->sa_handler);
		new_ka.sa.sa_handler = compat_ptr(handler);
#ifdef __ARCH_HAS_SA_RESTORER
		ret |= get_user(restorer, &act->sa_restorer);
		new_ka.sa.sa_restorer = compat_ptr(restorer);
#endif
		ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask));
		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
		if (ret)
			return -EFAULT;
		sigset_from_compat(&new_ka.sa.sa_mask, &mask);
	}

	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
	if (!ret && oact) {
		sigset_to_compat(&mask, &old_ka.sa.sa_mask);
		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), 
			       &oact->sa_handler);
		ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask));
		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
#ifdef __ARCH_HAS_SA_RESTORER
		ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer),
				&oact->sa_restorer);
#endif
	}
	return ret;
}
#endif
#endif
#endif /* !CONFIG_ODD_RT_SIGACTION */

#ifdef __ARCH_WANT_SYS_SGETMASK