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