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>
9 #include <klibc/string.h>
11 #include <sys/mm/mempart.h>
15 extern struct scheduler sched_ctx; /* kernel/sched.c */
17 #define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM))
18 #define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
19 #define CORE (sigset(SIGSEGV))
20 #define within_kstack(addr) \
21 (KERNEL_STACK <= (addr) && (addr) <= KERNEL_STACK_END)
24 signal_terminate(int errcode)
26 terminate_proc(errcode | PEXITSIG);
29 // Referenced in kernel/asm/x86/interrupt.S
33 if (!__current->sigctx.sig_pending) {
38 struct sighail* psig = &__current->sigctx;
39 struct sigact* prev_working = psig->inprogress;
40 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
42 int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
44 sigset_clear(psig->sig_pending, sig_selected);
46 struct sigact* action = &psig->signals[sig_selected];
48 if (sig_selected == 0) {
53 if (!action->sa_actor) {
54 if (sigset_test(TERMSIG, sig_selected)) {
55 signal_terminate(sig_selected);
62 ptr_t ustack = __current->ustack_top;
64 if ((int)(ustack - USR_STACK) < (int)sizeof(struct proc_sig)) {
69 struct proc_sig* sigframe =
70 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
72 sigframe->sig_num = sig_selected;
73 sigframe->sigact = action->sa_actor;
74 sigframe->sighand = action->sa_handler;
76 sigframe->saved_ictx = __current->intr_ctx;
78 action->prev = prev_working;
79 psig->inprogress = action;
85 proc_clear_signal(struct proc_info* proc)
87 memset(&proc->sigctx, 0, sizeof(proc->sigctx));
91 proc_setsignal(struct proc_info* proc, int signum)
93 sigset_add(proc->sigctx.sig_pending, signum);
94 proc->sigctx.signals[signum].sender = __current->pid;
98 signal_send(pid_t pid, int signum)
100 if (signum < 0 || signum >= _SIG_NUM) {
101 __current->k_status = EINVAL;
105 pid_t sender_pid = __current->pid;
106 struct proc_info* proc;
109 proc = get_process(pid);
114 } else if (pid < -1) {
115 proc = get_process(-pid);
118 // TODO: send to all process.
119 // But I don't want to support it yet.
120 __current->k_status = EINVAL;
125 struct proc_info *pos, *n;
126 llist_for_each(pos, n, &proc->grp_member, grp_member)
128 struct sighail* sh = &pos->sigctx;
129 sigset_add(sh->sig_pending, signum);
130 sh->signals[signum].sender = sender_pid;
134 if (proc_terminated(proc)) {
135 __current->k_status = EINVAL;
139 sigset_add(proc->sigctx.sig_pending, signum);
140 proc->sigctx.signals[signum].sender = sender_pid;
145 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
147 __current->intr_ctx = sig_ctx->saved_ictx;
149 struct sigact* current = __current->sigctx.inprogress;
151 __current->sigctx.inprogress = current->prev;
152 current->prev = NULL;
154 __current->sigctx.inprogress = NULL;
157 if (proc_terminated(__current)) {
158 __current->exit_code |= PEXITSIG;
159 } else if (sigset_test(CORE, sig_ctx->sig_num)) {
160 signal_terminate(sig_ctx->sig_num);
163 ptr_t ictx = (ptr_t)__current->intr_ctx;
166 Ensure our restored context is within kernel stack
168 This prevent user to forge their own context such that arbitrary code
169 can be executed as supervisor level
171 if (!within_kstack(ictx)) {
172 signal_terminate(SIGSEGV);
181 __DEFINE_LXSYSCALL3(int,
190 struct sighail* sh = &__current->sigctx;
191 *oldset = sh->sig_mask;
193 if (how == _SIG_BLOCK) {
194 sigset_union(sh->sig_mask, *set);
195 } else if (how == _SIG_UNBLOCK) {
196 sigset_intersect(sh->sig_mask, ~(*set));
197 } else if (how == _SIG_SETMASK) {
203 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
207 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
209 if (signum <= 0 || signum >= _SIG_NUM) {
213 if (sigset_test(UNMASKABLE, signum)) {
217 struct sigact* sa = &__current->sigctx.signals[signum];
219 sa->sa_actor = (void*)action->sa_sigaction;
220 sa->sa_handler = (void*)action->sa_handler;
221 sigset_union(sa->sa_mask, sigset(signum));
226 __DEFINE_LXSYSCALL(int, pause)
231 __current->k_status = EINTR;
235 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
237 return signal_send(pid, signum);
240 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
242 *sigset = __current->sigctx.sig_pending;
246 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
248 sigset_t tmp = __current->sigctx.sig_mask;
249 __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
254 __current->sigctx.sig_mask = tmp;