3900: # 3901: /* 3902: */ 3903: 3904: #include "../param.h" 3905: #include "../systm.h" 3906: #include "../user.h" 3907: #include "../proc.h" 3908: #include "../inode.h" 3909: #include "../reg.h" 3910: 3911: /* 3912: * Priority for tracing 3913: */ 3914: #define IPCPRI (-1) 3915: 3916: /* 3917: * Structure to access an array of integers. 3918: */ 3919: struct 3920: { 3921: int inta[]; 3922: }; 3923: /* --------------------------- */ 3924: 3925: /* 3926: * Tracing variables. 3927: * Used to pass trace command from 3928: * parent to child being traced. 3929: * This data base cannot be 3930: * shared and is locked 3931: * per user. 3932: */ 3933: struct 3934: { 3935: int ip_lock; 3936: int ip_req; 3937: int ip_addr; 3938: int ip_data; 3939: } ipc; 3940: /* --------------------------- */ 3941: 3942: /* 3943: * Send the specified signal to 3944: * all processes with 'tp' as its 3945: * controlling teletype. 3946: * Called by tty.c for quits and 3947: * interrupts. 3948: */ 3949: signal(tp, sig) 3950: { 3951: register struct proc *p; 3952: 3953: for(p = &proc[0]; p < &proc[NPROC]; p++) 3954: if(p->p_ttyp == tp) 3955: psignal(p, sig); 3956: } 3957: /* --------------------------- */ 3958: 3959: /* 3960: * Send the specified signal to 3961: * the specified process. 3962: */ 3963: psignal(p, sig) 3964: int *p; 3965: { 3966: register *rp; 3967: 3968: if(sig >= NSIG) 3969: return; 3970: rp = p; 3971: if(rp->p_sig != SIGKIL) 3972: rp->p_sig = sig; 3973: if(rp->p_stat > PUSER) 3974: rp->p_stat = PUSER; 3975: if(rp->p_stat == SWAIT) 3976: setrun(rp); 3977: } 3978: /* --------------------------- */ 3979: 3980: /* 3981: * Returns true if the current 3982: * process has a signal to process. 3983: * This is asked at least once 3984: * each time a process enters the 3985: * system. 3986: * A signal does not do anything 3987: * directly to a process; it sets 3988: * a flag that asks the process to 3989: * do something to itself. 3990: */ 3991: issig() 3992: { 3993: register n; 3994: register struct proc *p; 3995: 3996: p = u.u_procp; 3997: if(n = p->p_sig) { 3998: if (p->p_flag&STRC) { 3999: stop(); 4000: if ((n = p->p_sig) == 0) 4001: return(0); 4002: } 4003: if((u.u_signal[n]&1) == 0) 4004: return(n); 4005: } 4006: return(0); 4007: } 4008: /* --------------------------- */ 4009: 4010: /* 4011: * Enter the tracing STOP state. 4012: * In this state, the parent is 4013: * informed and the process is able to 4014: * receive commands from the parent. 4015: */ 4016: stop() 4017: { 4018: register struct proc *pp, *cp; 4019: 4020: loop: 4021: cp = u.u_procp; 4022: if(cp->p_ppid != 1) 4023: for (pp = &proc[0]; pp < &proc[NPROC]; pp++) 4024: if (pp->p_pid == cp->p_ppid) { 4025: wakeup(pp); 4026: cp->p_stat = SSTOP; 4027: swtch(); 4028: if ((cp->p_flag&STRC)==0 || procxmt()) 4029: return; 4030: goto loop; 4031: } 4032: exit(); 4033: } 4034: /* --------------------------- */ 4035: 4036: /* 4037: * Perform the action specified by 4038: * the current signal. 4039: * The usual sequence is: 4040: * if(issig()) 4041: * psig(); 4042: */ 4043: psig() 4044: { 4045: register n, p; 4046: register *rp; 4047: 4048: rp = u.u_procp; 4049: n = rp->p_sig; 4050: rp->p_sig = 0; 4051: if((p=u.u_signal[n]) != 0) { 4052: u.u_error = 0; 4053: if(n != SIGINS && n != SIGTRC) 4054: u.u_signal[n] = 0; 4055: n = u.u_ar0[R6] - 4; 4056: grow(n); 4057: suword(n+2, u.u_ar0[RPS]); 4058: suword(n, u.u_ar0[R7]); 4059: u.u_ar0[R6] = n; 4060: u.u_ar0[RPS] =& ~TBIT; 4061: u.u_ar0[R7] = p; 4062: return; 4063: } 4064: switch(n) { 4065: 4066: case SIGQIT: 4067: case SIGINS: 4068: case SIGTRC: 4069: case SIGIOT: 4070: case SIGEMT: 4071: case SIGFPT: 4072: case SIGBUS: 4073: case SIGSEG: 4074: case SIGSYS: 4075: u.u_arg[0] = n; 4076: if(core()) 4077: n =+ 0200; 4078: } 4079: u.u_arg[0] = (u.u_ar0[R0]<<8) | n; 4080: exit(); 4081: } 4082: /* --------------------------- */ 4083: 4084: /* 4085: * Create a core image on the file "core" 4086: * If you are looking for protection glitches, 4087: * there are probably a wealth of them here 4088: * when this occurs to a suid command. 4089: * 4090: * It writes USIZE block of the 4091: * user.h area followed by the entire 4092: * data+stack segments. 4093: */ 4094: core() 4095: { 4096: register s, *ip; 4097: extern schar; 4098: 4099: u.u_error = 0; 4100: u.u_dirp = "core"; 4101: ip = namei(&schar, 1); 4102: if(ip == NULL) { 4103: if(u.u_error) 4104: return(0); 4105: ip = maknode(0666); 4106: if(ip == NULL) 4107: return(0); 4108: } 4109: if(!access(ip, IWRITE) && 4110: (ip->i_mode&IFMT) == 0 && 4111: u.u_uid == u.u_ruid) { 4112: itrunc(ip); 4113: u.u_offset[0] = 0; 4114: u.u_offset[1] = 0; 4115: u.u_base = &u; 4116: u.u_count = USIZE*64; 4117: u.u_segflg = 1; 4118: writei(ip); 4119: s = u.u_procp->p_size - USIZE; 4120: estabur(0, s, 0, 0); 4121: u.u_base = 0; 4122: u.u_count = s*64; 4123: u.u_segflg = 0; 4124: writei(ip); 4125: } 4126: iput(ip); 4127: return(u.u_error==0); 4128: } 4129: /* --------------------------- */ 4130: 4131: /* 4132: * grow the stack to include the SP 4133: * true return if successful. 4134: */ 4135: 4136: grow(sp) 4137: char *sp; 4138: { 4139: register a, si, i; 4140: 4141: if(sp >= -u.u_ssize*64) 4142: return(0); 4143: si = ldiv(-sp, 64) - u.u_ssize + SINCR; 4144: if(si <= 0) 4145: return(0); 4146: if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep)) 4147: return(0); 4148: expand(u.u_procp->p_size+si); 4149: a = u.u_procp->p_addr + u.u_procp->p_size; 4150: for(i=u.u_ssize; i; i--) { 4151: a--; 4152: copyseg(a-si, a); 4153: } 4154: for(i=si; i; i--) 4155: clearseg(--a); 4156: u.u_ssize =+ si; 4157: return(1); 4158: } 4159: /* --------------------------- */ 4160: 4161: /* 4162: * sys-trace system call. 4163: */ 4164: ptrace() 4165: { 4166: register struct proc *p; 4167: 4168: if (u.u_arg[2] <= 0) { 4169: u.u_procp->p_flag =| STRC; 4170: return; 4171: } 4172: for (p=proc; p < &proc[NPROC]; p++) 4173: if (p->p_stat==SSTOP 4174: && p->p_pid==u.u_arg[0] 4175: && p->p_ppid==u.u_procp->p_pid) 4176: goto found; 4177: u.u_error = ESRCH; 4178: return; 4179: 4180: found: 4181: while (ipc.ip_lock) 4182: sleep(&ipc, IPCPRI); 4183: ipc.ip_lock = p->p_pid; 4184: ipc.ip_data = u.u_ar0[R0]; 4185: ipc.ip_addr = u.u_arg[1] & ~01; 4186: ipc.ip_req = u.u_arg[2]; 4187: p->p_flag =& ~SWTED; 4188: setrun(p); 4189: while (ipc.ip_req > 0) 4190: sleep(&ipc, IPCPRI); 4191: u.u_ar0[R0] = ipc.ip_data; 4192: if (ipc.ip_req < 0) 4193: u.u_error = EIO; 4194: ipc.ip_lock = 0; 4195: wakeup(&ipc); 4196: } 4197: /* --------------------------- */ 4198: 4199: /* 4200: * Code that the child process 4201: * executes to implement the command 4202: * of the parent process in tracing. 4203: */ 4204: procxmt() 4205: { 4206: register int i; 4207: register int *p; 4208: 4209: if (ipc.ip_lock != u.u_procp->p_pid) 4210: return(0); 4211: i = ipc.ip_req; 4212: ipc.ip_req = 0; 4213: wakeup(&ipc); 4214: switch (i) { 4215: 4216: /* read user I */ 4217: case 1: 4218: if (fuibyte(ipc.ip_addr) == -1) 4219: goto error; 4220: ipc.ip_data = fuiword(ipc.ip_addr); 4221: break; 4222: 4223: /* read user D */ 4224: case 2: 4225: if (fubyte(ipc.ip_addr) == -1) 4226: goto error; 4227: ipc.ip_data = fuword(ipc.ip_addr); 4228: break; 4229: 4230: /* read u */ 4231: case 3: 4232: i = ipc.ip_addr; 4233: if (i<0 || i >= (USIZE<<6)) 4234: goto error; 4235: ipc.ip_data = u.inta[i>>1]; 4236: break; 4237: 4238: /* write user I (for now, always an error) */ 4239: case 4: 4240: if (suiword(ipc.ip_addr, 0) < 0) 4241: goto error; 4242: suiword(ipc.ip_addr, ipc.ip_data); 4243: break; 4244: 4245: /* write user D */ 4246: case 5: 4247: if (suword(ipc.ip_addr, 0) < 0) 4248: goto error; 4249: suword(ipc.ip_addr, ipc.ip_data); 4250: break; 4251: 4252: /* write u */ 4253: case 6: 4254: p = &u.inta[ipc.ip_addr>>1]; 4255: if (p >= u.u_fsav && p < &u.u_fsav[25]) 4256: goto ok; 4257: for (i=0; i<9; i++) 4258: if (p == &u.u_ar0[regloc[i]]) 4259: goto ok; 4260: goto error; 4261: ok: 4262: if (p == &u.u_ar0[RPS]) { 4263: 4264: ipc.ip_data =| 0170000; /* assure user space */ 4265: 4266: ipc.ip_data =& ~0340; /* priority 0 */ 4267: } 4268: *p = ipc.ip_data; 4269: break; 4270: 4271: /* set signal and continue */ 4272: case 7: 4273: u.u_procp->p_sig = ipc.ip_data; 4274: return(1); 4275: 4276: /* force exit */ 4277: case 8: 4278: exit(); 4279: 4280: default: 4281: error: 4282: ipc.ip_req = -1; 4283: } 4284: return(0); 4285: } 4286: /* --------------------------- */