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