Add original unix v6
This commit is contained in:
+374
@@ -0,0 +1,374 @@
|
||||
#
|
||||
/*
|
||||
*/
|
||||
|
||||
#include "../param.h"
|
||||
#include "../systm.h"
|
||||
#include "../user.h"
|
||||
#include "../proc.h"
|
||||
#include "../inode.h"
|
||||
#include "../reg.h"
|
||||
|
||||
/*
|
||||
* Priority for tracing
|
||||
*/
|
||||
#define IPCPRI (-1)
|
||||
|
||||
/*
|
||||
* Structure to access an array of integers.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
int inta[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tracing variables.
|
||||
* Used to pass trace command from
|
||||
* parent to child being traced.
|
||||
* This data base cannot be
|
||||
* shared and is locked
|
||||
* per user.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
int ip_lock;
|
||||
int ip_req;
|
||||
int ip_addr;
|
||||
int ip_data;
|
||||
} ipc;
|
||||
|
||||
/*
|
||||
* Send the specified signal to
|
||||
* all processes with 'tp' as its
|
||||
* controlling teletype.
|
||||
* Called by tty.c for quits and
|
||||
* interrupts.
|
||||
*/
|
||||
signal(tp, sig)
|
||||
{
|
||||
register struct proc *p;
|
||||
|
||||
for(p = &proc[0]; p < &proc[NPROC]; p++)
|
||||
if(p->p_ttyp == tp)
|
||||
psignal(p, sig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the specified signal to
|
||||
* the specified process.
|
||||
*/
|
||||
psignal(p, sig)
|
||||
int *p;
|
||||
{
|
||||
register *rp;
|
||||
|
||||
if(sig >= NSIG)
|
||||
return;
|
||||
rp = p;
|
||||
if(rp->p_sig != SIGKIL)
|
||||
rp->p_sig = sig;
|
||||
if(rp->p_stat > PUSER)
|
||||
rp->p_stat = PUSER;
|
||||
if(rp->p_stat == SWAIT)
|
||||
setrun(rp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the current
|
||||
* process has a signal to process.
|
||||
* This is asked at least once
|
||||
* each time a process enters the
|
||||
* system.
|
||||
* A signal does not do anything
|
||||
* directly to a process; it sets
|
||||
* a flag that asks the process to
|
||||
* do something to itself.
|
||||
*/
|
||||
issig()
|
||||
{
|
||||
register n;
|
||||
register struct proc *p;
|
||||
|
||||
p = u.u_procp;
|
||||
if(n = p->p_sig) {
|
||||
if (p->p_flag&STRC) {
|
||||
stop();
|
||||
if ((n = p->p_sig) == 0)
|
||||
return(0);
|
||||
}
|
||||
if((u.u_signal[n]&1) == 0)
|
||||
return(n);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter the tracing STOP state.
|
||||
* In this state, the parent is
|
||||
* informed and the process is able to
|
||||
* receive commands from the parent.
|
||||
*/
|
||||
stop()
|
||||
{
|
||||
register struct proc *pp, *cp;
|
||||
|
||||
loop:
|
||||
cp = u.u_procp;
|
||||
if(cp->p_ppid != 1)
|
||||
for (pp = &proc[0]; pp < &proc[NPROC]; pp++)
|
||||
if (pp->p_pid == cp->p_ppid) {
|
||||
wakeup(pp);
|
||||
cp->p_stat = SSTOP;
|
||||
swtch();
|
||||
if ((cp->p_flag&STRC)==0 || procxmt())
|
||||
return;
|
||||
goto loop;
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the action specified by
|
||||
* the current signal.
|
||||
* The usual sequence is:
|
||||
* if(issig())
|
||||
* psig();
|
||||
*/
|
||||
psig()
|
||||
{
|
||||
register n, p;
|
||||
register *rp;
|
||||
|
||||
rp = u.u_procp;
|
||||
n = rp->p_sig;
|
||||
rp->p_sig = 0;
|
||||
if((p=u.u_signal[n]) != 0) {
|
||||
u.u_error = 0;
|
||||
if(n != SIGINS && n != SIGTRC)
|
||||
u.u_signal[n] = 0;
|
||||
n = u.u_ar0[R6] - 4;
|
||||
grow(n);
|
||||
suword(n+2, u.u_ar0[RPS]);
|
||||
suword(n, u.u_ar0[R7]);
|
||||
u.u_ar0[R6] = n;
|
||||
u.u_ar0[RPS] =& ~TBIT;
|
||||
u.u_ar0[R7] = p;
|
||||
return;
|
||||
}
|
||||
switch(n) {
|
||||
|
||||
case SIGQIT:
|
||||
case SIGINS:
|
||||
case SIGTRC:
|
||||
case SIGIOT:
|
||||
case SIGEMT:
|
||||
case SIGFPT:
|
||||
case SIGBUS:
|
||||
case SIGSEG:
|
||||
case SIGSYS:
|
||||
u.u_arg[0] = n;
|
||||
if(core())
|
||||
n =+ 0200;
|
||||
}
|
||||
u.u_arg[0] = (u.u_ar0[R0]<<8) | n;
|
||||
exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a core image on the file "core"
|
||||
* If you are looking for protection glitches,
|
||||
* there are probably a wealth of them here
|
||||
* when this occurs to a suid command.
|
||||
*
|
||||
* It writes USIZE block of the
|
||||
* user.h area followed by the entire
|
||||
* data+stack segments.
|
||||
*/
|
||||
core()
|
||||
{
|
||||
register s, *ip;
|
||||
extern schar;
|
||||
|
||||
u.u_error = 0;
|
||||
u.u_dirp = "core";
|
||||
ip = namei(&schar, 1);
|
||||
if(ip == NULL) {
|
||||
if(u.u_error)
|
||||
return(0);
|
||||
ip = maknode(0666);
|
||||
if(ip == NULL)
|
||||
return(0);
|
||||
}
|
||||
if(!access(ip, IWRITE) &&
|
||||
(ip->i_mode&IFMT) == 0 &&
|
||||
u.u_uid == u.u_ruid) {
|
||||
itrunc(ip);
|
||||
u.u_offset[0] = 0;
|
||||
u.u_offset[1] = 0;
|
||||
u.u_base = &u;
|
||||
u.u_count = USIZE*64;
|
||||
u.u_segflg = 1;
|
||||
writei(ip);
|
||||
s = u.u_procp->p_size - USIZE;
|
||||
estabur(0, s, 0, 0);
|
||||
u.u_base = 0;
|
||||
u.u_count = s*64;
|
||||
u.u_segflg = 0;
|
||||
writei(ip);
|
||||
}
|
||||
iput(ip);
|
||||
return(u.u_error==0);
|
||||
}
|
||||
|
||||
/*
|
||||
* grow the stack to include the SP
|
||||
* true return if successful.
|
||||
*/
|
||||
|
||||
grow(sp)
|
||||
char *sp;
|
||||
{
|
||||
register a, si, i;
|
||||
|
||||
if(sp >= -u.u_ssize*64)
|
||||
return(0);
|
||||
si = ldiv(-sp, 64) - u.u_ssize + SINCR;
|
||||
if(si <= 0)
|
||||
return(0);
|
||||
if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep))
|
||||
return(0);
|
||||
expand(u.u_procp->p_size+si);
|
||||
a = u.u_procp->p_addr + u.u_procp->p_size;
|
||||
for(i=u.u_ssize; i; i--) {
|
||||
a--;
|
||||
copyseg(a-si, a);
|
||||
}
|
||||
for(i=si; i; i--)
|
||||
clearseg(--a);
|
||||
u.u_ssize =+ si;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* sys-trace system call.
|
||||
*/
|
||||
ptrace()
|
||||
{
|
||||
register struct proc *p;
|
||||
|
||||
if (u.u_arg[2] <= 0) {
|
||||
u.u_procp->p_flag =| STRC;
|
||||
return;
|
||||
}
|
||||
for (p=proc; p < &proc[NPROC]; p++)
|
||||
if (p->p_stat==SSTOP
|
||||
&& p->p_pid==u.u_arg[0]
|
||||
&& p->p_ppid==u.u_procp->p_pid)
|
||||
goto found;
|
||||
u.u_error = ESRCH;
|
||||
return;
|
||||
|
||||
found:
|
||||
while (ipc.ip_lock)
|
||||
sleep(&ipc, IPCPRI);
|
||||
ipc.ip_lock = p->p_pid;
|
||||
ipc.ip_data = u.u_ar0[R0];
|
||||
ipc.ip_addr = u.u_arg[1] & ~01;
|
||||
ipc.ip_req = u.u_arg[2];
|
||||
p->p_flag =& ~SWTED;
|
||||
setrun(p);
|
||||
while (ipc.ip_req > 0)
|
||||
sleep(&ipc, IPCPRI);
|
||||
u.u_ar0[R0] = ipc.ip_data;
|
||||
if (ipc.ip_req < 0)
|
||||
u.u_error = EIO;
|
||||
ipc.ip_lock = 0;
|
||||
wakeup(&ipc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Code that the child process
|
||||
* executes to implement the command
|
||||
* of the parent process in tracing.
|
||||
*/
|
||||
procxmt()
|
||||
{
|
||||
register int i;
|
||||
register int *p;
|
||||
|
||||
if (ipc.ip_lock != u.u_procp->p_pid)
|
||||
return(0);
|
||||
i = ipc.ip_req;
|
||||
ipc.ip_req = 0;
|
||||
wakeup(&ipc);
|
||||
switch (i) {
|
||||
|
||||
/* read user I */
|
||||
case 1:
|
||||
if (fuibyte(ipc.ip_addr) == -1)
|
||||
goto error;
|
||||
ipc.ip_data = fuiword(ipc.ip_addr);
|
||||
break;
|
||||
|
||||
/* read user D */
|
||||
case 2:
|
||||
if (fubyte(ipc.ip_addr) == -1)
|
||||
goto error;
|
||||
ipc.ip_data = fuword(ipc.ip_addr);
|
||||
break;
|
||||
|
||||
/* read u */
|
||||
case 3:
|
||||
i = ipc.ip_addr;
|
||||
if (i<0 || i >= (USIZE<<6))
|
||||
goto error;
|
||||
ipc.ip_data = u.inta[i>>1];
|
||||
break;
|
||||
|
||||
/* write user I (for now, always an error) */
|
||||
case 4:
|
||||
if (suiword(ipc.ip_addr, 0) < 0)
|
||||
goto error;
|
||||
suiword(ipc.ip_addr, ipc.ip_data);
|
||||
break;
|
||||
|
||||
/* write user D */
|
||||
case 5:
|
||||
if (suword(ipc.ip_addr, 0) < 0)
|
||||
goto error;
|
||||
suword(ipc.ip_addr, ipc.ip_data);
|
||||
break;
|
||||
|
||||
/* write u */
|
||||
case 6:
|
||||
p = &u.inta[ipc.ip_addr>>1];
|
||||
if (p >= u.u_fsav && p < &u.u_fsav[25])
|
||||
goto ok;
|
||||
for (i=0; i<9; i++)
|
||||
if (p == &u.u_ar0[regloc[i]])
|
||||
goto ok;
|
||||
goto error;
|
||||
ok:
|
||||
if (p == &u.u_ar0[RPS]) {
|
||||
ipc.ip_data =| 0170000; /* assure user space */
|
||||
ipc.ip_data =& ~0340; /* priority 0 */
|
||||
}
|
||||
*p = ipc.ip_data;
|
||||
break;
|
||||
|
||||
/* set signal and continue */
|
||||
case 7:
|
||||
u.u_procp->p_sig = ipc.ip_data;
|
||||
return(1);
|
||||
|
||||
/* force exit */
|
||||
case 8:
|
||||
exit();
|
||||
|
||||
default:
|
||||
error:
|
||||
ipc.ip_req = -1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
Reference in New Issue
Block a user