bug fixes for LEASES from Rick Macklem
[unix-history] / usr / src / sys / kern / sys_process.c
CommitLineData
5dc2581e
KB
1/*-
2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
da7c5cc6 6 *
817f339a 7 * @(#)sys_process.c 7.36 (Berkeley) %G%
da7c5cc6 8 */
961945a8 9
ff32eb64 10#define IPCREG
38a01dbe
KB
11#include <sys/param.h>
12#include <sys/proc.h>
13#include <sys/vnode.h>
14#include <sys/buf.h>
15#include <sys/ptrace.h>
9ce4de2d 16
38a01dbe
KB
17#include <machine/reg.h>
18#include <machine/psl.h>
19#include <vm/vm.h>
20#include <vm/vm_page.h>
de5931fb 21
38a01dbe 22#include <sys/user.h>
d301d150 23
4147b3f6
BJ
24/*
25 * Priority for tracing
26 */
27#define IPCPRI PZERO
28
29/*
30 * Tracing variables.
31 * Used to pass trace command from
32 * parent to child being traced.
33 * This data base cannot be
34 * shared and is locked
35 * per user.
36 */
37struct {
38 int ip_lock;
39 int ip_req;
40 int *ip_addr;
41 int ip_data;
42} ipc;
43
44/*
3f75397a 45 * Process debugging system call.
4147b3f6 46 */
afc12c69
CT
47struct ptrace_args {
48 int req;
49 int pid;
50 int *addr;
51 int data;
52};
8c7d0e2a
KM
53ptrace(curp, uap, retval)
54 struct proc *curp;
afc12c69 55 register struct ptrace_args *uap;
8c7d0e2a
KM
56 int *retval;
57{
58 register struct proc *p;
ee8c7b71 59 int error;
4147b3f6 60
48c729cb
MH
61 if (uap->req <= 0) {
62 curp->p_flag |= STRC;
63 return (0);
64 }
ee8c7b71 65 p = pfind(uap->pid);
48c729cb
MH
66 if (p == 0)
67 return (ESRCH);
ee8c7b71
KM
68 if (uap->req == PT_ATTACH) {
69 /*
45f54c1f
KB
70 * Must be root if the process has used set user or group
71 * privileges or does not belong to the real user. Must
72 * not be already traced. Can't attach to ourselves.
ee8c7b71
KM
73 */
74 if ((p->p_flag & SUGID ||
75 p->p_cred->p_ruid != curp->p_cred->p_ruid) &&
76 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
77 return (error);
78 if (p->p_flag & STRC)
79 return (EALREADY); /* ??? */
45f54c1f
KB
80 if (p->p_pid == curp->p_pid)
81 return (EINVAL);
ee8c7b71
KM
82 /*
83 * It would be nice if the tracing relationship was separate
84 * from the parent relationship but that would require
85 * another set of links in the proc struct or for "wait"
86 * to scan the entire proc table. To make life easier,
87 * we just re-parent the process we're trying to trace.
88 * The old parent is remembered so we can put things back
89 * on a "detach".
90 */
91 p->p_flag |= STRC;
92 p->p_oppid = p->p_pptr->p_pid;
93 proc_reparent(p, curp);
94 psignal(p, SIGSTOP);
95 return (0);
96 }
48c729cb 97 if (p->p_stat != SSTOP || p->p_pptr != curp || !(p->p_flag & STRC))
d9c2f47f 98 return (ESRCH);
4147b3f6
BJ
99 while (ipc.ip_lock)
100 sleep((caddr_t)&ipc, IPCPRI);
101 ipc.ip_lock = p->p_pid;
102 ipc.ip_data = uap->data;
103 ipc.ip_addr = uap->addr;
104 ipc.ip_req = uap->req;
105 p->p_flag &= ~SWTED;
106 while (ipc.ip_req > 0) {
107 if (p->p_stat==SSTOP)
108 setrun(p);
109 sleep((caddr_t)&ipc, IPCPRI);
110 }
8c7d0e2a 111 *retval = ipc.ip_data;
4147b3f6
BJ
112 ipc.ip_lock = 0;
113 wakeup((caddr_t)&ipc);
8c7d0e2a 114 if (ipc.ip_req < 0)
d9c2f47f
MK
115 return (EIO);
116 return (0);
4147b3f6
BJ
117}
118
e128a701
MK
119#define PHYSOFF(p, o) ((caddr_t)(p) + (o))
120
6ce8aff2
WN
121#if defined(i386)
122#undef PC
123#undef SP
124#undef PS
125#undef R0
126#undef R1
127
128#define PC tEIP
129#define SP tESP
130#define PS tEFLAGS
131#define R0 tEDX
132#define R1 tECX
133#endif
883d0f83 134
4147b3f6 135/*
3f75397a
KM
136 * Transmit a tracing request from the parent to the child process
137 * being debugged. This code runs in the context of the child process
138 * to fulfill the command requested by the parent.
4147b3f6 139 */
82655668
KM
140procxmt(p)
141 register struct proc *p;
4147b3f6 142{
214b997f 143 register int i, *poff, *regs;
e128a701 144 extern char kstack[];
4147b3f6 145
82655668 146 if (ipc.ip_lock != p->p_pid)
4147b3f6 147 return (0);
82655668 148 p->p_slptime = 0;
214b997f
MH
149 regs = p->p_md.md_regs;
150 p->p_addr->u_kproc.kp_proc.p_md.md_regs = regs; /* u.u_ar0 */
4147b3f6
BJ
151 i = ipc.ip_req;
152 ipc.ip_req = 0;
153 switch (i) {
154
01b0e233 155 case PT_READ_I: /* read the child's text space */
4147b3f6
BJ
156 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
157 goto error;
158 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
159 break;
160
01b0e233 161 case PT_READ_D: /* read the child's data space */
4147b3f6
BJ
162 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
163 goto error;
164 ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
165 break;
166
01b0e233 167 case PT_READ_U: /* read the child's u. */
4147b3f6 168 i = (int)ipc.ip_addr;
e128a701 169 if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0)
4147b3f6 170 goto error;
eadb8ef2 171 ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
4147b3f6
BJ
172 break;
173
01b0e233 174 case PT_WRITE_I: /* write the child's text space */
883d0f83 175 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
9db58063
KM
176 vm_offset_t sa, ea;
177 int rv;
178
179 sa = trunc_page((vm_offset_t)ipc.ip_addr);
d6cefe4b 180 ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int));
d7db4999 181 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
9db58063
KM
182 VM_PROT_DEFAULT, FALSE);
183 if (rv == KERN_SUCCESS) {
883d0f83 184 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
d7db4999
MK
185 (void) vm_map_protect(&p->p_vmspace->vm_map,
186 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
187 FALSE);
9db58063 188 }
883d0f83 189 }
4147b3f6
BJ
190 if (i < 0)
191 goto error;
4147b3f6
BJ
192 break;
193
01b0e233 194 case PT_WRITE_D: /* write the child's data space */
4147b3f6
BJ
195 if (suword((caddr_t)ipc.ip_addr, 0) < 0)
196 goto error;
197 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
198 break;
199
01b0e233 200 case PT_WRITE_U: /* write the child's u. */
4147b3f6 201 i = (int)ipc.ip_addr;
d89b7f8b
MT
202#ifdef mips
203 poff = (int *)PHYSOFF(curproc->p_addr, i);
204#else
e128a701 205 poff = (int *)PHYSOFF(kstack, i);
d89b7f8b 206#endif
883d0f83 207 for (i=0; i<NIPCREG; i++)
214b997f 208 if (poff == &regs[ipcreg[i]])
4147b3f6 209 goto ok;
214b997f
MH
210#if defined(hp300)
211 /*
212 * In the new frame layout, PS/PC are skewed by 2 bytes.
213 */
214 regs = (int *)((short *)regs + 1);
215 if (poff == &regs[PC])
216 goto ok;
217#endif
218 if (poff == &regs[PS]) {
883d0f83 219 ipc.ip_data |= PSL_USERSET;
dc57440c 220 ipc.ip_data &= ~PSL_USERCLR;
bf47fbca
MK
221#ifdef PSL_CM_CLR
222 if (ipc.ip_data & PSL_CM)
223 ipc.ip_data &= ~PSL_CM_CLR;
224#endif
4147b3f6
BJ
225 goto ok;
226 }
7c02c1d3 227#if defined(hp300) || defined(luna68k)
dc57440c 228#ifdef FPCOPROC
e128a701
MK
229 if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs &&
230 poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar)
dc57440c
KM
231 goto ok;
232#endif
233#endif
4147b3f6
BJ
234 goto error;
235
236 ok:
82655668 237 *poff = ipc.ip_data;
4147b3f6
BJ
238 break;
239
01b0e233
MK
240 case PT_STEP: /* single step the child */
241 case PT_CONTINUE: /* continue the child */
214b997f 242 regs = (int *)((short *)regs + 1);
ee8c7b71
KM
243 if ((unsigned)ipc.ip_data >= NSIG)
244 goto error;
4147b3f6 245 if ((int)ipc.ip_addr != 1)
214b997f 246 regs[PC] = (int)ipc.ip_addr;
19dec745 247 p->p_xstat = ipc.ip_data; /* see issig */
d89b7f8b
MT
248#ifdef PSL_T
249 /* need something more machine independent here... */
01b0e233 250 if (i == PT_STEP)
214b997f 251 regs[PS] |= PSL_T;
d89b7f8b 252#endif
4147b3f6
BJ
253 wakeup((caddr_t)&ipc);
254 return (1);
255
01b0e233 256 case PT_KILL: /* kill the child process */
4147b3f6 257 wakeup((caddr_t)&ipc);
817f339a 258 exit1(p, (int)p->p_xstat);
4147b3f6 259
ee8c7b71 260 case PT_DETACH: /* stop tracing the child */
214b997f 261 regs = (int *)((short *)regs + 1);
ee8c7b71
KM
262 if ((unsigned)ipc.ip_data >= NSIG)
263 goto error;
264 if ((int)ipc.ip_addr != 1)
214b997f 265 regs[PC] = (int)ipc.ip_addr;
ee8c7b71
KM
266 p->p_xstat = ipc.ip_data; /* see issig */
267 p->p_flag &= ~STRC;
268 if (p->p_oppid != p->p_pptr->p_pid) {
269 register struct proc *pp = pfind(p->p_oppid);
270
271 if (pp)
272 proc_reparent(p, pp);
273 }
274 p->p_oppid = 0;
275 wakeup((caddr_t)&ipc);
276 return (1);
277
4147b3f6
BJ
278 default:
279 error:
280 ipc.ip_req = -1;
281 }
282 wakeup((caddr_t)&ipc);
283 return (0);
284}