d00e75755cf16136481e6e1213ebe7865d70abd4
[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_setsignal(struct proc_info* proc, int signum)
82 {
83     sigset_add(proc->sigctx.sig_pending, signum);
84     proc->sigctx.signals[signum].sender = __current->pid;
85 }
86
87 int
88 signal_send(pid_t pid, int signum)
89 {
90     if (signum < 0 || signum >= _SIG_NUM) {
91         __current->k_status = EINVAL;
92         return -1;
93     }
94
95     pid_t sender_pid = __current->pid;
96     struct proc_info* proc;
97
98     if (pid > 0) {
99         proc = get_process(pid);
100         goto send_single;
101     } else if (!pid) {
102         proc = __current;
103         goto send_grp;
104     } else if (pid < -1) {
105         proc = get_process(-pid);
106         goto send_grp;
107     } else {
108         // TODO: send to all process.
109         //  But I don't want to support it yet.
110         __current->k_status = EINVAL;
111         return -1;
112     }
113
114 send_grp:
115     struct proc_info *pos, *n;
116     llist_for_each(pos, n, &proc->grp_member, grp_member)
117     {
118         struct sighail* sh = &pos->sigctx;
119         sigset_add(sh->sig_pending, signum);
120         sh->signals[signum].sender = sender_pid;
121     }
122
123 send_single:
124     if (proc_terminated(proc)) {
125         __current->k_status = EINVAL;
126         return -1;
127     }
128
129     sigset_add(proc->sigctx.sig_pending, signum);
130     proc->sigctx.signals[signum].sender = sender_pid;
131
132     return 0;
133 }
134
135 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
136 {
137     __current->intr_ctx = sig_ctx->saved_ictx;
138
139     struct sigact* current = __current->sigctx.inprogress;
140     if (current) {
141         __current->sigctx.inprogress = current->prev;
142         current->prev = NULL;
143     } else {
144         __current->sigctx.inprogress = NULL;
145     }
146
147     if (proc_terminated(__current)) {
148         __current->exit_code |= PEXITSIG;
149     } else if (sigset_test(CORE, sig_ctx->sig_num)) {
150         signal_terminate(sig_ctx->sig_num);
151     }
152
153     ptr_t ictx = (ptr_t)__current->intr_ctx;
154
155     /*
156         Ensure our restored context is within kernel stack
157
158         This prevent user to forge their own context such that arbitrary code
159        can be executed as supervisor level
160     */
161     if (!within_kstack(ictx)) {
162         signal_terminate(SIGSEGV);
163     }
164
165     schedule();
166
167     // never reach!
168     return 0;
169 }
170
171 __DEFINE_LXSYSCALL3(int,
172                     sigprocmask,
173                     int,
174                     how,
175                     const sigset_t,
176                     *set,
177                     sigset_t,
178                     *oldset)
179 {
180     struct sighail* sh = &__current->sigctx;
181     *oldset = sh->sig_mask;
182
183     if (how == _SIG_BLOCK) {
184         sigset_union(sh->sig_mask, *set);
185     } else if (how == _SIG_UNBLOCK) {
186         sigset_intersect(sh->sig_mask, ~(*set));
187     } else if (how == _SIG_SETMASK) {
188         sh->sig_mask = *set;
189     } else {
190         return 0;
191     }
192
193     sigset_intersect(sh->sig_mask, ~UNMASKABLE);
194     return 1;
195 }
196
197 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
198 {
199     if (signum <= 0 || signum >= _SIG_NUM) {
200         return -1;
201     }
202
203     if (sigset_test(UNMASKABLE, signum)) {
204         return -1;
205     }
206
207     struct sigact* sa = &__current->sigctx.signals[signum];
208
209     sa->sa_actor = (void*)action->sa_sigaction;
210     sa->sa_handler = (void*)action->sa_handler;
211     sigset_union(sa->sa_mask, sigset(signum));
212
213     return 0;
214 }
215
216 __DEFINE_LXSYSCALL(int, pause)
217 {
218     pause_current();
219     sched_yieldk();
220
221     __current->k_status = EINTR;
222     return -1;
223 }
224
225 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
226 {
227     return signal_send(pid, signum);
228 }
229
230 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
231 {
232     *sigset = __current->sigctx.sig_pending;
233     return 0;
234 }
235
236 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
237 {
238     sigset_t tmp = __current->sigctx.sig_mask;
239     __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
240
241     pause_current();
242     sched_yieldk();
243
244     __current->sigctx.sig_mask = tmp;
245     return -1;
246 }