diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 120 |
1 files changed, 91 insertions, 29 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 0af8868525d6..372771e948c2 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 | ||
@@ -1159,8 +1160,9 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
1159 | return __send_signal(sig, info, t, group, from_ancestor_ns); | 1160 | return __send_signal(sig, info, t, group, from_ancestor_ns); |
1160 | } | 1161 | } |
1161 | 1162 | ||
1162 | static void print_fatal_signal(struct pt_regs *regs, int signr) | 1163 | static void print_fatal_signal(int signr) |
1163 | { | 1164 | { |
1165 | struct pt_regs *regs = signal_pt_regs(); | ||
1164 | printk("%s/%d: potentially unexpected fatal signal %d.\n", | 1166 | printk("%s/%d: potentially unexpected fatal signal %d.\n", |
1165 | current->comm, task_pid_nr(current), signr); | 1167 | current->comm, task_pid_nr(current), signr); |
1166 | 1168 | ||
@@ -1752,7 +1754,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, | |||
1752 | * see comment in do_notify_parent() about the following 4 lines | 1754 | * see comment in do_notify_parent() about the following 4 lines |
1753 | */ | 1755 | */ |
1754 | rcu_read_lock(); | 1756 | rcu_read_lock(); |
1755 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); | 1757 | info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(parent)); |
1756 | info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk)); | 1758 | info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk)); |
1757 | rcu_read_unlock(); | 1759 | rcu_read_unlock(); |
1758 | 1760 | ||
@@ -1908,7 +1910,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) | |||
1908 | preempt_disable(); | 1910 | preempt_disable(); |
1909 | read_unlock(&tasklist_lock); | 1911 | read_unlock(&tasklist_lock); |
1910 | preempt_enable_no_resched(); | 1912 | preempt_enable_no_resched(); |
1911 | schedule(); | 1913 | freezable_schedule(); |
1912 | } else { | 1914 | } else { |
1913 | /* | 1915 | /* |
1914 | * By the time we got the lock, our tracer went away. | 1916 | * By the time we got the lock, our tracer went away. |
@@ -1930,13 +1932,6 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) | |||
1930 | } | 1932 | } |
1931 | 1933 | ||
1932 | /* | 1934 | /* |
1933 | * While in TASK_TRACED, we were considered "frozen enough". | ||
1934 | * Now that we woke up, it's crucial if we're supposed to be | ||
1935 | * frozen that we freeze now before running anything substantial. | ||
1936 | */ | ||
1937 | try_to_freeze(); | ||
1938 | |||
1939 | /* | ||
1940 | * We are back. Now reacquire the siglock before touching | 1935 | * We are back. Now reacquire the siglock before touching |
1941 | * last_siginfo, so that we are sure to have synchronized with | 1936 | * last_siginfo, so that we are sure to have synchronized with |
1942 | * any signal-sending on another CPU that wants to examine it. | 1937 | * any signal-sending on another CPU that wants to examine it. |
@@ -2092,7 +2087,7 @@ static bool do_signal_stop(int signr) | |||
2092 | } | 2087 | } |
2093 | 2088 | ||
2094 | /* Now we don't run again until woken by SIGCONT or SIGKILL */ | 2089 | /* Now we don't run again until woken by SIGCONT or SIGKILL */ |
2095 | schedule(); | 2090 | freezable_schedule(); |
2096 | return true; | 2091 | return true; |
2097 | } else { | 2092 | } else { |
2098 | /* | 2093 | /* |
@@ -2138,10 +2133,9 @@ static void do_jobctl_trap(void) | |||
2138 | } | 2133 | } |
2139 | } | 2134 | } |
2140 | 2135 | ||
2141 | static int ptrace_signal(int signr, siginfo_t *info, | 2136 | static int ptrace_signal(int signr, siginfo_t *info) |
2142 | struct pt_regs *regs, void *cookie) | ||
2143 | { | 2137 | { |
2144 | ptrace_signal_deliver(regs, cookie); | 2138 | ptrace_signal_deliver(); |
2145 | /* | 2139 | /* |
2146 | * We do not check sig_kernel_stop(signr) but set this marker | 2140 | * We do not check sig_kernel_stop(signr) but set this marker |
2147 | * unconditionally because we do not know whether debugger will | 2141 | * unconditionally because we do not know whether debugger will |
@@ -2200,15 +2194,14 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, | |||
2200 | if (unlikely(uprobe_deny_signal())) | 2194 | if (unlikely(uprobe_deny_signal())) |
2201 | return 0; | 2195 | return 0; |
2202 | 2196 | ||
2203 | relock: | ||
2204 | /* | 2197 | /* |
2205 | * We'll jump back here after any time we were stopped in TASK_STOPPED. | 2198 | * Do this once, we can't return to user-mode if freezing() == T. |
2206 | * While in TASK_STOPPED, we were considered "frozen enough". | 2199 | * do_signal_stop() and ptrace_stop() do freezable_schedule() and |
2207 | * Now that we woke up, it's crucial if we're supposed to be | 2200 | * thus do not need another check after return. |
2208 | * frozen that we freeze now before running anything substantial. | ||
2209 | */ | 2201 | */ |
2210 | try_to_freeze(); | 2202 | try_to_freeze(); |
2211 | 2203 | ||
2204 | relock: | ||
2212 | spin_lock_irq(&sighand->siglock); | 2205 | spin_lock_irq(&sighand->siglock); |
2213 | /* | 2206 | /* |
2214 | * Every stopped thread goes here after wakeup. Check to see if | 2207 | * Every stopped thread goes here after wakeup. Check to see if |
@@ -2265,8 +2258,7 @@ relock: | |||
2265 | break; /* will return 0 */ | 2258 | break; /* will return 0 */ |
2266 | 2259 | ||
2267 | if (unlikely(current->ptrace) && signr != SIGKILL) { | 2260 | if (unlikely(current->ptrace) && signr != SIGKILL) { |
2268 | signr = ptrace_signal(signr, info, | 2261 | signr = ptrace_signal(signr, info); |
2269 | regs, cookie); | ||
2270 | if (!signr) | 2262 | if (!signr) |
2271 | continue; | 2263 | continue; |
2272 | } | 2264 | } |
@@ -2351,7 +2343,7 @@ relock: | |||
2351 | 2343 | ||
2352 | if (sig_kernel_coredump(signr)) { | 2344 | if (sig_kernel_coredump(signr)) { |
2353 | if (print_fatal_signals) | 2345 | if (print_fatal_signals) |
2354 | print_fatal_signal(regs, info->si_signo); | 2346 | print_fatal_signal(info->si_signo); |
2355 | /* | 2347 | /* |
2356 | * If it was able to dump core, this kills all | 2348 | * If it was able to dump core, this kills all |
2357 | * other threads in the group and synchronizes with | 2349 | * other threads in the group and synchronizes with |
@@ -2360,7 +2352,7 @@ relock: | |||
2360 | * first and our do_group_exit call below will use | 2352 | * first and our do_group_exit call below will use |
2361 | * that value and ignore the one we pass it. | 2353 | * that value and ignore the one we pass it. |
2362 | */ | 2354 | */ |
2363 | do_coredump(info, regs); | 2355 | do_coredump(info); |
2364 | } | 2356 | } |
2365 | 2357 | ||
2366 | /* | 2358 | /* |
@@ -2536,11 +2528,8 @@ static void __set_task_blocked(struct task_struct *tsk, const sigset_t *newset) | |||
2536 | */ | 2528 | */ |
2537 | void set_current_blocked(sigset_t *newset) | 2529 | void set_current_blocked(sigset_t *newset) |
2538 | { | 2530 | { |
2539 | struct task_struct *tsk = current; | ||
2540 | sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP)); | 2531 | sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP)); |
2541 | spin_lock_irq(&tsk->sighand->siglock); | 2532 | __set_current_blocked(newset); |
2542 | __set_task_blocked(tsk, newset); | ||
2543 | spin_unlock_irq(&tsk->sighand->siglock); | ||
2544 | } | 2533 | } |
2545 | 2534 | ||
2546 | void __set_current_blocked(const sigset_t *newset) | 2535 | void __set_current_blocked(const sigset_t *newset) |
@@ -3103,6 +3092,79 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s | |||
3103 | out: | 3092 | out: |
3104 | return error; | 3093 | return error; |
3105 | } | 3094 | } |
3095 | #ifdef CONFIG_GENERIC_SIGALTSTACK | ||
3096 | SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) | ||
3097 | { | ||
3098 | return do_sigaltstack(uss, uoss, current_user_stack_pointer()); | ||
3099 | } | ||
3100 | #endif | ||
3101 | |||
3102 | int restore_altstack(const stack_t __user *uss) | ||
3103 | { | ||
3104 | int err = do_sigaltstack(uss, NULL, current_user_stack_pointer()); | ||
3105 | /* squash all but EFAULT for now */ | ||
3106 | return err == -EFAULT ? err : 0; | ||
3107 | } | ||
3108 | |||
3109 | int __save_altstack(stack_t __user *uss, unsigned long sp) | ||
3110 | { | ||
3111 | struct task_struct *t = current; | ||
3112 | return __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) | | ||
3113 | __put_user(sas_ss_flags(sp), &uss->ss_flags) | | ||
3114 | __put_user(t->sas_ss_size, &uss->ss_size); | ||
3115 | } | ||
3116 | |||
3117 | #ifdef CONFIG_COMPAT | ||
3118 | #ifdef CONFIG_GENERIC_SIGALTSTACK | ||
3119 | asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, | ||
3120 | compat_stack_t __user *uoss_ptr) | ||
3121 | { | ||
3122 | stack_t uss, uoss; | ||
3123 | int ret; | ||
3124 | mm_segment_t seg; | ||
3125 | |||
3126 | if (uss_ptr) { | ||
3127 | compat_stack_t uss32; | ||
3128 | |||
3129 | memset(&uss, 0, sizeof(stack_t)); | ||
3130 | if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t))) | ||
3131 | return -EFAULT; | ||
3132 | uss.ss_sp = compat_ptr(uss32.ss_sp); | ||
3133 | uss.ss_flags = uss32.ss_flags; | ||
3134 | uss.ss_size = uss32.ss_size; | ||
3135 | } | ||
3136 | seg = get_fs(); | ||
3137 | set_fs(KERNEL_DS); | ||
3138 | ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), | ||
3139 | (stack_t __force __user *) &uoss, | ||
3140 | compat_user_stack_pointer()); | ||
3141 | set_fs(seg); | ||
3142 | if (ret >= 0 && uoss_ptr) { | ||
3143 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) || | ||
3144 | __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || | ||
3145 | __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || | ||
3146 | __put_user(uoss.ss_size, &uoss_ptr->ss_size)) | ||
3147 | ret = -EFAULT; | ||
3148 | } | ||
3149 | return ret; | ||
3150 | } | ||
3151 | |||
3152 | int compat_restore_altstack(const compat_stack_t __user *uss) | ||
3153 | { | ||
3154 | int err = compat_sys_sigaltstack(uss, NULL); | ||
3155 | /* squash all but -EFAULT for now */ | ||
3156 | return err == -EFAULT ? err : 0; | ||
3157 | } | ||
3158 | |||
3159 | int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp) | ||
3160 | { | ||
3161 | struct task_struct *t = current; | ||
3162 | return __put_user(ptr_to_compat((void __user *)t->sas_ss_sp), &uss->ss_sp) | | ||
3163 | __put_user(sas_ss_flags(sp), &uss->ss_flags) | | ||
3164 | __put_user(t->sas_ss_size, &uss->ss_size); | ||
3165 | } | ||
3166 | #endif | ||
3167 | #endif | ||
3106 | 3168 | ||
3107 | #ifdef __ARCH_WANT_SYS_SIGPENDING | 3169 | #ifdef __ARCH_WANT_SYS_SIGPENDING |
3108 | 3170 | ||
@@ -3139,7 +3201,6 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset, | |||
3139 | if (nset) { | 3201 | if (nset) { |
3140 | if (copy_from_user(&new_set, nset, sizeof(*nset))) | 3202 | if (copy_from_user(&new_set, nset, sizeof(*nset))) |
3141 | return -EFAULT; | 3203 | return -EFAULT; |
3142 | new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP)); | ||
3143 | 3204 | ||
3144 | new_blocked = current->blocked; | 3205 | new_blocked = current->blocked; |
3145 | 3206 | ||
@@ -3157,7 +3218,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset, | |||
3157 | return -EINVAL; | 3218 | return -EINVAL; |
3158 | } | 3219 | } |
3159 | 3220 | ||
3160 | __set_current_blocked(&new_blocked); | 3221 | set_current_blocked(&new_blocked); |
3161 | } | 3222 | } |
3162 | 3223 | ||
3163 | if (oset) { | 3224 | if (oset) { |
@@ -3221,6 +3282,7 @@ SYSCALL_DEFINE1(ssetmask, int, newmask) | |||
3221 | int old = current->blocked.sig[0]; | 3282 | int old = current->blocked.sig[0]; |
3222 | sigset_t newset; | 3283 | sigset_t newset; |
3223 | 3284 | ||
3285 | siginitset(&newset, newmask); | ||
3224 | set_current_blocked(&newset); | 3286 | set_current_blocked(&newset); |
3225 | 3287 | ||
3226 | return old; | 3288 | return old; |