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: /* --------------------------- */