xref: /csrg-svn/sys/kern/sys_process.c (revision 8952)
1 /*	sys_process.c	5.5	82/10/31	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/proc.h"
8 #include "../h/inode.h"
9 #include "../h/reg.h"
10 #include "../h/text.h"
11 #include "../h/seg.h"
12 #include "../h/pte.h"
13 #include "../h/psl.h"
14 #include "../h/vm.h"
15 #include "../h/buf.h"
16 #include "../h/acct.h"
17 
18 /*
19  * Priority for tracing
20  */
21 #define	IPCPRI	PZERO
22 
23 /*
24  * Tracing variables.
25  * Used to pass trace command from
26  * parent to child being traced.
27  * This data base cannot be
28  * shared and is locked
29  * per user.
30  */
31 struct {
32 	int	ip_lock;
33 	int	ip_req;
34 	int	*ip_addr;
35 	int	ip_data;
36 } ipc;
37 
38 /*
39  * sys-trace system call.
40  */
41 ptrace()
42 {
43 	register struct proc *p;
44 	register struct a {
45 		int	req;
46 		int	pid;
47 		int	*addr;
48 		int	data;
49 	} *uap;
50 
51 	uap = (struct a *)u.u_ap;
52 	if (uap->req <= 0) {
53 		u.u_procp->p_flag |= STRC;
54 		return;
55 	}
56 	p = pfind(uap->pid);
57 	if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid) {
58 		u.u_error = ESRCH;
59 		return;
60 	}
61 	while (ipc.ip_lock)
62 		sleep((caddr_t)&ipc, IPCPRI);
63 	ipc.ip_lock = p->p_pid;
64 	ipc.ip_data = uap->data;
65 	ipc.ip_addr = uap->addr;
66 	ipc.ip_req = uap->req;
67 	p->p_flag &= ~SWTED;
68 	while (ipc.ip_req > 0) {
69 		if (p->p_stat==SSTOP)
70 			setrun(p);
71 		sleep((caddr_t)&ipc, IPCPRI);
72 	}
73 	u.u_r.r_val1 = ipc.ip_data;
74 	if (ipc.ip_req < 0)
75 		u.u_error = EIO;
76 	ipc.ip_lock = 0;
77 	wakeup((caddr_t)&ipc);
78 }
79 
80 #if vax
81 #define	NIPCREG 16
82 #endif
83 #if sun
84 #define	NIPCREG 17
85 #endif
86 int ipcreg[NIPCREG] =
87 #if vax
88 	{R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC};
89 #endif
90 #if sun
91 	{R0,R1,R2,R3,R4,R5,R6,R7,AR0,AR1,AR2,AR3,AR4,AR5,AR6,AR7,PC};
92 #endif
93 
94 #define	PHYSOFF(p, o)
95 	((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
96 
97 /*
98  * Code that the child process
99  * executes to implement the command
100  * of the parent process in tracing.
101  */
102 procxmt()
103 {
104 	register int i;
105 	register *p;
106 	register struct text *xp;
107 
108 	if (ipc.ip_lock != u.u_procp->p_pid)
109 		return (0);
110 	u.u_procp->p_slptime = 0;
111 	i = ipc.ip_req;
112 	ipc.ip_req = 0;
113 	switch (i) {
114 
115 	/* read user I */
116 	case 1:
117 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
118 			goto error;
119 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
120 		break;
121 
122 	/* read user D */
123 	case 2:
124 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
125 			goto error;
126 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
127 		break;
128 
129 	/* read u */
130 	case 3:
131 		i = (int)ipc.ip_addr;
132 		if (i<0 || i >= ctob(UPAGES))
133 			goto error;
134 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
135 		break;
136 
137 	/* write user I */
138 	/* Must set up to allow writing */
139 	case 4:
140 		/*
141 		 * If text, must assure exclusive use
142 		 */
143 		if (xp = u.u_procp->p_textp) {
144 			if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
145 				goto error;
146 			xp->x_iptr->i_flag &= ~ITEXT;
147 		}
148 		i = -1;
149 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
150 			if (chgprot((caddr_t)ipc.ip_addr, RW) &&
151 			    chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
152 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
153 			(void) chgprot((caddr_t)ipc.ip_addr, RO);
154 			(void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
155 		}
156 		if (i < 0)
157 			goto error;
158 		if (xp)
159 			xp->x_flag |= XWRIT;
160 		break;
161 
162 	/* write user D */
163 	case 5:
164 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
165 			goto error;
166 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
167 		break;
168 
169 	/* write u */
170 	case 6:
171 		i = (int)ipc.ip_addr;
172 		p = (int *)PHYSOFF(&u, i);
173 		for (i=0; i<NIPCREG; i++)
174 			if (p == &u.u_ar0[ipcreg[i]])
175 				goto ok;
176 		if (p == &u.u_ar0[PS]) {
177 			ipc.ip_data |= PSL_USERSET;
178 			ipc.ip_data &=  ~PSL_USERCLR;
179 			goto ok;
180 		}
181 		goto error;
182 
183 	ok:
184 		*p = ipc.ip_data;
185 		break;
186 
187 	/* set signal and continue */
188 	/* one version causes a trace-trap */
189 	case 9:
190 	case 7:
191 		if ((int)ipc.ip_addr != 1)
192 			u.u_ar0[PC] = (int)ipc.ip_addr;
193 		if ((unsigned)ipc.ip_data > NSIG)
194 			goto error;
195 		u.u_procp->p_cursig = ipc.ip_data;	/* see issig */
196 		if (i == 9)
197 			u.u_ar0[PS] |= PSL_T;
198 		wakeup((caddr_t)&ipc);
199 		return (1);
200 
201 	/* force exit */
202 	case 8:
203 		wakeup((caddr_t)&ipc);
204 		exit(u.u_procp->p_cursig);
205 
206 	default:
207 	error:
208 		ipc.ip_req = -1;
209 	}
210 	wakeup((caddr_t)&ipc);
211 	return (0);
212 }
213