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