Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro: "This is the first pile; another one will come a bit later and will contain SYSCALL_DEFINE-related patches. - a bunch of signal-related syscalls (both native and compat) unified. - a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE (fixing several potential problems with missing argument validation, while we are at it) - a lot of now-pointless wrappers killed - a couple of architectures (cris and hexagon) forgot to save altstack settings into sigframe, even though they used the (uninitialized) values in sigreturn; fixed. - microblaze fixes for delivery of multiple signals arriving at once - saner set of helpers for signal delivery introduced, several architectures switched to using those." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits) x86: convert to ksignal sparc: convert to ksignal arm: switch to struct ksignal * passing alpha: pass k_sigaction and siginfo_t using ksignal pointer burying unused conditionals make do_sigaltstack() static arm64: switch to generic old sigaction() (compat-only) arm64: switch to generic compat rt_sigaction() arm64: switch compat to generic old sigsuspend arm64: switch to generic compat rt_sigqueueinfo() arm64: switch to generic compat rt_sigpending() arm64: switch to generic compat rt_sigprocmask() arm64: switch to generic sigaltstack sparc: switch to generic old sigsuspend sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE sparc: kill sign-extending wrappers for native syscalls kill sparc32_open() sparc: switch to use of generic old sigaction sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE mips: switch to generic sys_fork() and sys_clone() ...
Cette révision appartient à :
@@ -1748,44 +1748,6 @@ ENTRY(sys_rt_sigreturn_wrapper)
|
||||
LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
|
||||
ENDPROC(sys_rt_sigreturn_wrapper)
|
||||
|
||||
ENTRY(sys_sigaltstack_wrapper)
|
||||
/* Get the user stack pointer */
|
||||
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
|
||||
ldo TASK_REGS(%r1),%r24 /* get pt regs */
|
||||
LDREG TASK_PT_GR30(%r24),%r24
|
||||
STREG %r2, -RP_OFFSET(%r30)
|
||||
#ifdef CONFIG_64BIT
|
||||
ldo FRAME_SIZE(%r30), %r30
|
||||
BL do_sigaltstack,%r2
|
||||
ldo -16(%r30),%r29 /* Reference param save area */
|
||||
#else
|
||||
BL do_sigaltstack,%r2
|
||||
ldo FRAME_SIZE(%r30), %r30
|
||||
#endif
|
||||
|
||||
ldo -FRAME_SIZE(%r30), %r30
|
||||
LDREG -RP_OFFSET(%r30), %r2
|
||||
bv %r0(%r2)
|
||||
nop
|
||||
ENDPROC(sys_sigaltstack_wrapper)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
ENTRY(sys32_sigaltstack_wrapper)
|
||||
/* Get the user stack pointer */
|
||||
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
|
||||
LDREG TASK_PT_GR30(%r24),%r24
|
||||
STREG %r2, -RP_OFFSET(%r30)
|
||||
ldo FRAME_SIZE(%r30), %r30
|
||||
BL do_sigaltstack32,%r2
|
||||
ldo -16(%r30),%r29 /* Reference param save area */
|
||||
|
||||
ldo -FRAME_SIZE(%r30), %r30
|
||||
LDREG -RP_OFFSET(%r30), %r2
|
||||
bv %r0(%r2)
|
||||
nop
|
||||
ENDPROC(sys32_sigaltstack_wrapper)
|
||||
#endif
|
||||
|
||||
ENTRY(syscall_exit)
|
||||
/* NOTE: HP-UX syscalls also come through here
|
||||
* after hpux_syscall_exit fixes up return
|
||||
|
@@ -143,7 +143,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
||||
goto give_sigsegv;
|
||||
DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
|
||||
usp, &compat_frame->uc.uc_stack);
|
||||
if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
|
||||
if (compat_restore_altstack(&compat_frame->uc.uc_stack))
|
||||
goto give_sigsegv;
|
||||
} else
|
||||
#endif
|
||||
@@ -154,7 +154,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
||||
goto give_sigsegv;
|
||||
DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
|
||||
usp, &frame->uc.uc_stack);
|
||||
if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
|
||||
if (restore_altstack(&frame->uc.uc_stack))
|
||||
goto give_sigsegv;
|
||||
}
|
||||
|
||||
@@ -262,15 +262,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (is_compat_task()) {
|
||||
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
|
||||
err |= copy_siginfo_to_user32(&compat_frame->info, info);
|
||||
DBG(1,"SETUP_RT_FRAME: 1\n");
|
||||
compat_val = (compat_int_t)current->sas_ss_sp;
|
||||
err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
|
||||
DBG(1,"SETUP_RT_FRAME: 2\n");
|
||||
compat_val = (compat_int_t)current->sas_ss_size;
|
||||
err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
|
||||
DBG(1,"SETUP_RT_FRAME: 3\n");
|
||||
compat_val = sas_ss_flags(regs->gr[30]);
|
||||
err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);
|
||||
err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
|
||||
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
|
||||
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
|
||||
err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
|
||||
@@ -282,10 +274,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
{
|
||||
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
|
||||
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
|
||||
err |= __put_user(sas_ss_flags(regs->gr[30]),
|
||||
&frame->uc.uc_stack.ss_flags);
|
||||
err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
|
||||
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
|
||||
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
|
||||
|
@@ -60,136 +60,6 @@ sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
|
||||
s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
|
||||
}
|
||||
|
||||
static int
|
||||
put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
|
||||
{
|
||||
compat_sigset_t s;
|
||||
|
||||
if (sz != sizeof(compat_sigset_t))
|
||||
return -EINVAL;
|
||||
sigset_64to32(&s, set);
|
||||
|
||||
return copy_to_user(up, &s, sizeof s);
|
||||
}
|
||||
|
||||
static int
|
||||
get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
|
||||
{
|
||||
compat_sigset_t s;
|
||||
int r;
|
||||
|
||||
if (sz != sizeof(compat_sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if ((r = copy_from_user(&s, up, sz)) == 0) {
|
||||
sigset_32to64(set, &s);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
|
||||
unsigned int sigsetsize)
|
||||
{
|
||||
sigset_t old_set, new_set;
|
||||
int ret;
|
||||
|
||||
if (set) {
|
||||
ret = get_sigset32(set, &new_set, sigsetsize);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
|
||||
oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
|
||||
|
||||
if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
|
||||
{
|
||||
int ret;
|
||||
sigset_t set;
|
||||
|
||||
KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
|
||||
|
||||
if (!ret && put_sigset32(uset, &set, sigsetsize))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long
|
||||
sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
|
||||
size_t sigsetsize)
|
||||
{
|
||||
struct k_sigaction32 new_sa32, old_sa32;
|
||||
struct k_sigaction new_sa, old_sa;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(compat_sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (act) {
|
||||
if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
|
||||
return -EFAULT;
|
||||
new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
|
||||
new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
|
||||
sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
|
||||
}
|
||||
|
||||
ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
|
||||
|
||||
if (!ret && oact) {
|
||||
sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
|
||||
old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
|
||||
old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
|
||||
if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
|
||||
return -EFAULT;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
|
||||
{
|
||||
compat_stack_t ss32, oss32;
|
||||
stack_t ss, oss;
|
||||
stack_t *ssp = NULL, *ossp = NULL;
|
||||
int ret;
|
||||
|
||||
if (uss32) {
|
||||
if (copy_from_user(&ss32, uss32, sizeof ss32))
|
||||
return -EFAULT;
|
||||
|
||||
ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
|
||||
ss.ss_flags = ss32.ss_flags;
|
||||
ss.ss_size = ss32.ss_size;
|
||||
|
||||
ssp = &ss;
|
||||
}
|
||||
|
||||
if (uoss32)
|
||||
ossp = &oss;
|
||||
|
||||
KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
|
||||
|
||||
if (!ret && uoss32) {
|
||||
oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
|
||||
oss32.ss_flags = oss.ss_flags;
|
||||
oss32.ss_size = oss.ss_size;
|
||||
if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long
|
||||
restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
|
||||
struct pt_regs *regs)
|
||||
@@ -506,22 +376,3 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
|
||||
struct compat_siginfo __user *uinfo)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (copy_siginfo_from_user32(&info, uinfo))
|
||||
return -EFAULT;
|
||||
|
||||
/* Not even root can pretend to send signals from the kernel.
|
||||
Nor can they impersonate a kill(), which adds source info. */
|
||||
if (info.si_code >= 0)
|
||||
return -EPERM;
|
||||
info.si_signo = sig;
|
||||
|
||||
/* POSIX.1b doesn't mention process groups. */
|
||||
return kill_proc_info(sig, &info, pid);
|
||||
}
|
||||
|
||||
|
@@ -21,23 +21,6 @@
|
||||
|
||||
#include <linux/compat.h>
|
||||
|
||||
typedef compat_uptr_t compat_sighandler_t;
|
||||
|
||||
typedef struct compat_sigaltstack {
|
||||
compat_uptr_t ss_sp;
|
||||
compat_int_t ss_flags;
|
||||
compat_size_t ss_size;
|
||||
} compat_stack_t;
|
||||
|
||||
/* Most things should be clean enough to redefine this at will, if care
|
||||
is taken to make libc match. */
|
||||
|
||||
struct compat_sigaction {
|
||||
compat_sighandler_t sa_handler;
|
||||
compat_uint_t sa_flags;
|
||||
compat_sigset_t sa_mask; /* mask last for extensibility */
|
||||
};
|
||||
|
||||
/* 32-bit ucontext as seen from an 64-bit kernel */
|
||||
struct compat_ucontext {
|
||||
compat_uint_t uc_flags;
|
||||
@@ -51,10 +34,6 @@ struct compat_ucontext {
|
||||
|
||||
/* ELF32 signal handling */
|
||||
|
||||
struct k_sigaction32 {
|
||||
struct compat_sigaction sa;
|
||||
};
|
||||
|
||||
int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
|
||||
int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
|
||||
|
||||
@@ -102,8 +81,6 @@ struct compat_rt_sigframe {
|
||||
|
||||
void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
|
||||
void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
|
||||
int do_sigaltstack32 (const compat_stack_t __user *uss32,
|
||||
compat_stack_t __user *uoss32, unsigned long sp);
|
||||
long restore_sigcontext32(struct compat_sigcontext __user *sc,
|
||||
struct compat_regfile __user *rf,
|
||||
struct pt_regs *regs);
|
||||
|
@@ -33,16 +33,4 @@
|
||||
set_fs (old_fs); \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
typedef __u32 __sighandler_t32;
|
||||
|
||||
struct sigaction32 {
|
||||
__sighandler_t32 sa_handler;
|
||||
unsigned int sa_flags;
|
||||
compat_sigset_t sa_mask; /* mask last for extensibility */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -252,7 +252,7 @@
|
||||
ENTRY_SAME(mremap)
|
||||
ENTRY_SAME(setresuid)
|
||||
ENTRY_SAME(getresuid) /* 165 */
|
||||
ENTRY_DIFF(sigaltstack_wrapper)
|
||||
ENTRY_COMP(sigaltstack)
|
||||
ENTRY_SAME(ni_syscall) /* query_module */
|
||||
ENTRY_SAME(poll)
|
||||
/* structs contain pointers and an in_addr... */
|
||||
@@ -262,9 +262,9 @@
|
||||
ENTRY_SAME(prctl)
|
||||
/* signals need a careful review */
|
||||
ENTRY_SAME(rt_sigreturn_wrapper)
|
||||
ENTRY_DIFF(rt_sigaction)
|
||||
ENTRY_DIFF(rt_sigprocmask) /* 175 */
|
||||
ENTRY_DIFF(rt_sigpending)
|
||||
ENTRY_COMP(rt_sigaction)
|
||||
ENTRY_COMP(rt_sigprocmask) /* 175 */
|
||||
ENTRY_COMP(rt_sigpending)
|
||||
ENTRY_COMP(rt_sigtimedwait)
|
||||
/* even though the struct siginfo_t is different, it appears like
|
||||
* all the paths use values which should be same wide and narrow.
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur