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