8c4322f442a9fd33680b4ebbb6ba327fb91170c5
[lunaix-os.git] / lunaix-os / kernel / process / signal.c
1 #include <lunaix/process.h>
2 #include <lunaix/sched.h>
3 #include <lunaix/signal.h>
4 #include <lunaix/spike.h>
5 #include <lunaix/status.h>
6 #include <lunaix/syscall.h>
7 #include <lunaix/syslog.h>
8
9 LOG_MODULE("SIG")
10
11 #include <klibc/string.h>
12
13 extern struct scheduler sched_ctx; /* kernel/sched.c */
14
15 #define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM))
16 #define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
17 #define CORE (sigset(SIGSEGV))
18
19 static inline void
20 signal_terminate(int errcode)
21 {
22     terminate_proc(errcode | PEXITSIG);
23 }
24
25 // Referenced in kernel/asm/x86/interrupt.S
26 void*
27 signal_dispatch()
28 {
29     if (!__current->sigctx.sig_pending) {
30         // 没有待处理信号
31         return 0;
32     }
33
34     struct sighail* psig = &__current->sigctx;
35     struct sigact* prev_working = psig->inprogress;
36     sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
37
38     int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
39
40     sigset_clear(psig->sig_pending, sig_selected);
41
42     struct sigact* action = &psig->signals[sig_selected];
43
44     if (sig_selected == 0) {
45         // SIG0 is reserved
46         return 0;
47     }
48
49     if (!action->sa_actor) {
50         if (sigset_test(TERMSIG, sig_selected)) {
51             signal_terminate(sig_selected);
52             schedule();
53             // never return
54         }
55         return 0;
56     }
57
58     ptr_t ustack = __current->ustack_top;
59
60     if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
61         // 用户栈没有空间存放信号上下文
62         return 0;
63     }
64
65     struct proc_sig* sigframe =
66       (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
67
68     sigframe->sig_num = sig_selected;
69     sigframe->sigact = action->sa_actor;
70     sigframe->sighand = action->sa_handler;
71
72     sigframe->saved_ictx = __current->intr_ctx;
73
74     action->prev = prev_working;
75     psig->inprogress = action;
76
77     return sigframe;
78 }
79
80 void
81 proc_clear_signal(struct proc_info* proc)
82 {
83     memset(&proc->sigctx, 0, sizeof(proc->sigctx));
84 }
85
86 void
87 proc_setsignal(struct proc_info* proc, int signum)
88 {
89     sigset_add(proc->sigctx.sig_pending, signum);
90     proc->sigctx.signals[signum].sender = __current->pid;
91 }
92
93 int
94 signal_send(pid_t pid, int signum)
95 {
96     if (signum < 0 || signum >= _SIG_NUM) {
97         __current->k_status = EINVAL;
98         return -1;
99     }
100
101     pid_t sender_pid = __current->pid;
102     struct proc_info* proc;
103
104     if (pid > 0) {
105         proc = get_process(pid);
106         goto send_single;
107     } else if (!pid) {
108         proc = __current;
109         goto send_grp;
110     } else if (pid < -1) {
111         proc = get_process(-pid);
112         goto send_grp;
113     } else {
114         // TODO: send to all process.
115         //  But I don't want to support it yet.
116         __current->k_status = EINVAL;
117         return -1;
118     }
119
120 send_grp:
121     struct proc_info *pos, *n;
122     llist_for_each(pos, n, &proc->grp_member, grp_member)
123     {
124         struct sighail* sh = &pos->sigctx;
125         sigset_add(sh->sig_pending, signum);
126         sh->signals[signum].sender = sender_pid;
127     }
128
129 send_single:
130     if (proc_terminated(proc)) {
131         __current->k_status = EINVAL;
132         return -1;
133     }
134
135     sigset_add(proc->sigctx.sig_pending, signum);
136     proc->sigctx.signals[signum].sender = sender_pid;
137
138     return 0;
139 }
140
141 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
142 {
143     __current->intr_ctx = sig_ctx->saved_ictx;
144
145     struct sigact* current = __current->sigctx.inprogress;
146     if (current) {
147         __current->sigctx.inprogress = current->prev;
148         current->prev = NULL;
149     } else {
150         __current->sigctx.inprogress = NULL;
151     }
152
153     if (proc_terminated(__current)) {
154         __current->exit_code |= PEXITSIG;
155     } else if (sigset_test(CORE, sig_ctx->sig_num)) {
156         signal_terminate(sig_ctx->sig_num);
157     }
158
159     ptr_t ictx = (ptr_t)__current->intr_ctx;
160
161     /*
162         Ensure our restored context is within kernel stack
163
164         This prevent user to forge their own context such that arbitrary code
165        can be executed as supervisor level
166     */
167     if (!within_kstack(ictx)) {
168         signal_terminate(SIGSEGV);
169     }
170
171     schedule();
172
173     // never reach!
174     return 0;
175 }
176
177 __DEFINE_LXSYSCALL3(int,
178                     sigprocmask,
179                     int,
180                     how,
181                     const sigset_t,
182                     *set,
183                     sigset_t,
184                     *oldset)
185 {
186     struct sighail* sh = &__current->sigctx;
187     *oldset = sh->sig_mask;
188
189     if (how == _SIG_BLOCK) {
190         sigset_union(sh->sig_mask, *set);
191     } else if (how == _SIG_UNBLOCK) {
192         sigset_intersect(sh->sig_mask, ~(*set));
193     } else if (how == _SIG_SETMASK) {
194         sh->sig_mask = *set;
195     } else {
196         return 0;
197     }
198
199     sigset_intersect(sh->sig_mask, ~UNMASKABLE);
200     return 1;
201 }
202
203 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
204 {
205     if (signum <= 0 || signum >= _SIG_NUM) {
206         return -1;
207     }
208
209     if (sigset_test(UNMASKABLE, signum)) {
210         return -1;
211     }
212
213     struct sigact* sa = &__current->sigctx.signals[signum];
214
215     sa->sa_actor = (void*)action->sa_sigaction;
216     sa->sa_handler = (void*)action->sa_handler;
217     sigset_union(sa->sa_mask, sigset(signum));
218
219     return 0;
220 }
221
222 __DEFINE_LXSYSCALL(int, pause)
223 {
224     pause_current();
225     sched_yieldk();
226
227     __current->k_status = EINTR;
228     return -1;
229 }
230
231 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
232 {
233     return signal_send(pid, signum);
234 }
235
236 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
237 {
238     *sigset = __current->sigctx.sig_pending;
239     return 0;
240 }
241
242 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
243 {
244     sigset_t tmp = __current->sigctx.sig_mask;
245     __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
246
247     pause_current();
248     sched_yieldk();
249
250     __current->sigctx.sig_mask = tmp;
251     return -1;
252 }