sys/sig.c

04600 #include "../h/param.h" 04601 #include "../h/systm.h" 04602 #include "../h/dir.h" 04603 #include "../h/user.h" 04604 #include "../h/proc.h" 04605 #include "../h/inode.h" 04606 #include "../h/reg.h" 04607 #include "../h/text.h" 04608 #include "../h/seg.h" 04609 04610 /* 04611 * Priority for tracing 04612 */ 04613 #define IPCPRI PZERO 04614 04615 /* 04616 * Tracing variables. 04617 * Used to pass trace command from 04618 * parent to child being traced. 04619 * This data base cannot be 04620 * shared and is locked 04621 * per user. 04622 */ 04623 struct 04624 { 04625 int ip_lock; 04626 int ip_req; 04627 int *ip_addr; 04628 int ip_data; 04629 } ipc; 04630 04631 /* 04632 * Send the specified signal to 04633 * all processes with 'pgrp' as 04634 * process group. 04635 * Called by tty.c for quits and 04636 * interrupts. 04637 */ 04638 signal(pgrp, sig) 04639 register pgrp; 04640 { 04641 register struct proc *p; 04642 04643 if(pgrp == 0) 04644 return; 04645 for(p = &proc[0]; p < &proc[NPROC]; p++) 04646 if(p->p_pgrp == pgrp) 04647 psignal(p, sig); 04648 } 04649 04650 /* 04651 * Send the specified signal to 04652 * the specified process. 04653 */ 04654 psignal(p, sig) 04655 register struct proc *p; 04656 register sig; 04657 { 04658 04659 if((unsigned)sig >= NSIG) 04660 return; 04661 if(sig) 04662 p->p_sig |= 1<<(sig-1); 04663 if(p->p_pri > PUSER) 04664 p->p_pri = PUSER; 04665 if(p->p_stat == SSLEEP && p->p_pri > PZERO) 04666 setrun(p); 04667 } 04668 04669 /* 04670 * Returns true if the current 04671 * process has a signal to process. 04672 * This is asked at least once 04673 * each time a process enters the 04674 * system. 04675 * A signal does not do anything 04676 * directly to a process; it sets 04677 * a flag that asks the process to 04678 * do something to itself. 04679 */ 04680 issig() 04681 { 04682 register n; 04683 register struct proc *p; 04684 04685 p = u.u_procp; 04686 while(p->p_sig) { 04687 n = fsig(p); 04688 if((u.u_signal[n]&1) == 0 || (p->p_flag&STRC)) 04689 return(n); 04690 p->p_sig &= ~(1<<(n-1)); 04691 } 04692 return(0); 04693 } 04694 04695 /* 04696 * Enter the tracing STOP state. 04697 * In this state, the parent is 04698 * informed and the process is able to 04699 * receive commands from the parent. 04700 */ 04701 stop() 04702 { 04703 register struct proc *pp, *cp; 04704 04705 loop: 04706 cp = u.u_procp; 04707 if(cp->p_ppid != 1) 04708 for (pp = &proc[0]; pp < &proc[NPROC]; pp++) 04709 if (pp->p_pid == cp->p_ppid) { 04710 wakeup((caddr_t)pp); 04711 cp->p_stat = SSTOP; 04712 swtch(); 04713 if ((cp->p_flag&STRC)==0 || procxmt()) 04714 return; 04715 goto loop; 04716 } 04717 exit(fsig(u.u_procp)); 04718 } 04719 04720 /* 04721 * Perform the action specified by 04722 * the current signal. 04723 * The usual sequence is: 04724 * if(issig()) 04725 * psig(); 04726 */ 04727 psig() 04728 { 04729 register n, p; 04730 register struct proc *rp; 04731 04732 rp = u.u_procp; 04733 if (u.u_fpsaved==0) { 04734 savfp(&u.u_fps); 04735 u.u_fpsaved = 1; 04736 } 04737 if (rp->p_flag&STRC) 04738 stop(); 04739 n = fsig(rp); 04740 if (n==0) 04741 return; 04742 rp->p_sig &= ~(1<<(n-1)); 04743 if((p=u.u_signal[n]) != 0) { 04744 u.u_error = 0; 04745 if(n != SIGINS && n != SIGTRC) 04746 u.u_signal[n] = 0; 04747 sendsig((caddr_t)p, n); 04748 return; 04749 } 04750 switch(n) { 04751 04752 case SIGQUIT: 04753 case SIGINS: 04754 case SIGTRC: 04755 case SIGIOT: 04756 case SIGEMT: 04757 case SIGFPT: 04758 case SIGBUS: 04759 case SIGSEG: 04760 case SIGSYS: 04761 if(core()) 04762 n += 0200; 04763 } 04764 exit(n); 04765 } 04766 04767 /* 04768 * find the signal in bit-position 04769 * representation in p_sig. 04770 */ 04771 fsig(p) 04772 struct proc *p; 04773 { 04774 register n, i; 04775 04776 n = p->p_sig; 04777 for(i=1; i04778 if(n & 1) 04779 return(i); 04780 n >>= 1; 04781 } 04782 return(0); 04783 } 04784 04785 /* 04786 * Create a core image on the file "core" 04787 * If you are looking for protection glitches, 04788 * there are probably a wealth of them here 04789 * when this occurs to a suid command. 04790 * 04791 * It writes USIZE block of the 04792 * user.h area followed by the entire 04793 * data+stack segments. 04794 */ 04795 core() 04796 { 04797 register struct inode *ip; 04798 register unsigned s; 04799 extern schar(); 04800 04801 u.u_error = 0; 04802 u.u_dirp = "core"; 04803 ip = namei(schar, 1); 04804 if(ip == NULL) { 04805 if(u.u_error) 04806 return(0); 04807 ip = maknode(0666); 04808 if (ip==NULL) 04809 return(0); 04810 } 04811 if(!access(ip, IWRITE) && 04812 (ip->i_mode&IFMT) == IFREG && 04813 u.u_uid == u.u_ruid) { 04814 itrunc(ip); 04815 u.u_offset = 0; 04816 u.u_base = (caddr_t)&u; 04817 u.u_count = ctob(USIZE); 04818 u.u_segflg = 1; 04819 writei(ip); 04820 s = u.u_procp->p_size - USIZE; 04821 estabur((unsigned)0, s, (unsigned)0, 0, RO); 04822 u.u_base = 0; 04823 u.u_count = ctob(s); 04824 u.u_segflg = 0; 04825 writei(ip); 04826 } 04827 iput(ip); 04828 return(u.u_error==0); 04829 } 04830 04831 /* 04832 * grow the stack to include the SP 04833 * true return if successful. 04834 */ 04835 04836 grow(sp) 04837 unsigned sp; 04838 { 04839 register si, i; 04840 register struct proc *p; 04841 register a; 04842 04843 if(sp >= -ctob(u.u_ssize)) 04844 return(0); 04845 si = (-sp)/64 - u.u_ssize + SINCR; 04846 if(si <= 0) 04847 return(0); 04848 if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep, RO)) 04849 return(0); 04850 p = u.u_procp; 04851 expand(p->p_size+si); 04852 a = p->p_addr + p->p_size; 04853 for(i=u.u_ssize; i; i--) { 04854 a--; 04855 copyseg(a-si, a); 04856 } 04857 for(i=si; i; i--) 04858 clearseg(--a); 04859 u.u_ssize += si; 04860 return(1); 04861 } 04862 04863 /* 04864 * sys-trace system call. 04865 */ 04866 ptrace() 04867 { 04868 register struct proc *p; 04869 register struct a { 04870 int data; 04871 int pid; 04872 int *addr; 04873 int req; 04874 } *uap; 04875 04876 uap = (struct a *)u.u_ap; 04877 if (uap->req <= 0) { 04878 u.u_procp->p_flag |= STRC; 04879 return; 04880 } 04881 for (p=proc; p < &proc[NPROC]; p++) 04882 if (p->p_stat==SSTOP 04883 && p->p_pid==uap->pid 04884 && p->p_ppid==u.u_procp->p_pid) 04885 goto found; 04886 u.u_error = ESRCH; 04887 return; 04888 04889 found: 04890 while (ipc.ip_lock) 04891 sleep((caddr_t)&ipc, IPCPRI); 04892 ipc.ip_lock = p->p_pid; 04893 ipc.ip_data = uap->data; 04894 ipc.ip_addr = uap->addr; 04895 ipc.ip_req = uap->req; 04896 p->p_flag &= ~SWTED; 04897 setrun(p); 04898 while (ipc.ip_req > 0) 04899 sleep((caddr_t)&ipc, IPCPRI); 04900 u.u_r.r_val1 = ipc.ip_data; 04901 if (ipc.ip_req < 0) 04902 u.u_error = EIO; 04903 ipc.ip_lock = 0; 04904 wakeup((caddr_t)&ipc); 04905 } 04906 04907 /* 04908 * Code that the child process 04909 * executes to implement the command 04910 * of the parent process in tracing. 04911 */ 04912 procxmt() 04913 { 04914 register int i; 04915 register *p; 04916 register struct text *xp; 04917 04918 if (ipc.ip_lock != u.u_procp->p_pid) 04919 return(0); 04920 i = ipc.ip_req; 04921 ipc.ip_req = 0; 04922 wakeup((caddr_t)&ipc); 04923 switch (i) { 04924 04925 /* read user I */ 04926 case 1: 04927 if (fuibyte((caddr_t)ipc.ip_addr) == -1) 04928 goto error; 04929 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 04930 break; 04931 04932 /* read user D */ 04933 case 2: 04934 if (fubyte((caddr_t)ipc.ip_addr) == -1) 04935 goto error; 04936 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 04937 break; 04938 04939 /* read u */ 04940 case 3: 04941 i = (int)ipc.ip_addr; 04942 if (i<0 || i >= ctob(USIZE)) 04943 goto error; 04944 ipc.ip_data = ((physadr)&u)->r[i>>1]; 04945 break; 04946 04947 /* write user I */ 04948 /* Must set up to allow writing */ 04949 case 4: 04950 /* 04951 * If text, must assure exclusive use 04952 */ 04953 if (xp = u.u_procp->p_textp) { 04954 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 04955 goto error; 04956 xp->x_iptr->i_flag &= ~ITEXT; 04957 } 04958 estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RW); 04959 i = suiword((caddr_t)ipc.ip_addr, 0); 04960 suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 04961 estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RO); 04962 if (i<0) 04963 goto error; 04964 if (xp) 04965 xp->x_flag |= XWRIT; 04966 break; 04967 04968 /* write user D */ 04969 case 5: 04970 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 04971 goto error; 04972 suword((caddr_t)ipc.ip_addr, ipc.ip_data); 04973 break; 04974 04975 /* write u */ 04976 case 6: 04977 i = (int)ipc.ip_addr; 04978 p = (int *)&((physadr)&u)->r[i>>1]; 04979 if (p >= (int *)&u.u_fps && p < (int *)&u.u_fps.u_fpregs[6]) 04980 goto ok; 04981 for (i=0; i<8; i++) 04982 if (p == &u.u_ar0[regloc[i]]) 04983 goto ok; 04984 if (p == &u.u_ar0[RPS]) { 04985 ipc.ip_data |= 0170000; /* assure user space */ 04986 ipc.ip_data &= ~0340; /* priority 0 */ 04987 goto ok; 04988 } 04989 goto error; 04990 04991 ok: 04992 *p = ipc.ip_data; 04993 break; 04994 04995 /* set signal and continue */ 04996 /* one version causes a trace-trap */ 04997 case 9: 04998 u.u_ar0[RPS] |= TBIT; 04999 case 7: 05000 if ((int)ipc.ip_addr != 1) 05001 u.u_ar0[PC] = (int)ipc.ip_addr; 05002 u.u_procp->p_sig = 0; 05003 if (ipc.ip_data) 05004 psignal(u.u_procp, ipc.ip_data); 05005 return(1); 05006 05007 /* force exit */ 05008 case 8: 05009 exit(fsig(u.u_procp)); 05010 05011 default: 05012 error: 05013 ipc.ip_req = -1; 05014 } 05015 return(0); 05016 } 05017 05018 05019 05020 05021 05022 05023 05024 05025 05026 05027 05028 05029 05030 05031 05032 05033 05034 05035 05036 05037 05038 05039 05040 05041 05042 05043 05044 05045 05046 05047 05048 05049