This source file includes following definitions.
- sys_sgetmask
- sys_ssetmask
- sys_sigpending
- sys_sigsuspend
- check_pending
- sys_signal
- sys_sigaction
- sys_sigreturn
- setup_frame
- do_signal
1
2
3
4
5
6
7 #include <linux/sched.h>
8 #include <linux/kernel.h>
9 #include <linux/signal.h>
10 #include <linux/errno.h>
11 #include <linux/wait.h>
12 #include <linux/ptrace.h>
13 #include <linux/unistd.h>
14
15 #include <asm/segment.h>
16
17 #define _S(nr) (1<<((nr)-1))
18
19 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
20
21 extern int core_dump(long signr,struct pt_regs * regs);
22 int do_signal(unsigned long oldmask, struct pt_regs * regs);
23
24 int sys_sgetmask(void)
25 {
26 return current->blocked;
27 }
28
29 int sys_ssetmask(int newmask)
30 {
31 int old=current->blocked;
32
33 current->blocked = newmask & _BLOCKABLE;
34 return old;
35 }
36
37 int sys_sigpending(sigset_t *set)
38 {
39 int error;
40
41 error = verify_area(VERIFY_WRITE, set, 4);
42 if (!error)
43 put_fs_long(current->blocked & current->signal, (unsigned long *)set);
44 return error;
45 }
46
47
48
49
50 int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
51 {
52 unsigned long mask;
53 struct pt_regs * regs = (struct pt_regs *) &restart;
54
55 mask = current->blocked;
56 current->blocked = set & _BLOCKABLE;
57 regs->eax = -EINTR;
58 while (1) {
59 current->state = TASK_INTERRUPTIBLE;
60 schedule();
61 if (do_signal(mask,regs))
62 return -EINTR;
63 }
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 static void check_pending(int signum)
82 {
83 struct sigaction *p;
84
85 p = signum - 1 + current->sigaction;
86 if (p->sa_handler == SIG_IGN) {
87 if (signum == SIGCHLD)
88 return;
89 current->signal &= ~_S(signum);
90 return;
91 }
92 if (p->sa_handler == SIG_DFL) {
93 if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
94 return;
95 current->signal &= ~_S(signum);
96 return;
97 }
98 }
99
100 int sys_signal(int signum, unsigned long handler)
101 {
102 struct sigaction tmp;
103
104 if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
105 return -EINVAL;
106 if (handler >= TASK_SIZE)
107 return -EFAULT;
108 tmp.sa_handler = (void (*)(int)) handler;
109 tmp.sa_mask = 0;
110 tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
111 tmp.sa_restorer = NULL;
112 handler = (long) current->sigaction[signum-1].sa_handler;
113 current->sigaction[signum-1] = tmp;
114 check_pending(signum);
115 return handler;
116 }
117
118 int sys_sigaction(int signum, const struct sigaction * action,
119 struct sigaction * oldaction)
120 {
121 struct sigaction new, *p;
122
123 if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
124 return -EINVAL;
125 p = signum - 1 + current->sigaction;
126 if (action) {
127 memcpy_fromfs(&new, action, sizeof(struct sigaction));
128 if (new.sa_flags & SA_NOMASK)
129 new.sa_mask = 0;
130 else {
131 new.sa_mask |= _S(signum);
132 new.sa_mask &= _BLOCKABLE;
133 }
134 if (TASK_SIZE <= (unsigned long) new.sa_handler)
135 return -EFAULT;
136 }
137 if (oldaction) {
138 if (!verify_area(VERIFY_WRITE,oldaction, sizeof(struct sigaction)))
139 memcpy_tofs(oldaction, p, sizeof(struct sigaction));
140 }
141 if (action) {
142 *p = new;
143 check_pending(signum);
144 }
145 return 0;
146 }
147
148 extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
149
150
151
152
153 int sys_sigreturn(unsigned long oldmask, unsigned long eip, unsigned long esp)
154 {
155 struct pt_regs * regs;
156
157 regs = (struct pt_regs *) &oldmask;
158 current->blocked = oldmask & _BLOCKABLE;
159 regs->eip = eip;
160 regs->esp = esp;
161 return 0;
162 }
163
164
165
166
167
168 static void setup_frame(unsigned long ** fp, unsigned long eip,
169 struct pt_regs * regs, int signr,
170 unsigned long sa_handler, unsigned long oldmask)
171 {
172 unsigned long * frame;
173
174 #define __CODE ((unsigned long)(frame+24))
175 #define CODE(x) ((void *) ((x)+__CODE))
176 frame = *fp - 32;
177 verify_area(VERIFY_WRITE,frame,32*4);
178
179 put_fs_long(__CODE,frame);
180 put_fs_long(signr, frame+1);
181 put_fs_long(regs->gs, frame+2);
182 put_fs_long(regs->fs, frame+3);
183 put_fs_long(regs->es, frame+4);
184 put_fs_long(regs->ds, frame+5);
185 put_fs_long(regs->edi, frame+6);
186 put_fs_long(regs->esi, frame+7);
187 put_fs_long(regs->ebp, frame+8);
188 put_fs_long(regs->esp, frame+9);
189 put_fs_long(regs->ebx, frame+10);
190 put_fs_long(regs->edx, frame+11);
191 put_fs_long(regs->ecx, frame+12);
192 put_fs_long(regs->eax, frame+13);
193 put_fs_long(0, frame+14);
194 put_fs_long(0, frame+15);
195 put_fs_long(regs->eip, frame+16);
196 put_fs_long(regs->cs, frame+17);
197 put_fs_long(regs->eflags, frame+18);
198 put_fs_long(regs->esp, frame+19);
199 put_fs_long(regs->ss, frame+20);
200 put_fs_long(0,frame+21);
201
202 put_fs_long(regs->eflags, frame+22);
203 put_fs_long(eip, frame+23);
204
205 put_fs_long(0x0000b858, CODE(0));
206 put_fs_long(0x00bb0000, CODE(4));
207 put_fs_long(0xcd000000, CODE(8));
208 put_fs_long(0x0fa90f80, CODE(12));
209 put_fs_long(0x611f07a1, CODE(16));
210 put_fs_long(0x20c48390, CODE(20));
211 put_fs_long(0x0020c29d, CODE(24));
212 put_fs_long(__NR_ssetmask, CODE(2));
213 put_fs_long(oldmask, CODE(7));
214 *fp = frame;
215 #undef __CODE
216 #undef CODE
217 }
218
219
220
221
222
223
224
225
226
227
228 int do_signal(unsigned long oldmask, struct pt_regs * regs)
229 {
230 unsigned long mask = ~current->blocked;
231 unsigned long handler_signal = 0;
232 unsigned long *frame = NULL;
233 unsigned long eip = 0;
234 unsigned long signr;
235 unsigned long sa_handler;
236 struct sigaction * sa;
237
238 while ((signr = current->signal & mask)) {
239 __asm__("bsf %2,%1\n\t"
240 "btrl %1,%0"
241 :"=m" (current->signal),"=r" (signr)
242 :"1" (signr));
243 sa = current->sigaction + signr;
244 signr++;
245 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
246 current->exit_code = signr;
247 current->state = TASK_STOPPED;
248 notify_parent(current);
249 schedule();
250 if (!(signr = current->exit_code))
251 continue;
252 current->exit_code = 0;
253 if (signr == SIGSTOP)
254 continue;
255 if (_S(signr) & current->blocked) {
256 current->signal |= _S(signr);
257 continue;
258 }
259 sa = current->sigaction + signr - 1;
260 }
261 if (sa->sa_handler == SIG_IGN) {
262 if (signr != SIGCHLD)
263 continue;
264
265 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
266 ;
267 continue;
268 }
269 if (sa->sa_handler == SIG_DFL) {
270 if (current->pid == 1)
271 continue;
272 switch (signr) {
273 case SIGCONT: case SIGCHLD: case SIGWINCH:
274 continue;
275
276 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
277 current->state = TASK_STOPPED;
278 current->exit_code = signr;
279 if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
280 SA_NOCLDSTOP))
281 notify_parent(current);
282 schedule();
283 continue;
284
285 case SIGQUIT: case SIGILL: case SIGTRAP:
286 case SIGIOT: case SIGFPE: case SIGSEGV:
287 if (core_dump(signr,regs))
288 signr |= 0x80;
289
290 default:
291 current->signal |= _S(signr & 0x7f);
292 do_exit(signr);
293 }
294 }
295
296
297
298 if (regs->orig_eax >= 0) {
299 if (regs->eax == -ERESTARTNOHAND ||
300 (regs->eax == -ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
301 regs->eax = -EINTR;
302 }
303 handler_signal |= 1 << (signr-1);
304 mask &= ~sa->sa_mask;
305 }
306 if (regs->orig_eax >= 0 &&
307 (regs->eax == -ERESTARTNOHAND ||
308 regs->eax == -ERESTARTSYS ||
309 regs->eax == -ERESTARTNOINTR)) {
310 regs->eax = regs->orig_eax;
311 regs->eip -= 2;
312 }
313 if (!handler_signal)
314 return 0;
315 eip = regs->eip;
316 frame = (unsigned long *) regs->esp;
317 signr = 1;
318 sa = current->sigaction;
319 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
320 if (mask > handler_signal)
321 break;
322 if (!(mask & handler_signal))
323 continue;
324 sa_handler = (unsigned long) sa->sa_handler;
325 if (sa->sa_flags & SA_ONESHOT)
326 sa->sa_handler = NULL;
327
328 __asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler));
329 setup_frame(&frame,eip,regs,signr,sa_handler,oldmask);
330 eip = sa_handler;
331 current->blocked |= sa->sa_mask;
332 oldmask |= sa->sa_mask;
333 }
334 regs->esp = (unsigned long) frame;
335 regs->eip = eip;
336 return 1;
337 }