generic compat_sys_sigaltstack()
Again, conditional on CONFIG_GENERIC_SIGALTSTACK Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
6bf9adfc90
commit
9026843952
|
@ -136,52 +136,6 @@ asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||||
return sigsuspend(&blocked);
|
return sigsuspend(&blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
|
|
||||||
stack_ia32_t __user *uoss_ptr,
|
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
stack_t uss, uoss;
|
|
||||||
int ret, err = 0;
|
|
||||||
mm_segment_t seg;
|
|
||||||
|
|
||||||
if (uss_ptr) {
|
|
||||||
u32 ptr;
|
|
||||||
|
|
||||||
memset(&uss, 0, sizeof(stack_t));
|
|
||||||
if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
get_user_try {
|
|
||||||
get_user_ex(ptr, &uss_ptr->ss_sp);
|
|
||||||
get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
|
|
||||||
get_user_ex(uss.ss_size, &uss_ptr->ss_size);
|
|
||||||
} get_user_catch(err);
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
return -EFAULT;
|
|
||||||
uss.ss_sp = compat_ptr(ptr);
|
|
||||||
}
|
|
||||||
seg = get_fs();
|
|
||||||
set_fs(KERNEL_DS);
|
|
||||||
ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
|
|
||||||
(stack_t __force __user *) &uoss, regs->sp);
|
|
||||||
set_fs(seg);
|
|
||||||
if (ret >= 0 && uoss_ptr) {
|
|
||||||
if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
put_user_try {
|
|
||||||
put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
|
|
||||||
put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
|
|
||||||
put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
|
|
||||||
} put_user_catch(err);
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
ret = -EFAULT;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do a signal return; undo the signal stack.
|
* Do a signal return; undo the signal stack.
|
||||||
*/
|
*/
|
||||||
|
@ -292,7 +246,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
|
||||||
struct rt_sigframe_ia32 __user *frame;
|
struct rt_sigframe_ia32 __user *frame;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
unsigned int ax;
|
unsigned int ax;
|
||||||
struct pt_regs tregs;
|
|
||||||
|
|
||||||
frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
|
frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
|
||||||
|
|
||||||
|
@ -306,8 +259,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
|
||||||
if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
tregs = *regs;
|
if (compat_restore_altstack(&frame->uc.uc_stack))
|
||||||
if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
|
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
return ax;
|
return ax;
|
||||||
|
|
|
@ -464,7 +464,6 @@ GLOBAL(\label)
|
||||||
|
|
||||||
PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
|
PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
|
||||||
PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
|
PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
|
||||||
PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
|
|
||||||
PTREGSCALL stub32_execve, compat_sys_execve, %rcx
|
PTREGSCALL stub32_execve, compat_sys_execve, %rcx
|
||||||
PTREGSCALL stub32_fork, sys_fork, %rdi
|
PTREGSCALL stub32_fork, sys_fork, %rdi
|
||||||
PTREGSCALL stub32_vfork, sys_vfork, %rdi
|
PTREGSCALL stub32_vfork, sys_vfork, %rdi
|
||||||
|
|
|
@ -29,16 +29,10 @@ struct old_sigaction32 {
|
||||||
unsigned int sa_restorer; /* Another 32 bit pointer */
|
unsigned int sa_restorer; /* Another 32 bit pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct sigaltstack_ia32 {
|
|
||||||
unsigned int ss_sp;
|
|
||||||
int ss_flags;
|
|
||||||
unsigned int ss_size;
|
|
||||||
} stack_ia32_t;
|
|
||||||
|
|
||||||
struct ucontext_ia32 {
|
struct ucontext_ia32 {
|
||||||
unsigned int uc_flags;
|
unsigned int uc_flags;
|
||||||
unsigned int uc_link;
|
unsigned int uc_link;
|
||||||
stack_ia32_t uc_stack;
|
compat_stack_t uc_stack;
|
||||||
struct sigcontext_ia32 uc_mcontext;
|
struct sigcontext_ia32 uc_mcontext;
|
||||||
compat_sigset_t uc_sigmask; /* mask last for extensibility */
|
compat_sigset_t uc_sigmask; /* mask last for extensibility */
|
||||||
};
|
};
|
||||||
|
@ -46,7 +40,7 @@ struct ucontext_ia32 {
|
||||||
struct ucontext_x32 {
|
struct ucontext_x32 {
|
||||||
unsigned int uc_flags;
|
unsigned int uc_flags;
|
||||||
unsigned int uc_link;
|
unsigned int uc_link;
|
||||||
stack_ia32_t uc_stack;
|
compat_stack_t uc_stack;
|
||||||
unsigned int uc__pad0; /* needed for alignment */
|
unsigned int uc__pad0; /* needed for alignment */
|
||||||
struct sigcontext uc_mcontext; /* the 64-bit sigcontext type */
|
struct sigcontext uc_mcontext; /* the 64-bit sigcontext type */
|
||||||
compat_sigset_t uc_sigmask; /* mask last for extensibility */
|
compat_sigset_t uc_sigmask; /* mask last for extensibility */
|
||||||
|
|
|
@ -69,8 +69,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned,
|
||||||
|
|
||||||
/* ia32/ia32_signal.c */
|
/* ia32/ia32_signal.c */
|
||||||
asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
|
asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
|
||||||
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *,
|
|
||||||
stack_ia32_t __user *, struct pt_regs *);
|
|
||||||
asmlinkage long sys32_sigreturn(struct pt_regs *);
|
asmlinkage long sys32_sigreturn(struct pt_regs *);
|
||||||
asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
|
asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
|
||||||
|
|
||||||
|
|
|
@ -912,8 +912,6 @@ ENTRY(stub_rt_sigreturn)
|
||||||
END(stub_rt_sigreturn)
|
END(stub_rt_sigreturn)
|
||||||
|
|
||||||
#ifdef CONFIG_X86_X32_ABI
|
#ifdef CONFIG_X86_X32_ABI
|
||||||
PTREGSCALL stub_x32_sigaltstack, sys32_sigaltstack, %rdx
|
|
||||||
|
|
||||||
ENTRY(stub_x32_rt_sigreturn)
|
ENTRY(stub_x32_rt_sigreturn)
|
||||||
CFI_STARTPROC
|
CFI_STARTPROC
|
||||||
addq $8, %rsp
|
addq $8, %rsp
|
||||||
|
|
|
@ -857,7 +857,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
|
||||||
struct rt_sigframe_x32 __user *frame;
|
struct rt_sigframe_x32 __user *frame;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
unsigned long ax;
|
unsigned long ax;
|
||||||
struct pt_regs tregs;
|
|
||||||
|
|
||||||
frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
|
frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
|
||||||
|
|
||||||
|
@ -871,8 +870,7 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
tregs = *regs;
|
if (compat_restore_altstack(&frame->uc.uc_stack))
|
||||||
if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
|
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
return ax;
|
return ax;
|
||||||
|
|
|
@ -192,7 +192,7 @@
|
||||||
183 i386 getcwd sys_getcwd
|
183 i386 getcwd sys_getcwd
|
||||||
184 i386 capget sys_capget
|
184 i386 capget sys_capget
|
||||||
185 i386 capset sys_capset
|
185 i386 capset sys_capset
|
||||||
186 i386 sigaltstack sys_sigaltstack stub32_sigaltstack
|
186 i386 sigaltstack sys_sigaltstack compat_sys_sigaltstack
|
||||||
187 i386 sendfile sys_sendfile sys32_sendfile
|
187 i386 sendfile sys_sendfile sys32_sendfile
|
||||||
188 i386 getpmsg
|
188 i386 getpmsg
|
||||||
189 i386 putpmsg
|
189 i386 putpmsg
|
||||||
|
|
|
@ -337,7 +337,7 @@
|
||||||
522 x32 rt_sigpending sys32_rt_sigpending
|
522 x32 rt_sigpending sys32_rt_sigpending
|
||||||
523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
|
523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
|
||||||
524 x32 rt_sigqueueinfo sys32_rt_sigqueueinfo
|
524 x32 rt_sigqueueinfo sys32_rt_sigqueueinfo
|
||||||
525 x32 sigaltstack stub_x32_sigaltstack
|
525 x32 sigaltstack compat_sys_sigaltstack
|
||||||
526 x32 timer_create compat_sys_timer_create
|
526 x32 timer_create compat_sys_timer_create
|
||||||
527 x32 mq_notify compat_sys_mq_notify
|
527 x32 mq_notify compat_sys_mq_notify
|
||||||
528 x32 kexec_load compat_sys_kexec_load
|
528 x32 kexec_load compat_sys_kexec_load
|
||||||
|
|
|
@ -68,6 +68,16 @@
|
||||||
#ifndef compat_user_stack_pointer
|
#ifndef compat_user_stack_pointer
|
||||||
#define compat_user_stack_pointer() current_user_stack_pointer()
|
#define compat_user_stack_pointer() current_user_stack_pointer()
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_GENERIC_SIGALTSTACK
|
||||||
|
#ifndef compat_sigaltstack /* we'll need that for MIPS */
|
||||||
|
typedef struct compat_sigaltstack {
|
||||||
|
compat_uptr_t ss_sp;
|
||||||
|
int ss_flags;
|
||||||
|
compat_size_t ss_size;
|
||||||
|
} compat_stack_t;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define compat_jiffies_to_clock_t(x) \
|
#define compat_jiffies_to_clock_t(x) \
|
||||||
(((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
|
(((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
|
||||||
|
|
||||||
|
@ -632,6 +642,12 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
|
||||||
|
|
||||||
asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
|
asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
|
||||||
compat_off_t __user *offset, compat_size_t count);
|
compat_off_t __user *offset, compat_size_t count);
|
||||||
|
#ifdef CONFIG_GENERIC_SIGALTSTACK
|
||||||
|
asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
|
||||||
|
compat_stack_t __user *uoss_ptr);
|
||||||
|
|
||||||
|
int compat_restore_altstack(const compat_stack_t __user *uss);
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/nsproxy.h>
|
#include <linux/nsproxy.h>
|
||||||
#include <linux/user_namespace.h>
|
#include <linux/user_namespace.h>
|
||||||
#include <linux/uprobes.h>
|
#include <linux/uprobes.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/signal.h>
|
#include <trace/events/signal.h>
|
||||||
|
|
||||||
|
@ -3116,6 +3117,50 @@ int restore_altstack(const stack_t __user *uss)
|
||||||
return err == -EFAULT ? err : 0;
|
return err == -EFAULT ? err : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
#ifdef CONFIG_GENERIC_SIGALTSTACK
|
||||||
|
asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
|
||||||
|
compat_stack_t __user *uoss_ptr)
|
||||||
|
{
|
||||||
|
stack_t uss, uoss;
|
||||||
|
int ret;
|
||||||
|
mm_segment_t seg;
|
||||||
|
|
||||||
|
if (uss_ptr) {
|
||||||
|
compat_stack_t uss32;
|
||||||
|
|
||||||
|
memset(&uss, 0, sizeof(stack_t));
|
||||||
|
if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t)))
|
||||||
|
return -EFAULT;
|
||||||
|
uss.ss_sp = compat_ptr(uss32.ss_sp);
|
||||||
|
uss.ss_flags = uss32.ss_flags;
|
||||||
|
uss.ss_size = uss32.ss_size;
|
||||||
|
}
|
||||||
|
seg = get_fs();
|
||||||
|
set_fs(KERNEL_DS);
|
||||||
|
ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
|
||||||
|
(stack_t __force __user *) &uoss,
|
||||||
|
compat_user_stack_pointer());
|
||||||
|
set_fs(seg);
|
||||||
|
if (ret >= 0 && uoss_ptr) {
|
||||||
|
if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||
|
||||||
|
__put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
|
||||||
|
__put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
|
||||||
|
__put_user(uoss.ss_size, &uoss_ptr->ss_size))
|
||||||
|
ret = -EFAULT;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compat_restore_altstack(const compat_stack_t __user *uss)
|
||||||
|
{
|
||||||
|
int err = compat_sys_sigaltstack(uss, NULL);
|
||||||
|
/* squash all but -EFAULT for now */
|
||||||
|
return err == -EFAULT ? err : 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __ARCH_WANT_SYS_SIGPENDING
|
#ifdef __ARCH_WANT_SYS_SIGPENDING
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Reference in New Issue