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