sys_process.c revision 1.7
1/* $OpenBSD: sys_process.c,v 1.7 1999/02/26 05:12:18 art Exp $ */ 2/* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */ 3 4/*- 5 * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. 6 * Copyright (c) 1982, 1986, 1989, 1993 7 * The Regents of the University of California. All rights reserved. 8 * (c) UNIX System Laboratories, Inc. 9 * All or some portions of this file are derived from material licensed 10 * to the University of California by American Telephone and Telegraph 11 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 12 * the permission of UNIX System Laboratories, Inc. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93 43 */ 44 45/* 46 * References: 47 * (1) Bach's "The Design of the UNIX Operating System", 48 * (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution, 49 * (3) the "4.4BSD Programmer's Reference Manual" published 50 * by USENIX and O'Reilly & Associates. 51 * The 4.4BSD PRM does a reasonably good job of documenting what the various 52 * ptrace() requests should actually do, and its text is quoted several times 53 * in this file. 54 */ 55 56#include <sys/param.h> 57#include <sys/systm.h> 58#include <sys/proc.h> 59#include <sys/errno.h> 60#include <sys/ptrace.h> 61#include <sys/uio.h> 62#include <sys/user.h> 63 64#include <sys/mount.h> 65#include <sys/syscallargs.h> 66 67#if defined(UVM) 68#include <vm/vm.h> 69#include <uvm/uvm_extern.h> 70#endif 71 72#include <machine/reg.h> 73 74#include <miscfs/procfs/procfs.h> 75 76/* Macros to clear/set/test flags. */ 77#define SET(t, f) (t) |= (f) 78#define CLR(t, f) (t) &= ~(f) 79#define ISSET(t, f) ((t) & (f)) 80 81/* 82 * Process debugging system call. 83 */ 84int 85sys_ptrace(p, v, retval) 86 struct proc *p; 87 void *v; 88 register_t *retval; 89{ 90 struct sys_ptrace_args /* { 91 syscallarg(int) req; 92 syscallarg(pid_t) pid; 93 syscallarg(caddr_t) addr; 94 syscallarg(int) data; 95 } */ *uap = v; 96 struct proc *t; /* target process */ 97 struct uio uio; 98 struct iovec iov; 99 int error, write; 100 101 /* "A foolish consistency..." XXX */ 102 if (SCARG(uap, req) == PT_TRACE_ME) 103 t = p; 104 else { 105 106 /* Find the process we're supposed to be operating on. */ 107 if ((t = pfind(SCARG(uap, pid))) == NULL) 108 return (ESRCH); 109 } 110 111 /* Make sure we can operate on it. */ 112 switch (SCARG(uap, req)) { 113 case PT_TRACE_ME: 114 /* Saying that you're being traced is always legal. */ 115 break; 116 117 case PT_ATTACH: 118 /* 119 * You can't attach to a process if: 120 * (1) it's the process that's doing the attaching, 121 */ 122 if (t->p_pid == p->p_pid) 123 return (EINVAL); 124 125 /* 126 * (2) it's already being traced, or 127 */ 128 if (ISSET(t->p_flag, P_TRACED)) 129 return (EBUSY); 130 131 /* 132 * (3) it's not owned by you, or the last exec 133 * gave us setuid/setgid privs (unless 134 * you're root), or... 135 * 136 * [Note: once P_SUGID gets set in execve(), it stays 137 * set until the process does another execve(). Hence 138 * this prevents a setuid process which revokes it's 139 * special privilidges using setuid() from being 140 * traced. This is good security.] 141 */ 142 if ((t->p_cred->p_ruid != p->p_cred->p_ruid || 143 ISSET(t->p_flag, P_SUGID)) && 144 (error = suser(p->p_ucred, &p->p_acflag)) != 0) 145 return (error); 146 147 /* 148 * (4) ...it's init, which controls the security level 149 * of the entire system, and the system was not 150 * compiled with permanently insecure mode turned 151 * on. 152 */ 153 if ((t->p_pid == 1) && (securelevel > -1)) 154 return (EPERM); 155 break; 156 157 case PT_READ_I: 158 case PT_READ_D: 159 case PT_WRITE_I: 160 case PT_WRITE_D: 161 case PT_CONTINUE: 162 case PT_KILL: 163 case PT_DETACH: 164#ifdef PT_STEP 165 case PT_STEP: 166#endif 167#ifdef PT_GETREGS 168 case PT_GETREGS: 169#endif 170#ifdef PT_SETREGS 171 case PT_SETREGS: 172#endif 173#ifdef PT_GETFPREGS 174 case PT_GETFPREGS: 175#endif 176#ifdef PT_SETFPREGS 177 case PT_SETFPREGS: 178#endif 179 /* 180 * You can't do what you want to the process if: 181 * (1) It's not being traced at all, 182 */ 183 if (!ISSET(t->p_flag, P_TRACED)) 184 return (EPERM); 185 186 /* 187 * (2) it's not being traced by _you_, or 188 */ 189 if (t->p_pptr != p) 190 return (EBUSY); 191 192 /* 193 * (3) it's not currently stopped. 194 */ 195 if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED)) 196 return (EBUSY); 197 break; 198 199 default: /* It was not a legal request. */ 200 return (EINVAL); 201 } 202 203 /* Do single-step fixup if needed. */ 204 FIX_SSTEP(t); 205 206 /* Now do the operation. */ 207 write = 0; 208 *retval = 0; 209 210 switch (SCARG(uap, req)) { 211 case PT_TRACE_ME: 212 /* Just set the trace flag. */ 213 SET(t->p_flag, P_TRACED); 214 t->p_oppid = t->p_pptr->p_pid; 215 return (0); 216 217 case PT_WRITE_I: /* XXX no seperate I and D spaces */ 218 case PT_WRITE_D: 219 write = 1; 220 case PT_READ_I: /* XXX no seperate I and D spaces */ 221 case PT_READ_D: 222 /* write = 0 done above. */ 223 iov.iov_base = 224 write ? (caddr_t)&SCARG(uap, data) : (caddr_t)retval; 225 iov.iov_len = sizeof(int); 226 uio.uio_iov = &iov; 227 uio.uio_iovcnt = 1; 228 uio.uio_offset = (off_t)(long)SCARG(uap, addr); 229 uio.uio_resid = sizeof(int); 230 uio.uio_segflg = UIO_SYSSPACE; 231 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 232 uio.uio_procp = p; 233 return (procfs_domem(p, t, NULL, &uio)); 234 235#ifdef PT_STEP 236 case PT_STEP: 237 /* 238 * From the 4.4BSD PRM: 239 * "Execution continues as in request PT_CONTINUE; however 240 * as soon as possible after execution of at least one 241 * instruction, execution stops again. [ ... ]" 242 */ 243#endif 244 case PT_CONTINUE: 245 case PT_DETACH: 246 /* 247 * From the 4.4BSD PRM: 248 * "The data argument is taken as a signal number and the 249 * child's execution continues at location addr as if it 250 * incurred that signal. Normally the signal number will 251 * be either 0 to indicate that the signal that caused the 252 * stop should be ignored, or that value fetched out of 253 * the process's image indicating which signal caused 254 * the stop. If addr is (int *)1 then execution continues 255 * from where it stopped." 256 */ 257 258 /* Check that the data is a valid signal number or zero. */ 259 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG) 260 return (EINVAL); 261 262 PHOLD(t); 263 264#ifdef PT_STEP 265 /* 266 * Arrange for a single-step, if that's requested and possible. 267 */ 268 error = process_sstep(t, SCARG(uap, req) == PT_STEP); 269 if (error) 270 goto relebad; 271#endif 272 273 /* If the address paramter is not (int *)1, set the pc. */ 274 if ((int *)SCARG(uap, addr) != (int *)1) 275 if ((error = process_set_pc(t, SCARG(uap, addr))) != 0) 276 goto relebad; 277 278 PRELE(t); 279 280 if (SCARG(uap, req) == PT_DETACH) { 281 /* give process back to original parent or init */ 282 if (t->p_oppid != t->p_pptr->p_pid) { 283 struct proc *pp; 284 285 pp = pfind(t->p_oppid); 286 proc_reparent(t, pp ? pp : initproc); 287 } 288 289 /* not being traced any more */ 290 t->p_oppid = 0; 291 CLR(t->p_flag, P_TRACED|P_WAITED); 292 } 293 294 sendsig: 295 /* Finally, deliver the requested signal (or none). */ 296 if (t->p_stat == SSTOP) { 297 t->p_xstat = SCARG(uap, data); 298 setrunnable(t); 299 } else { 300 if (SCARG(uap, data) != 0) 301 psignal(t, SCARG(uap, data)); 302 } 303 return (0); 304 305 relebad: 306 PRELE(t); 307 return (error); 308 309 case PT_KILL: 310 /* just send the process a KILL signal. */ 311 SCARG(uap, data) = SIGKILL; 312 goto sendsig; /* in PT_CONTINUE, above. */ 313 314 case PT_ATTACH: 315 /* 316 * As done in procfs: 317 * Go ahead and set the trace flag. 318 * Save the old parent (it's reset in 319 * _DETACH, and also in kern_exit.c:wait4() 320 * Reparent the process so that the tracing 321 * proc gets to see all the action. 322 * Stop the target. 323 */ 324 SET(t->p_flag, P_TRACED); 325 t->p_oppid = t->p_pptr->p_pid; 326 if (t->p_pptr != p) 327 proc_reparent(t, p); 328 SCARG(uap, data) = SIGSTOP; 329 goto sendsig; 330 331#ifdef PT_SETREGS 332 case PT_SETREGS: 333 write = 1; 334#endif 335#ifdef PT_GETREGS 336 case PT_GETREGS: 337 /* write = 0 done above. */ 338#endif 339#if defined(PT_SETREGS) || defined(PT_GETREGS) 340 if (!procfs_validregs(t)) 341 return (EINVAL); 342 else { 343 iov.iov_base = SCARG(uap, addr); 344 iov.iov_len = sizeof(struct reg); 345 uio.uio_iov = &iov; 346 uio.uio_iovcnt = 1; 347 uio.uio_offset = 0; 348 uio.uio_resid = sizeof(struct reg); 349 uio.uio_segflg = UIO_USERSPACE; 350 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 351 uio.uio_procp = p; 352 return (procfs_doregs(p, t, NULL, &uio)); 353 } 354#endif 355 356#ifdef PT_SETFPREGS 357 case PT_SETFPREGS: 358 write = 1; 359#endif 360#ifdef PT_GETFPREGS 361 case PT_GETFPREGS: 362 /* write = 0 done above. */ 363#endif 364#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) 365 if (!procfs_validfpregs(t)) 366 return (EINVAL); 367 else { 368 iov.iov_base = SCARG(uap, addr); 369 iov.iov_len = sizeof(struct fpreg); 370 uio.uio_iov = &iov; 371 uio.uio_iovcnt = 1; 372 uio.uio_offset = 0; 373 uio.uio_resid = sizeof(struct fpreg); 374 uio.uio_segflg = UIO_USERSPACE; 375 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 376 uio.uio_procp = p; 377 return (procfs_dofpregs(p, t, NULL, &uio)); 378 } 379#endif 380 } 381 382#ifdef DIAGNOSTIC 383 panic("ptrace: impossible"); 384#endif 385 return 0; 386} 387 388int 389trace_req(a1) 390 struct proc *a1; 391{ 392 393 /* just return 1 to keep other parts of the system happy */ 394 return (1); 395} 396