This source file includes following definitions.
- _sigpause_common
- sys_sigpause
- sys_sigsuspend
- do_sigreturn
- do_magic_sparc_stuff
- setup_frame
- do_signal
- sys_sigstack
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 #include <linux/mm.h>
15
16 #include <asm/segment.h>
17 #include <asm/bitops.h>
18 #include <asm/ptrace.h>
19
20 #define _S(nr) (1<<((nr)-1))
21
22 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
23
24 asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
25 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
26
27
28
29
30
31 asmlinkage inline int _sigpause_common(unsigned int set, struct pt_regs *regs)
32 {
33 unsigned long mask;
34
35 mask = current->blocked;
36 current->blocked = set & _BLOCKABLE;
37
38
39
40
41
42 regs->pc += 4;
43 regs->npc += 4;
44
45 while (1) {
46 current->state = TASK_INTERRUPTIBLE;
47 schedule();
48 if (do_signal(mask, regs)) {
49
50
51
52
53 regs->pc -= 4;
54 regs->npc -= 4;
55 return -EINTR;
56 }
57 }
58 }
59
60 asmlinkage int sys_sigpause(unsigned int set)
61 {
62 struct pt_regs *regs;
63 unsigned long fp;
64
65 __asm__ __volatile__("mov %%fp, %0\n\t" :
66 "=r" (fp));
67 regs = ((struct pt_regs *) (fp + STACKFRAME_SZ));
68 return _sigpause_common(set, regs);
69 }
70
71 asmlinkage int sys_sigsuspend(unsigned int *sigmaskp)
72 {
73 struct pt_regs *regs;
74 unsigned long fp;
75 unsigned int set;
76
77 __asm__ __volatile__("mov %%fp, %0\n\t" :
78 "=r" (fp));
79 regs = ((struct pt_regs *) (fp + STACKFRAME_SZ));
80 if(verify_area(VERIFY_READ, sigmaskp, sizeof(unsigned int)))
81 return -EFAULT;
82 set = *sigmaskp;
83 return _sigpause_common(set, regs);
84 }
85
86 extern unsigned long nwindows;
87
88 asmlinkage void do_sigreturn(struct pt_regs *regs)
89 {
90 struct sigcontext_struct *scptr =
91 (struct sigcontext_struct *) regs->u_regs[UREG_I0];
92
93
94 flush_user_windows();
95
96
97 if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext_struct)) ||
98 ((((unsigned long) scptr)) & 0x3))
99 do_exit(SIGSEGV);
100
101 if((scptr->sigc_pc | scptr->sigc_npc) & 3)
102 return;
103
104 current->blocked = scptr->sigc_mask & _BLOCKABLE;
105 current->tss.sstk_info.cur_status = (scptr->sigc_onstack & 0x1);
106 regs->pc = scptr->sigc_pc;
107 regs->npc = scptr->sigc_npc;
108 regs->u_regs[UREG_FP] = scptr->sigc_sp;
109 regs->u_regs[UREG_I0] = scptr->sigc_o0;
110 regs->u_regs[UREG_G1] = scptr->sigc_g1;
111
112
113 regs->psr &= (~PSR_ICC);
114 regs->psr |= (scptr->sigc_psr & PSR_ICC);
115 }
116
117
118
119
120
121
122
123
124 static inline void
125 do_magic_sparc_stuff(void)
126 {
127 unsigned long sp;
128 int this_win;
129
130 flush_user_windows();
131 this_win = (current->tss.w_saved - 1);
132 while(this_win >= 0) {
133 sp = current->tss.rwbuf_stkptrs[this_win];
134 if(!(sp & 7) && !verify_area(VERIFY_WRITE, (char *)sp,
135 sizeof(struct reg_window))) {
136 memcpy((char *)sp,
137 (char *)¤t->tss.reg_window[this_win],
138 sizeof(struct reg_window));
139 current->tss.w_saved--;
140 memcpy((char *)¤t->tss.reg_window[this_win],
141 (char *)¤t->tss.reg_window[this_win+1],
142 (sizeof(struct reg_window) *
143 (current->tss.w_saved-this_win)));
144 }
145 this_win -= 1;
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 struct signal_sframe {
163 struct reg_window sig_window;
164 int sig_num;
165 int sig_code;
166 struct sigcontext_struct *sig_scptr;
167 int sig_address;
168 struct sigcontext_struct sig_context;
169 };
170
171 #define SF_ALIGNEDSZ (((sizeof(struct signal_sframe) + 7) & (~7)))
172
173 static inline void
174 setup_frame(struct sigaction *sa, struct sigcontext_struct **fp,
175 unsigned long pc, struct pt_regs *regs, int signr,
176 unsigned long oldmask)
177 {
178 struct signal_sframe *sframep;
179 struct sigcontext_struct *sc;
180 int window = 0;
181 int old_status = current->tss.sstk_info.cur_status;
182
183 sframep = (struct signal_sframe *) *fp;
184 sframep = (struct signal_sframe *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
185 sc = &sframep->sig_context;
186 if(verify_area(VERIFY_WRITE, sframep, sizeof(*sframep)) ||
187 (((unsigned long) sframep) & 7) ||
188 (((unsigned long) sframep) >= KERNBASE)) {
189 printk("%s [%d]: User has trashed signal stack\n",
190 current->comm, current->pid);
191 printk("Sigstack ptr %p handler at pc<%08lx> for sig<%d>\n",
192 sframep, pc, signr);
193 show_regs(regs);
194
195
196
197 current->sig->action[SIGILL-1].sa_handler = SIG_DFL;
198 current->blocked &= ~(1<<(SIGILL-1));
199 send_sig(SIGILL,current,1);
200 return;
201 }
202 *fp = (struct sigcontext_struct *) sframep;
203 do_magic_sparc_stuff();
204
205 sc->sigc_onstack = old_status;
206 sc->sigc_mask = oldmask;
207 sc->sigc_sp = regs->u_regs[UREG_FP];
208 sc->sigc_pc = regs->pc;
209 sc->sigc_npc = regs->npc;
210 sc->sigc_psr = regs->psr;
211 sc->sigc_g1 = regs->u_regs[UREG_G1];
212 sc->sigc_o0 = regs->u_regs[UREG_I0];
213 sc->sigc_oswins = current->tss.w_saved;
214 if(current->tss.w_saved)
215 for(window = 0; window < current->tss.w_saved; window++) {
216 sc->sigc_spbuf[window] =
217 (char *)current->tss.rwbuf_stkptrs[window];
218 memcpy(&sc->sigc_wbuf[window],
219 ¤t->tss.reg_window[window],
220 sizeof(struct reg_window));
221 }
222 else
223
224
225
226
227
228
229 memcpy(sframep, (char *)regs->u_regs[UREG_FP],
230 sizeof(struct reg_window));
231
232 current->tss.w_saved = 0;
233 sframep->sig_num = signr;
234 if(signr == SIGSEGV ||
235 signr == SIGILL ||
236 signr == SIGFPE ||
237 signr == SIGBUS ||
238 signr == SIGEMT) {
239 sframep->sig_code = current->tss.sig_desc;
240 sframep->sig_address = current->tss.sig_address;
241 } else {
242 sframep->sig_code = 0;
243 sframep->sig_address = 0;
244 }
245 sframep->sig_scptr = sc;
246 }
247
248
249
250
251
252
253
254
255
256
257
258 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
259 {
260 unsigned long mask = ~current->blocked;
261 unsigned long handler_signal = 0;
262 struct sigcontext_struct *frame = NULL;
263 unsigned long pc = 0;
264 unsigned long signr;
265 struct sigaction *sa;
266
267 while ((signr = current->signal & mask) != 0) {
268 signr = ffz(~signr);
269 clear_bit(signr, ¤t->signal);
270 sa = current->sig->action + signr;
271 signr++;
272 if((current->flags & PF_PTRACED) && signr != SIGKILL) {
273 current->exit_code = signr;
274 current->state = TASK_STOPPED;
275 notify_parent(current);
276 schedule();
277 if(!(signr = current->exit_code))
278 continue;
279 current->exit_code = 0;
280 if(signr == SIGSTOP)
281 continue;
282 if(_S(signr) & current->blocked) {
283 current->signal |= _S(signr);
284 continue;
285 }
286 sa = current->sig->action + signr - 1;
287 }
288 if(sa->sa_handler == SIG_IGN) {
289 if(signr != SIGCHLD)
290 continue;
291 while(sys_waitpid(-1,NULL,WNOHANG) > 0);
292 continue;
293 }
294 if(sa->sa_handler == SIG_DFL) {
295 if(current->pid == 1)
296 continue;
297 switch(signr) {
298 case SIGCONT: case SIGCHLD: case SIGWINCH:
299 continue;
300
301 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
302 if(current->flags & PF_PTRACED)
303 continue;
304 current->state = TASK_STOPPED;
305 current->exit_code = signr;
306 if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
307 SA_NOCLDSTOP))
308 notify_parent(current);
309 schedule();
310 continue;
311
312 case SIGQUIT: case SIGILL: case SIGTRAP:
313 case SIGABRT: case SIGFPE: case SIGSEGV:
314 if(current->binfmt && current->binfmt->core_dump) {
315 if(current->binfmt->core_dump(signr, regs))
316 signr |= 0x80;
317 }
318
319 default:
320 current->signal |= _S(signr & 0x7f);
321 do_exit(signr);
322 }
323 }
324
325 handler_signal |= 1 << (signr - 1);
326 mask &= ~sa->sa_mask;
327 }
328 if(!handler_signal)
329 return 0;
330 pc = regs->pc;
331 frame = (struct sigcontext_struct *) regs->u_regs[UREG_FP];
332 signr = 1;
333 sa = current->sig->action;
334 for(mask = 1; mask; sa++, signr++, mask += mask) {
335 if(mask > handler_signal)
336 break;
337 if(!(mask & handler_signal))
338 continue;
339 setup_frame(sa, &frame, pc, regs, signr, oldmask);
340 pc = (unsigned long) sa->sa_handler;
341 if(sa->sa_flags & SA_ONESHOT)
342 sa->sa_handler = NULL;
343 current->blocked |= sa->sa_mask;
344 oldmask |= sa->sa_mask;
345 }
346 regs->u_regs[UREG_FP] = (unsigned long) frame;
347 regs->npc = (regs->pc = pc) + 4;
348 return 1;
349 }
350
351 asmlinkage int
352 sys_sigstack(struct sigstack *ssptr, struct sigstack *ossptr)
353 {
354
355 if(ossptr) {
356 if(verify_area(VERIFY_WRITE, ossptr, sizeof(struct sigstack)))
357 return -EFAULT;
358 memcpy(ossptr, ¤t->tss.sstk_info, sizeof(struct sigstack));
359 }
360
361
362 if(ssptr) {
363 if(verify_area(VERIFY_READ, ssptr, sizeof(struct sigstack)))
364 return -EFAULT;
365 memcpy(¤t->tss.sstk_info, ssptr, sizeof(struct sigstack));
366 }
367 return 0;
368 }