diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-14 14:47:53 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-19 18:07:41 -0500 |
commit | 9026843952adac5b123c7b8dc961e5c15828d9e1 (patch) | |
tree | 4ef89cf05cf97427ceb2587fed94a6a12833d527 /kernel/signal.c | |
parent | 6bf9adfc90370b695cb111116e15fdc0e1906270 (diff) |
generic compat_sys_sigaltstack()
Again, conditional on CONFIG_GENERIC_SIGALTSTACK
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index f05f4c4150d9..aee85bd76b8a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/nsproxy.h> | 31 | #include <linux/nsproxy.h> |
32 | #include <linux/user_namespace.h> | 32 | #include <linux/user_namespace.h> |
33 | #include <linux/uprobes.h> | 33 | #include <linux/uprobes.h> |
34 | #include <linux/compat.h> | ||
34 | #define CREATE_TRACE_POINTS | 35 | #define CREATE_TRACE_POINTS |
35 | #include <trace/events/signal.h> | 36 | #include <trace/events/signal.h> |
36 | 37 | ||
@@ -3116,6 +3117,50 @@ int restore_altstack(const stack_t __user *uss) | |||
3116 | return err == -EFAULT ? err : 0; | 3117 | return err == -EFAULT ? err : 0; |
3117 | } | 3118 | } |
3118 | 3119 | ||
3120 | #ifdef CONFIG_COMPAT | ||
3121 | #ifdef CONFIG_GENERIC_SIGALTSTACK | ||
3122 | asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, | ||
3123 | compat_stack_t __user *uoss_ptr) | ||
3124 | { | ||
3125 | stack_t uss, uoss; | ||
3126 | int ret; | ||
3127 | mm_segment_t seg; | ||
3128 | |||
3129 | if (uss_ptr) { | ||
3130 | compat_stack_t uss32; | ||
3131 | |||
3132 | memset(&uss, 0, sizeof(stack_t)); | ||
3133 | if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t))) | ||
3134 | return -EFAULT; | ||
3135 | uss.ss_sp = compat_ptr(uss32.ss_sp); | ||
3136 | uss.ss_flags = uss32.ss_flags; | ||
3137 | uss.ss_size = uss32.ss_size; | ||
3138 | } | ||
3139 | seg = get_fs(); | ||
3140 | set_fs(KERNEL_DS); | ||
3141 | ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), | ||
3142 | (stack_t __force __user *) &uoss, | ||
3143 | compat_user_stack_pointer()); | ||
3144 | set_fs(seg); | ||
3145 | if (ret >= 0 && uoss_ptr) { | ||
3146 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) || | ||
3147 | __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || | ||
3148 | __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || | ||
3149 | __put_user(uoss.ss_size, &uoss_ptr->ss_size)) | ||
3150 | ret = -EFAULT; | ||
3151 | } | ||
3152 | return ret; | ||
3153 | } | ||
3154 | |||
3155 | int compat_restore_altstack(const compat_stack_t __user *uss) | ||
3156 | { | ||
3157 | int err = compat_sys_sigaltstack(uss, NULL); | ||
3158 | /* squash all but -EFAULT for now */ | ||
3159 | return err == -EFAULT ? err : 0; | ||
3160 | } | ||
3161 | #endif | ||
3162 | #endif | ||
3163 | |||
3119 | #ifdef __ARCH_WANT_SYS_SIGPENDING | 3164 | #ifdef __ARCH_WANT_SYS_SIGPENDING |
3120 | 3165 | ||
3121 | /** | 3166 | /** |