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