Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/um/kernel/signal.c
26486 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4
*/
5
6
#include <linux/module.h>
7
#include <linux/ptrace.h>
8
#include <linux/sched.h>
9
#include <linux/ftrace.h>
10
#include <asm/siginfo.h>
11
#include <asm/signal.h>
12
#include <asm/unistd.h>
13
#include <frame_kern.h>
14
#include <kern_util.h>
15
#include <os.h>
16
17
EXPORT_SYMBOL(block_signals);
18
EXPORT_SYMBOL(unblock_signals);
19
20
void block_signals_trace(void)
21
{
22
block_signals();
23
if (current_thread_info())
24
trace_hardirqs_off();
25
}
26
27
void unblock_signals_trace(void)
28
{
29
if (current_thread_info())
30
trace_hardirqs_on();
31
unblock_signals();
32
}
33
34
void um_trace_signals_on(void)
35
{
36
if (current_thread_info())
37
trace_hardirqs_on();
38
}
39
40
void um_trace_signals_off(void)
41
{
42
if (current_thread_info())
43
trace_hardirqs_off();
44
}
45
46
/*
47
* OK, we're invoking a handler
48
*/
49
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
50
{
51
sigset_t *oldset = sigmask_to_save();
52
int singlestep = 0;
53
unsigned long sp;
54
int err;
55
56
if (test_thread_flag(TIF_SINGLESTEP) && (current->ptrace & PT_PTRACED))
57
singlestep = 1;
58
59
/* Did we come from a system call? */
60
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
61
/* If so, check system call restarting.. */
62
switch (PT_REGS_SYSCALL_RET(regs)) {
63
case -ERESTART_RESTARTBLOCK:
64
case -ERESTARTNOHAND:
65
PT_REGS_SYSCALL_RET(regs) = -EINTR;
66
break;
67
68
case -ERESTARTSYS:
69
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
70
PT_REGS_SYSCALL_RET(regs) = -EINTR;
71
break;
72
}
73
fallthrough;
74
case -ERESTARTNOINTR:
75
PT_REGS_RESTART_SYSCALL(regs);
76
PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
77
break;
78
}
79
}
80
81
sp = PT_REGS_SP(regs);
82
if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
83
sp = current->sas_ss_sp + current->sas_ss_size;
84
85
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
86
if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
87
err = setup_signal_stack_sc(sp, ksig, regs, oldset);
88
else
89
#endif
90
err = setup_signal_stack_si(sp, ksig, regs, oldset);
91
92
signal_setup_done(err, ksig, singlestep);
93
}
94
95
void do_signal(struct pt_regs *regs)
96
{
97
struct ksignal ksig;
98
int handled_sig = 0;
99
100
while (get_signal(&ksig)) {
101
handled_sig = 1;
102
/* Whee! Actually deliver the signal. */
103
handle_signal(&ksig, regs);
104
}
105
106
/* Did we come from a system call? */
107
if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
108
/* Restart the system call - no handlers present */
109
switch (PT_REGS_SYSCALL_RET(regs)) {
110
case -ERESTARTNOHAND:
111
case -ERESTARTSYS:
112
case -ERESTARTNOINTR:
113
PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
114
PT_REGS_RESTART_SYSCALL(regs);
115
break;
116
case -ERESTART_RESTARTBLOCK:
117
PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
118
PT_REGS_RESTART_SYSCALL(regs);
119
break;
120
}
121
}
122
123
/*
124
* if there's no signal to deliver, we just put the saved sigmask
125
* back
126
*/
127
if (!handled_sig)
128
restore_saved_sigmask();
129
}
130
131