1 /* $OpenBSD: sys_process.c,v 1.17 2002/01/30 20:45:35 nordin 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/signalvar.h> 60 #include <sys/errno.h> 61 #include <sys/ptrace.h> 62 #include <sys/uio.h> 63 #include <sys/user.h> 64 65 #include <sys/mount.h> 66 #include <sys/syscallargs.h> 67 68 #include <uvm/uvm_extern.h> 69 70 #include <machine/reg.h> 71 72 #include <miscfs/procfs/procfs.h> 73 74 /* 75 * Process debugging system call. 76 */ 77 int 78 sys_ptrace(p, v, retval) 79 struct proc *p; 80 void *v; 81 register_t *retval; 82 { 83 struct sys_ptrace_args /* { 84 syscallarg(int) req; 85 syscallarg(pid_t) pid; 86 syscallarg(caddr_t) addr; 87 syscallarg(int) data; 88 } */ *uap = v; 89 struct proc *t; /* target process */ 90 struct uio uio; 91 struct iovec iov; 92 int error, write; 93 int temp; 94 95 /* "A foolish consistency..." XXX */ 96 if (SCARG(uap, req) == PT_TRACE_ME) 97 t = p; 98 else { 99 100 /* Find the process we're supposed to be operating on. */ 101 if ((t = pfind(SCARG(uap, pid))) == NULL) 102 return (ESRCH); 103 } 104 105 if ((t->p_flag & P_INEXEC) != 0) 106 return (EAGAIN); 107 108 /* Make sure we can operate on it. */ 109 switch (SCARG(uap, req)) { 110 case PT_TRACE_ME: 111 /* Saying that you're being traced is always legal. */ 112 break; 113 114 case PT_ATTACH: 115 /* 116 * You can't attach to a process if: 117 * (1) it's the process that's doing the attaching, 118 */ 119 if (t->p_pid == p->p_pid) 120 return (EINVAL); 121 122 /* 123 * (2) it's already being traced, or 124 */ 125 if (ISSET(t->p_flag, P_TRACED)) 126 return (EBUSY); 127 128 /* 129 * (3) it's not owned by you, or the last exec 130 * gave us setuid/setgid privs (unless 131 * you're root), or... 132 * 133 * [Note: once P_SUGID gets set in execve(), it stays 134 * set until the process does another execve(). Hence 135 * this prevents a setuid process which revokes it's 136 * special privilidges using setuid() from being 137 * traced. This is good security.] 138 */ 139 if ((t->p_cred->p_ruid != p->p_cred->p_ruid || 140 ISSET(t->p_flag, P_SUGID)) && 141 (error = suser(p->p_ucred, &p->p_acflag)) != 0) 142 return (error); 143 144 /* 145 * (4) ...it's init, which controls the security level 146 * of the entire system, and the system was not 147 * compiled with permanently insecure mode turned 148 * on. 149 */ 150 if ((t->p_pid == 1) && (securelevel > -1)) 151 return (EPERM); 152 break; 153 154 case PT_READ_I: 155 case PT_READ_D: 156 case PT_WRITE_I: 157 case PT_WRITE_D: 158 case PT_CONTINUE: 159 case PT_KILL: 160 case PT_DETACH: 161 #ifdef PT_STEP 162 case PT_STEP: 163 #endif 164 #ifdef PT_GETREGS 165 case PT_GETREGS: 166 #endif 167 #ifdef PT_SETREGS 168 case PT_SETREGS: 169 #endif 170 #ifdef PT_GETFPREGS 171 case PT_GETFPREGS: 172 #endif 173 #ifdef PT_SETFPREGS 174 case PT_SETFPREGS: 175 #endif 176 /* 177 * You can't do what you want to the process if: 178 * (1) It's not being traced at all, 179 */ 180 if (!ISSET(t->p_flag, P_TRACED)) 181 return (EPERM); 182 183 /* 184 * (2) it's not being traced by _you_, or 185 */ 186 if (t->p_pptr != p) 187 return (EBUSY); 188 189 /* 190 * (3) it's not currently stopped. 191 */ 192 if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED)) 193 return (EBUSY); 194 break; 195 196 default: /* It was not a legal request. */ 197 return (EINVAL); 198 } 199 200 /* Do single-step fixup if needed. */ 201 FIX_SSTEP(t); 202 203 /* Now do the operation. */ 204 write = 0; 205 *retval = 0; 206 207 switch (SCARG(uap, req)) { 208 case PT_TRACE_ME: 209 /* Just set the trace flag. */ 210 SET(t->p_flag, P_TRACED); 211 t->p_oppid = t->p_pptr->p_pid; 212 return (0); 213 214 case PT_WRITE_I: /* XXX no separate I and D spaces */ 215 case PT_WRITE_D: 216 write = 1; 217 temp = SCARG(uap, data); 218 case PT_READ_I: /* XXX no separate I and D spaces */ 219 case PT_READ_D: 220 /* write = 0 done above. */ 221 iov.iov_base = (caddr_t)&temp; 222 iov.iov_len = sizeof(int); 223 uio.uio_iov = &iov; 224 uio.uio_iovcnt = 1; 225 uio.uio_offset = (off_t)(long)SCARG(uap, addr); 226 uio.uio_resid = sizeof(int); 227 uio.uio_segflg = UIO_SYSSPACE; 228 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 229 uio.uio_procp = p; 230 error = procfs_domem(p, t, NULL, &uio); 231 if (write == 0) 232 *retval = temp; 233 return (error); 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 /* 246 * From the 4.4BSD PRM: 247 * "The data argument is taken as a signal number and the 248 * child's execution continues at location addr as if it 249 * incurred that signal. Normally the signal number will 250 * be either 0 to indicate that the signal that caused the 251 * stop should be ignored, or that value fetched out of 252 * the process's image indicating which signal caused 253 * the stop. If addr is (int *)1 then execution continues 254 * from where it stopped." 255 */ 256 257 /* Check that the data is a valid signal number or zero. */ 258 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG) 259 return (EINVAL); 260 261 PHOLD(t); 262 #ifdef PT_STEP 263 /* 264 * Arrange for a single-step, if that's requested and possible. 265 */ 266 error = process_sstep(t, SCARG(uap, req) == PT_STEP); 267 if (error) 268 goto relebad; 269 #endif 270 271 /* If the address paramter is not (int *)1, set the pc. */ 272 if ((int *)SCARG(uap, addr) != (int *)1) 273 if ((error = process_set_pc(t, SCARG(uap, addr))) != 0) 274 goto relebad; 275 PRELE(t); 276 goto sendsig; 277 278 case PT_DETACH: 279 /* 280 * From the 4.4BSD PRM: 281 * "The data argument is taken as a signal number and the 282 * child's execution continues at location addr as if it 283 * incurred that signal. Normally the signal number will 284 * be either 0 to indicate that the signal that caused the 285 * stop should be ignored, or that value fetched out of 286 * the process's image indicating which signal caused 287 * the stop. If addr is (int *)1 then execution continues 288 * from where it stopped." 289 */ 290 291 /* Check that the data is a valid signal number or zero. */ 292 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG) 293 return (EINVAL); 294 295 PHOLD(t); 296 #ifdef PT_STEP 297 /* 298 * Arrange for a single-step, if that's requested and possible. 299 */ 300 error = process_sstep(t, SCARG(uap, req) == PT_STEP); 301 if (error) 302 goto relebad; 303 #endif 304 PRELE(t); 305 306 /* give process back to original parent or init */ 307 if (t->p_oppid != t->p_pptr->p_pid) { 308 struct proc *pp; 309 310 pp = pfind(t->p_oppid); 311 proc_reparent(t, pp ? pp : initproc); 312 } 313 314 /* not being traced any more */ 315 t->p_oppid = 0; 316 CLR(t->p_flag, P_TRACED|P_WAITED); 317 318 sendsig: 319 /* Finally, deliver the requested signal (or none). */ 320 if (t->p_stat == SSTOP) { 321 t->p_xstat = SCARG(uap, data); 322 setrunnable(t); 323 } else { 324 if (SCARG(uap, data) != 0) 325 psignal(t, SCARG(uap, data)); 326 } 327 return (0); 328 329 relebad: 330 PRELE(t); 331 return (error); 332 333 case PT_KILL: 334 /* just send the process a KILL signal. */ 335 SCARG(uap, data) = SIGKILL; 336 goto sendsig; /* in PT_CONTINUE, above. */ 337 338 case PT_ATTACH: 339 /* 340 * As done in procfs: 341 * Go ahead and set the trace flag. 342 * Save the old parent (it's reset in 343 * _DETACH, and also in kern_exit.c:wait4() 344 * Reparent the process so that the tracing 345 * proc gets to see all the action. 346 * Stop the target. 347 */ 348 SET(t->p_flag, P_TRACED); 349 t->p_oppid = t->p_pptr->p_pid; 350 if (t->p_pptr != p) 351 proc_reparent(t, p); 352 SCARG(uap, data) = SIGSTOP; 353 goto sendsig; 354 355 #ifdef PT_SETREGS 356 case PT_SETREGS: 357 write = 1; 358 #endif 359 #ifdef PT_GETREGS 360 case PT_GETREGS: 361 /* write = 0 done above. */ 362 #endif 363 #if defined(PT_SETREGS) || defined(PT_GETREGS) 364 if (!procfs_validregs(t, NULL)) 365 return (EINVAL); 366 else { 367 iov.iov_base = SCARG(uap, addr); 368 iov.iov_len = sizeof(struct reg); 369 uio.uio_iov = &iov; 370 uio.uio_iovcnt = 1; 371 uio.uio_offset = 0; 372 uio.uio_resid = sizeof(struct reg); 373 uio.uio_segflg = UIO_USERSPACE; 374 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 375 uio.uio_procp = p; 376 return (procfs_doregs(p, t, NULL, &uio)); 377 } 378 #endif 379 380 #ifdef PT_SETFPREGS 381 case PT_SETFPREGS: 382 write = 1; 383 #endif 384 #ifdef PT_GETFPREGS 385 case PT_GETFPREGS: 386 /* write = 0 done above. */ 387 #endif 388 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) 389 if (!procfs_validfpregs(t, NULL)) 390 return (EINVAL); 391 else { 392 iov.iov_base = SCARG(uap, addr); 393 iov.iov_len = sizeof(struct fpreg); 394 uio.uio_iov = &iov; 395 uio.uio_iovcnt = 1; 396 uio.uio_offset = 0; 397 uio.uio_resid = sizeof(struct fpreg); 398 uio.uio_segflg = UIO_USERSPACE; 399 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 400 uio.uio_procp = p; 401 return (procfs_dofpregs(p, t, NULL, &uio)); 402 } 403 #endif 404 } 405 406 #ifdef DIAGNOSTIC 407 panic("ptrace: impossible"); 408 #endif 409 return 0; 410 } 411