Loading arch/Kconfig +3 −0 Original line number Diff line number Diff line Loading @@ -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 # Loading include/linux/compat.h +24 −0 Original line number Diff line number Diff line Loading @@ -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* */ Loading Loading @@ -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); Loading kernel/signal.c +49 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
arch/Kconfig +3 −0 Original line number Diff line number Diff line Loading @@ -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 # Loading
include/linux/compat.h +24 −0 Original line number Diff line number Diff line Loading @@ -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* */ Loading Loading @@ -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); Loading
kernel/signal.c +49 −0 Original line number Diff line number Diff line Loading @@ -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 Loading