This source file includes following definitions.
- generate
- send_sig
- notify_parent
- release
- bad_task_ptr
- audit_ptree
- session_of_pgrp
- kill_pg
- kill_sl
- kill_proc
- sys_kill
- is_orphaned_pgrp
- has_stopped_jobs
- forget_original_parent
- do_exit
- sys_exit
- sys_wait4
- sys_waitpid
1
2
3
4
5
6
7 #define DEBUG_PROC_TREE
8
9 #include <linux/wait.h>
10 #include <linux/errno.h>
11 #include <linux/signal.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/resource.h>
15 #include <linux/mm.h>
16 #include <linux/tty.h>
17
18 #include <asm/segment.h>
19 extern void shm_exit (void);
20 extern void sem_exit (void);
21
22 int getrusage(struct task_struct *, int, struct rusage *);
23
24 static int generate(unsigned long sig, struct task_struct * p)
25 {
26 unsigned long mask = 1 << (sig-1);
27 struct sigaction * sa = sig + p->sigaction - 1;
28
29
30 if (p->flags & PF_PTRACED) {
31 p->signal |= mask;
32 return 1;
33 }
34
35 if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
36 return 0;
37
38 if ((sa->sa_handler == SIG_DFL) &&
39 (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))
40 return 0;
41 p->signal |= mask;
42 return 1;
43 }
44
45 int send_sig(unsigned long sig,struct task_struct * p,int priv)
46 {
47 if (!p || sig > 32)
48 return -EINVAL;
49 if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
50 (current->euid != p->euid) && (current->uid != p->uid) && !suser())
51 return -EPERM;
52 if (!sig)
53 return 0;
54 if ((sig == SIGKILL) || (sig == SIGCONT)) {
55 if (p->state == TASK_STOPPED)
56 p->state = TASK_RUNNING;
57 p->exit_code = 0;
58 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
59 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
60 }
61
62 if ((sig >= SIGSTOP) && (sig <= SIGTTOU))
63 p->signal &= ~(1<<(SIGCONT-1));
64
65 generate(sig,p);
66 return 0;
67 }
68
69 void notify_parent(struct task_struct * tsk)
70 {
71 if (tsk->p_pptr == task[1])
72 tsk->exit_signal = SIGCHLD;
73 send_sig(tsk->exit_signal, tsk->p_pptr, 1);
74 wake_up_interruptible(&tsk->p_pptr->wait_chldexit);
75 }
76
77 void release(struct task_struct * p)
78 {
79 int i;
80
81 if (!p)
82 return;
83 if (p == current) {
84 printk("task releasing itself\n");
85 return;
86 }
87 for (i=1 ; i<NR_TASKS ; i++)
88 if (task[i] == p) {
89 task[i] = NULL;
90 REMOVE_LINKS(p);
91 free_page(p->kernel_stack_page);
92 free_page((long) p);
93 return;
94 }
95 panic("trying to release non-existent task");
96 }
97
98 #ifdef DEBUG_PROC_TREE
99
100
101
102
103 int bad_task_ptr(struct task_struct *p)
104 {
105 int i;
106
107 if (!p)
108 return 0;
109 for (i=0 ; i<NR_TASKS ; i++)
110 if (task[i] == p)
111 return 0;
112 return 1;
113 }
114
115
116
117
118
119
120
121
122
123
124 void audit_ptree(void)
125 {
126 int i;
127
128 for (i=1 ; i<NR_TASKS ; i++) {
129 if (!task[i])
130 continue;
131 if (bad_task_ptr(task[i]->p_pptr))
132 printk("Warning, pid %d's parent link is bad\n",
133 task[i]->pid);
134 if (bad_task_ptr(task[i]->p_cptr))
135 printk("Warning, pid %d's child link is bad\n",
136 task[i]->pid);
137 if (bad_task_ptr(task[i]->p_ysptr))
138 printk("Warning, pid %d's ys link is bad\n",
139 task[i]->pid);
140 if (bad_task_ptr(task[i]->p_osptr))
141 printk("Warning, pid %d's os link is bad\n",
142 task[i]->pid);
143 if (task[i]->p_pptr == task[i])
144 printk("Warning, pid %d parent link points to self\n",
145 task[i]->pid);
146 if (task[i]->p_cptr == task[i])
147 printk("Warning, pid %d child link points to self\n",
148 task[i]->pid);
149 if (task[i]->p_ysptr == task[i])
150 printk("Warning, pid %d ys link points to self\n",
151 task[i]->pid);
152 if (task[i]->p_osptr == task[i])
153 printk("Warning, pid %d os link points to self\n",
154 task[i]->pid);
155 if (task[i]->p_osptr) {
156 if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
157 printk(
158 "Warning, pid %d older sibling %d parent is %d\n",
159 task[i]->pid, task[i]->p_osptr->pid,
160 task[i]->p_osptr->p_pptr->pid);
161 if (task[i]->p_osptr->p_ysptr != task[i])
162 printk(
163 "Warning, pid %d older sibling %d has mismatched ys link\n",
164 task[i]->pid, task[i]->p_osptr->pid);
165 }
166 if (task[i]->p_ysptr) {
167 if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
168 printk(
169 "Warning, pid %d younger sibling %d parent is %d\n",
170 task[i]->pid, task[i]->p_osptr->pid,
171 task[i]->p_osptr->p_pptr->pid);
172 if (task[i]->p_ysptr->p_osptr != task[i])
173 printk(
174 "Warning, pid %d younger sibling %d has mismatched os link\n",
175 task[i]->pid, task[i]->p_ysptr->pid);
176 }
177 if (task[i]->p_cptr) {
178 if (task[i]->p_cptr->p_pptr != task[i])
179 printk(
180 "Warning, pid %d youngest child %d has mismatched parent link\n",
181 task[i]->pid, task[i]->p_cptr->pid);
182 if (task[i]->p_cptr->p_ysptr)
183 printk(
184 "Warning, pid %d youngest child %d has non-NULL ys link\n",
185 task[i]->pid, task[i]->p_cptr->pid);
186 }
187 }
188 }
189 #endif
190
191
192
193
194
195
196 int session_of_pgrp(int pgrp)
197 {
198 struct task_struct *p;
199 int fallback;
200
201 fallback = -1;
202 for_each_task(p) {
203 if (p->session <= 0)
204 continue;
205 if (p->pgrp == pgrp)
206 return p->session;
207 if (p->pid == pgrp)
208 fallback = p->session;
209 }
210 return fallback;
211 }
212
213
214
215
216
217 int kill_pg(int pgrp, int sig, int priv)
218 {
219 struct task_struct *p;
220 int err,retval = -ESRCH;
221 int found = 0;
222
223 if (sig<0 || sig>32 || pgrp<=0)
224 return -EINVAL;
225 for_each_task(p) {
226 if (p->pgrp == pgrp) {
227 if ((err = send_sig(sig,p,priv)) != 0)
228 retval = err;
229 else
230 found++;
231 }
232 }
233 return(found ? 0 : retval);
234 }
235
236
237
238
239
240
241 int kill_sl(int sess, int sig, int priv)
242 {
243 struct task_struct *p;
244 int err,retval = -ESRCH;
245 int found = 0;
246
247 if (sig<0 || sig>32 || sess<=0)
248 return -EINVAL;
249 for_each_task(p) {
250 if (p->session == sess && p->leader) {
251 if ((err = send_sig(sig,p,priv)) != 0)
252 retval = err;
253 else
254 found++;
255 }
256 }
257 return(found ? 0 : retval);
258 }
259
260 int kill_proc(int pid, int sig, int priv)
261 {
262 struct task_struct *p;
263
264 if (sig<0 || sig>32)
265 return -EINVAL;
266 for_each_task(p) {
267 if (p && p->pid == pid)
268 return send_sig(sig,p,priv);
269 }
270 return(-ESRCH);
271 }
272
273
274
275
276
277 asmlinkage int sys_kill(int pid,int sig)
278 {
279 int err, retval = 0, count = 0;
280
281 if (!pid)
282 return(kill_pg(current->pgrp,sig,0));
283 if (pid == -1) {
284 struct task_struct * p;
285 for_each_task(p) {
286 if (p->pid > 1 && p != current) {
287 ++count;
288 if ((err = send_sig(sig,p,0)) != -EPERM)
289 retval = err;
290 }
291 }
292 return(count ? retval : -ESRCH);
293 }
294 if (pid < 0)
295 return(kill_pg(-pid,sig,0));
296
297 return(kill_proc(pid,sig,0));
298 }
299
300
301
302
303
304
305
306
307
308 int is_orphaned_pgrp(int pgrp)
309 {
310 struct task_struct *p;
311
312 for_each_task(p) {
313 if ((p->pgrp != pgrp) ||
314 (p->state == TASK_ZOMBIE) ||
315 (p->p_pptr->pid == 1))
316 continue;
317 if ((p->p_pptr->pgrp != pgrp) &&
318 (p->p_pptr->session == p->session))
319 return 0;
320 }
321 return(1);
322 }
323
324 static int has_stopped_jobs(int pgrp)
325 {
326 struct task_struct * p;
327
328 for_each_task(p) {
329 if (p->pgrp != pgrp)
330 continue;
331 if (p->state == TASK_STOPPED)
332 return(1);
333 }
334 return(0);
335 }
336
337 static void forget_original_parent(struct task_struct * father)
338 {
339 struct task_struct * p;
340
341 for_each_task(p) {
342 if (p->p_opptr == father)
343 if (task[1])
344 p->p_opptr = task[1];
345 else
346 p->p_opptr = task[0];
347 }
348 }
349
350 volatile void do_exit(long code)
351 {
352 struct task_struct *p;
353 int i;
354
355 fake_volatile:
356 if (current->semun)
357 sem_exit();
358 if (current->shm)
359 shm_exit();
360 free_page_tables(current);
361 for (i=0 ; i<NR_OPEN ; i++)
362 if (current->filp[i])
363 sys_close(i);
364 forget_original_parent(current);
365 iput(current->pwd);
366 current->pwd = NULL;
367 iput(current->root);
368 current->root = NULL;
369 iput(current->executable);
370 current->executable = NULL;
371
372
373 {
374 struct vm_area_struct * mpnt, *mpnt1;
375 mpnt = current->mmap;
376 current->mmap = NULL;
377 while (mpnt) {
378 mpnt1 = mpnt->vm_next;
379 if (mpnt->vm_ops && mpnt->vm_ops->close)
380 mpnt->vm_ops->close(mpnt);
381 kfree(mpnt);
382 mpnt = mpnt1;
383 }
384 }
385
386 if (current->ldt) {
387 free_page((unsigned long) current->ldt);
388 current->ldt = NULL;
389 for (i=1 ; i<NR_TASKS ; i++) {
390 if (task[i] == current) {
391 set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, &default_ldt, 1);
392 load_ldt(i);
393 }
394 }
395 }
396
397 current->state = TASK_ZOMBIE;
398 current->exit_code = code;
399 current->rss = 0;
400
401
402
403
404
405
406
407
408
409 if ((current->p_pptr->pgrp != current->pgrp) &&
410 (current->p_pptr->session == current->session) &&
411 is_orphaned_pgrp(current->pgrp) &&
412 has_stopped_jobs(current->pgrp)) {
413 kill_pg(current->pgrp,SIGHUP,1);
414 kill_pg(current->pgrp,SIGCONT,1);
415 }
416
417 notify_parent(current);
418
419
420
421
422
423
424
425
426
427 while ((p = current->p_cptr) != NULL) {
428 current->p_cptr = p->p_osptr;
429 p->p_ysptr = NULL;
430 p->flags &= ~(PF_PTRACED|PF_TRACESYS);
431 if (task[1])
432 p->p_pptr = task[1];
433 else
434 p->p_pptr = task[0];
435 p->p_osptr = p->p_pptr->p_cptr;
436 p->p_osptr->p_ysptr = p;
437 p->p_pptr->p_cptr = p;
438 if (p->state == TASK_ZOMBIE)
439 notify_parent(p);
440
441
442
443
444
445
446 if ((p->pgrp != current->pgrp) &&
447 (p->session == current->session) &&
448 is_orphaned_pgrp(p->pgrp) &&
449 has_stopped_jobs(p->pgrp)) {
450 kill_pg(p->pgrp,SIGHUP,1);
451 kill_pg(p->pgrp,SIGCONT,1);
452 }
453 }
454 if (current->leader) {
455 struct task_struct *p;
456 struct tty_struct *tty;
457
458 if (current->tty >= 0) {
459 tty = TTY_TABLE(current->tty);
460 if (tty) {
461 if (tty->pgrp > 0)
462 kill_pg(tty->pgrp, SIGHUP, 1);
463 tty->pgrp = -1;
464 tty->session = 0;
465 }
466 }
467 for_each_task(p) {
468 if (p->session == current->session)
469 p->tty = -1;
470 }
471 }
472 if (last_task_used_math == current)
473 last_task_used_math = NULL;
474 #ifdef DEBUG_PROC_TREE
475 audit_ptree();
476 #endif
477 schedule();
478
479
480
481
482
483
484
485
486
487
488
489
490
491 goto fake_volatile;
492 }
493
494 asmlinkage int sys_exit(int error_code)
495 {
496 do_exit((error_code&0xff)<<8);
497 }
498
499 asmlinkage int sys_wait4(pid_t pid,unsigned long * stat_addr, int options, struct rusage * ru)
500 {
501 int flag, retval;
502 struct wait_queue wait = { current, NULL };
503 struct task_struct *p;
504
505 if (stat_addr) {
506 flag = verify_area(VERIFY_WRITE, stat_addr, 4);
507 if (flag)
508 return flag;
509 }
510 add_wait_queue(¤t->wait_chldexit,&wait);
511 repeat:
512 flag=0;
513 for (p = current->p_cptr ; p ; p = p->p_osptr) {
514 if (pid>0) {
515 if (p->pid != pid)
516 continue;
517 } else if (!pid) {
518 if (p->pgrp != current->pgrp)
519 continue;
520 } else if (pid != -1) {
521 if (p->pgrp != -pid)
522 continue;
523 }
524
525 if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
526 continue;
527 flag = 1;
528 switch (p->state) {
529 case TASK_STOPPED:
530 if (!p->exit_code)
531 continue;
532 if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
533 continue;
534 if (stat_addr)
535 put_fs_long((p->exit_code << 8) | 0x7f,
536 stat_addr);
537 p->exit_code = 0;
538 if (ru != NULL)
539 getrusage(p, RUSAGE_BOTH, ru);
540 retval = p->pid;
541 goto end_wait4;
542 case TASK_ZOMBIE:
543 current->cutime += p->utime + p->cutime;
544 current->cstime += p->stime + p->cstime;
545 current->cmin_flt += p->min_flt + p->cmin_flt;
546 current->cmaj_flt += p->maj_flt + p->cmaj_flt;
547 if (ru != NULL)
548 getrusage(p, RUSAGE_BOTH, ru);
549 flag = p->pid;
550 if (stat_addr)
551 put_fs_long(p->exit_code, stat_addr);
552 if (p->p_opptr != p->p_pptr) {
553 REMOVE_LINKS(p);
554 p->p_pptr = p->p_opptr;
555 SET_LINKS(p);
556 notify_parent(p);
557 } else
558 release(p);
559 #ifdef DEBUG_PROC_TREE
560 audit_ptree();
561 #endif
562 retval = flag;
563 goto end_wait4;
564 default:
565 continue;
566 }
567 }
568 if (flag) {
569 retval = 0;
570 if (options & WNOHANG)
571 goto end_wait4;
572 current->state=TASK_INTERRUPTIBLE;
573 schedule();
574 current->signal &= ~(1<<(SIGCHLD-1));
575 retval = -ERESTARTSYS;
576 if (current->signal & ~current->blocked)
577 goto end_wait4;
578 goto repeat;
579 }
580 retval = -ECHILD;
581 end_wait4:
582 remove_wait_queue(¤t->wait_chldexit,&wait);
583 return retval;
584 }
585
586
587
588
589
590 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
591 {
592 return sys_wait4(pid, stat_addr, options, NULL);
593 }