This source file includes following definitions.
- sys_sigsuspend
- sys_sigreturn
- setup_frame
- handle_signal
- do_signal
1
2
3
4
5
6
7 #include <linux/sched.h>
8 #include <linux/mm.h>
9 #include <linux/kernel.h>
10 #include <linux/signal.h>
11 #include <linux/errno.h>
12 #include <linux/wait.h>
13 #include <linux/ptrace.h>
14 #include <linux/unistd.h>
15
16 #include <asm/segment.h>
17
18 #define _S(nr) (1<<((nr)-1))
19
20 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
21
22 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
23 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
24
25
26
27
28 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
29 {
30 unsigned long mask;
31 struct pt_regs * regs = (struct pt_regs *) &restart;
32
33 mask = current->blocked;
34 current->blocked = set & _BLOCKABLE;
35 regs->eax = -EINTR;
36 while (1) {
37 current->state = TASK_INTERRUPTIBLE;
38 schedule();
39 if (do_signal(mask,regs))
40 return -EINTR;
41 }
42 }
43
44
45
46
47 asmlinkage int sys_sigreturn(unsigned long __unused)
48 {
49 #define COPY(x) regs->x = context.x
50 #define COPY_SEG(x) \
51 if ((context.x & 0xfffc) && (context.x & 3) != 3) goto badframe; COPY(x);
52 #define COPY_SEG_STRICT(x) \
53 if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
54 struct sigcontext_struct context;
55 struct pt_regs * regs;
56
57 regs = (struct pt_regs *) &__unused;
58 if (verify_area(VERIFY_READ, (void *) regs->esp, sizeof(context)))
59 goto badframe;
60 memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
61 current->blocked = context.oldmask & _BLOCKABLE;
62 COPY_SEG(ds);
63 COPY_SEG(es);
64 COPY_SEG(fs);
65 COPY_SEG(gs);
66 COPY_SEG_STRICT(ss);
67 COPY_SEG_STRICT(cs);
68 COPY(eip);
69 COPY(ecx); COPY(edx);
70 COPY(ebx);
71 COPY(esp); COPY(ebp);
72 COPY(edi); COPY(esi);
73 regs->eflags &= ~0x40DD5;
74 regs->eflags |= context.eflags & 0x40DD5;
75 regs->orig_eax = -1;
76 return context.eax;
77 badframe:
78 do_exit(SIGSEGV);
79 }
80
81
82
83
84
85 static void setup_frame(struct sigaction * sa,
86 struct pt_regs * regs, int signr,
87 unsigned long oldmask)
88 {
89 unsigned long * frame;
90
91 frame = (unsigned long *) regs->esp;
92 if (regs->ss != USER_DS && sa->sa_restorer)
93 frame = (unsigned long *) sa->sa_restorer;
94 frame -= 32;
95 if (verify_area(VERIFY_WRITE,frame,32*4))
96 do_exit(SIGSEGV);
97
98
99 #define __CODE ((unsigned long)(frame+24))
100 #define CODE(x) ((unsigned long *) ((x)+__CODE))
101 put_user(__CODE,frame);
102 if (current->exec_domain && current->exec_domain->signal_invmap)
103 put_user(current->exec_domain->signal_invmap[signr], frame+1);
104 else
105 put_user(signr, frame+1);
106 put_user(regs->gs, frame+2);
107 put_user(regs->fs, frame+3);
108 put_user(regs->es, frame+4);
109 put_user(regs->ds, frame+5);
110 put_user(regs->edi, frame+6);
111 put_user(regs->esi, frame+7);
112 put_user(regs->ebp, frame+8);
113 put_user(regs->esp, frame+9);
114 put_user(regs->ebx, frame+10);
115 put_user(regs->edx, frame+11);
116 put_user(regs->ecx, frame+12);
117 put_user(regs->eax, frame+13);
118 put_user(current->tss.trap_no, frame+14);
119 put_user(current->tss.error_code, frame+15);
120 put_user(regs->eip, frame+16);
121 put_user(regs->cs, frame+17);
122 put_user(regs->eflags, frame+18);
123 put_user(regs->esp, frame+19);
124 put_user(regs->ss, frame+20);
125 put_user(NULL,frame+21);
126
127 put_user(oldmask, frame+22);
128 put_user(current->tss.cr2, frame+23);
129
130 put_user(0x0000b858, CODE(0));
131 put_user(0x80cd0000, CODE(4));
132 put_user(__NR_sigreturn, CODE(2));
133 #undef __CODE
134 #undef CODE
135
136
137 regs->esp = (unsigned long) frame;
138 regs->eip = (unsigned long) sa->sa_handler;
139 regs->cs = USER_CS; regs->ss = USER_DS;
140 regs->ds = USER_DS; regs->es = USER_DS;
141 regs->gs = USER_DS; regs->fs = USER_DS;
142 regs->eflags &= ~TF_MASK;
143 }
144
145
146
147
148 static void handle_signal(unsigned long signr, struct sigaction *sa,
149 unsigned long oldmask, struct pt_regs * regs)
150 {
151
152 if (regs->orig_eax >= 0) {
153
154 switch (regs->eax) {
155 case -ERESTARTNOHAND:
156 regs->eax = -EINTR;
157 break;
158
159 case -ERESTARTSYS:
160 if (!(sa->sa_flags & SA_RESTART)) {
161 regs->eax = -EINTR;
162 break;
163 }
164
165 case -ERESTARTNOINTR:
166 regs->eax = regs->orig_eax;
167 regs->eip -= 2;
168 }
169 }
170
171
172 setup_frame(sa, regs, signr, oldmask);
173
174 if (sa->sa_flags & SA_ONESHOT)
175 sa->sa_handler = NULL;
176 current->blocked |= sa->sa_mask;
177 }
178
179
180
181
182
183
184
185
186
187
188 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
189 {
190 unsigned long mask = ~current->blocked;
191 unsigned long signr;
192 struct sigaction * sa;
193
194 while ((signr = current->signal & mask)) {
195
196
197
198
199
200 struct task_struct *t=current;
201 __asm__("bsf %3,%1\n\t"
202 "btrl %1,%0"
203 :"=m" (t->signal),"=r" (signr)
204 :"0" (t->signal), "1" (signr));
205 sa = current->sig->action + signr;
206 signr++;
207 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
208 current->exit_code = signr;
209 current->state = TASK_STOPPED;
210 notify_parent(current);
211 schedule();
212 if (!(signr = current->exit_code))
213 continue;
214 current->exit_code = 0;
215 if (signr == SIGSTOP)
216 continue;
217 if (_S(signr) & current->blocked) {
218 current->signal |= _S(signr);
219 continue;
220 }
221 sa = current->sig->action + signr - 1;
222 }
223 if (sa->sa_handler == SIG_IGN) {
224 if (signr != SIGCHLD)
225 continue;
226
227 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
228 ;
229 continue;
230 }
231 if (sa->sa_handler == SIG_DFL) {
232 if (current->pid == 1)
233 continue;
234 switch (signr) {
235 case SIGCONT: case SIGCHLD: case SIGWINCH:
236 continue;
237
238 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
239 if (current->flags & PF_PTRACED)
240 continue;
241 current->state = TASK_STOPPED;
242 current->exit_code = signr;
243 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
244 SA_NOCLDSTOP))
245 notify_parent(current);
246 schedule();
247 continue;
248
249 case SIGQUIT: case SIGILL: case SIGTRAP:
250 case SIGABRT: case SIGFPE: case SIGSEGV:
251 if (current->binfmt && current->binfmt->core_dump) {
252 if (current->binfmt->core_dump(signr, regs))
253 signr |= 0x80;
254 }
255
256 default:
257 current->signal |= _S(signr & 0x7f);
258 current->flags |= PF_SIGNALED;
259 do_exit(signr);
260 }
261 }
262 handle_signal(signr, sa, oldmask, regs);
263 return 1;
264 }
265
266
267 if (regs->orig_eax >= 0) {
268
269 if (regs->eax == -ERESTARTNOHAND ||
270 regs->eax == -ERESTARTSYS ||
271 regs->eax == -ERESTARTNOINTR) {
272 regs->eax = regs->orig_eax;
273 regs->eip -= 2;
274 }
275 }
276 return 0;
277 }