Bug Summary

File:kern/sys_process.c
Warning:line 857, column 2
Value stored to 'addr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sys_process.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/kern/sys_process.c
1/* $OpenBSD: sys_process.c,v 1.89 2021/12/07 04:19:24 guenther 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. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
39 */
40
41/*
42 * References:
43 * (1) Bach's "The Design of the UNIX Operating System",
44 * (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
45 * (3) the "4.4BSD Programmer's Reference Manual" published
46 * by USENIX and O'Reilly & Associates.
47 * The 4.4BSD PRM does a reasonably good job of documenting what the various
48 * ptrace() requests should actually do, and its text is quoted several times
49 * in this file.
50 */
51
52#include <sys/param.h>
53#include <sys/systm.h>
54#include <sys/exec.h>
55#include <sys/proc.h>
56#include <sys/signalvar.h>
57#include <sys/errno.h>
58#include <sys/malloc.h>
59#include <sys/ptrace.h>
60#include <sys/uio.h>
61#include <sys/sched.h>
62#include <sys/exec_elf.h>
63
64#include <sys/mount.h>
65#include <sys/syscallargs.h>
66
67#include <uvm/uvm_extern.h>
68
69#include <machine/reg.h>
70
71#ifdef PTRACE1
72
73static inline int process_checktracestate(struct process *_curpr,
74 struct process *_tr, struct proc *_t);
75static inline struct process *process_tprfind(pid_t _tpid, struct proc **_tp);
76
77int ptrace_ctrl(struct proc *, int, pid_t, caddr_t, int);
78int ptrace_ustate(struct proc *, int, pid_t, void *, int, register_t *);
79int ptrace_kstate(struct proc *, int, pid_t, void *);
80int process_auxv_offset(struct proc *, struct process *, struct uio *);
81
82int global_ptrace; /* permit tracing of not children */
83
84
85/*
86 * Process debugging system call.
87 */
88int
89sys_ptrace(struct proc *p, void *v, register_t *retval)
90{
91 struct sys_ptrace_args /* {
92 syscallarg(int) req;
93 syscallarg(pid_t) pid;
94 syscallarg(caddr_t) addr;
95 syscallarg(int) data;
96 } */ *uap = v;
97 int req = SCARG(uap, req)((uap)->req.le.datum);
98 pid_t pid = SCARG(uap, pid)((uap)->pid.le.datum);
99 caddr_t uaddr = SCARG(uap, addr)((uap)->addr.le.datum); /* userspace */
100 void *kaddr = NULL((void *)0); /* kernelspace */
101 int data = SCARG(uap, data)((uap)->data.le.datum);
102 union {
103 struct ptrace_thread_state u_pts;
104 struct ptrace_io_desc u_piod;
105 struct ptrace_event u_pe;
106 struct ptrace_state u_ps;
107 register_t u_wcookie;
108 } u;
109 int size = 0;
110 enum { NONE, IN, IN_ALLOC, OUT, OUT_ALLOC, IN_OUT } mode;
111 int kstate = 0;
112 int error;
113
114 *retval = 0;
115
116 /* Figure out what sort of copyin/out operations we'll do */
117 switch (req) {
118 case PT_TRACE_ME0:
119 case PT_CONTINUE7:
120 case PT_KILL8:
121 case PT_ATTACH9:
122 case PT_DETACH10:
123#ifdef PT_STEP(32 + 0)
124 case PT_STEP(32 + 0):
125#endif
126 /* control operations do no copyin/out; dispatch directly */
127 return ptrace_ctrl(p, req, pid, uaddr, data);
128
129 case PT_READ_I1:
130 case PT_READ_D2:
131 case PT_WRITE_I4:
132 case PT_WRITE_D5:
133 mode = NONE;
134 break;
135 case PT_IO11:
136 mode = IN_OUT;
137 size = sizeof u.u_piod;
138 data = size; /* suppress the data == size check */
139 break;
140 case PT_GET_THREAD_FIRST15:
141 mode = OUT;
142 size = sizeof u.u_pts;
143 kstate = 1;
144 break;
145 case PT_GET_THREAD_NEXT16:
146 mode = IN_OUT;
147 size = sizeof u.u_pts;
148 kstate = 1;
149 break;
150 case PT_GET_EVENT_MASK13:
151 mode = OUT;
152 size = sizeof u.u_pe;
153 kstate = 1;
154 break;
155 case PT_SET_EVENT_MASK12:
156 mode = IN;
157 size = sizeof u.u_pe;
158 kstate = 1;
159 break;
160 case PT_GET_PROCESS_STATE14:
161 mode = OUT;
162 size = sizeof u.u_ps;
163 kstate = 1;
164 break;
165 case PT_GETREGS(32 + 1):
166 mode = OUT_ALLOC;
167 size = sizeof(struct reg);
168 break;
169 case PT_SETREGS(32 + 2):
170 mode = IN_ALLOC;
171 size = sizeof(struct reg);
172 break;
173#ifdef PT_GETFPREGS(32 + 3)
174 case PT_GETFPREGS(32 + 3):
175 mode = OUT_ALLOC;
176 size = sizeof(struct fpreg);
177 break;
178#endif
179#ifdef PT_SETFPREGS(32 + 4)
180 case PT_SETFPREGS(32 + 4):
181 mode = IN_ALLOC;
182 size = sizeof(struct fpreg);
183 break;
184#endif
185#ifdef PT_GETXMMREGS
186 case PT_GETXMMREGS:
187 mode = OUT_ALLOC;
188 size = sizeof(struct xmmregs);
189 break;
190#endif
191#ifdef PT_SETXMMREGS
192 case PT_SETXMMREGS:
193 mode = IN_ALLOC;
194 size = sizeof(struct xmmregs);
195 break;
196#endif
197#ifdef PT_WCOOKIE
198 case PT_WCOOKIE:
199 mode = OUT;
200 size = sizeof u.u_wcookie;
201 data = size; /* suppress the data == size check */
202 break;
203#endif
204 default:
205 return EINVAL22;
206 }
207
208
209 /* Now do any copyin()s and allocations in a consistent manner */
210 switch (mode) {
211 case NONE:
212 kaddr = uaddr;
213 break;
214 case IN:
215 case IN_OUT:
216 case OUT:
217 KASSERT(size <= sizeof u)((size <= sizeof u) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_process.c"
, 217, "size <= sizeof u"))
;
218 if (data != size)
219 return EINVAL22;
220 if (mode == OUT)
221 memset(&u, 0, size)__builtin_memset((&u), (0), (size));
222 else { /* IN or IN_OUT */
223 if ((error = copyin(uaddr, &u, size)))
224 return error;
225 }
226 kaddr = &u;
227 break;
228 case IN_ALLOC:
229 kaddr = malloc(size, M_TEMP127, M_WAITOK0x0001);
230 if ((error = copyin(uaddr, kaddr, size))) {
231 free(kaddr, M_TEMP127, size);
232 return error;
233 }
234 break;
235 case OUT_ALLOC:
236 kaddr = malloc(size, M_TEMP127, M_WAITOK0x0001 | M_ZERO0x0008);
237 break;
238 }
239
240 if (kstate)
241 error = ptrace_kstate(p, req, pid, kaddr);
242 else
243 error = ptrace_ustate(p, req, pid, kaddr, data, retval);
244
245 /* Do any copyout()s and frees */
246 if (error == 0) {
247 switch (mode) {
248 case NONE:
249 case IN:
250 case IN_ALLOC:
251 break;
252 case IN_OUT:
253 case OUT:
254 error = copyout(&u, uaddr, size);
255 if (req == PT_IO11) {
256 /* historically, errors here are ignored */
257 error = 0;
258 }
259 break;
260 case OUT_ALLOC:
261 error = copyout(kaddr, uaddr, size);
262 break;
263 }
264 }
265
266 if (mode == IN_ALLOC || mode == OUT_ALLOC)
267 free(kaddr, M_TEMP127, size);
268 return error;
269}
270
271/*
272 * ptrace control requests: attach, detach, continue, kill, single-step, etc
273 */
274int
275ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data)
276{
277 struct proc *t; /* target thread */
278 struct process *tr; /* target process */
279 int error = 0;
280 int s;
281
282 switch (req) {
283 case PT_TRACE_ME0:
284 /* Just set the trace flag. */
285 tr = p->p_p;
286 if (ISSET(tr->ps_flags, PS_TRACED)((tr->ps_flags) & (0x00000200)))
287 return EBUSY16;
288 atomic_setbits_intx86_atomic_setbits_u32(&tr->ps_flags, PS_TRACED0x00000200);
289 tr->ps_oppid = tr->ps_pptr->ps_pid;
290 if (tr->ps_ptstat == NULL((void *)0))
291 tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat),
292 M_SUBPROC42, M_WAITOK0x0001);
293 memset(tr->ps_ptstat, 0, sizeof(*tr->ps_ptstat))__builtin_memset((tr->ps_ptstat), (0), (sizeof(*tr->ps_ptstat
)))
;
294 return 0;
295
296 /* calls that only operate on the PID */
297 case PT_KILL8:
298 case PT_ATTACH9:
299 case PT_DETACH10:
300 /* Find the process we're supposed to be operating on. */
301 if ((tr = prfind(pid)) == NULL((void *)0)) {
302 error = ESRCH3;
303 goto fail;
304 }
305 t = TAILQ_FIRST(&tr->ps_threads)((&tr->ps_threads)->tqh_first);
306 break;
307
308 /* calls that accept a PID or a thread ID */
309 case PT_CONTINUE7:
310#ifdef PT_STEP(32 + 0)
311 case PT_STEP(32 + 0):
312#endif
313 if ((tr = process_tprfind(pid, &t)) == NULL((void *)0)) {
314 error = ESRCH3;
315 goto fail;
316 }
317 break;
318 }
319
320 /* Check permissions/state */
321 if (req != PT_ATTACH9) {
322 /* Check that the data is a valid signal number or zero. */
323 if (req != PT_KILL8 && (data < 0 || data >= NSIG33)) {
324 error = EINVAL22;
325 goto fail;
326 }
327
328 /* Most operations require the target to already be traced */
329 if ((error = process_checktracestate(p->p_p, tr, t)))
330 goto fail;
331
332 /* Do single-step fixup if needed. */
333 FIX_SSTEP(t);
334 } else {
335 /*
336 * PT_ATTACH is the opposite; you can't attach to a process if:
337 * (1) it's the process that's doing the attaching,
338 */
339 if (tr == p->p_p) {
340 error = EINVAL22;
341 goto fail;
342 }
343
344 /*
345 * (2) it's a system process
346 */
347 if (ISSET(tr->ps_flags, PS_SYSTEM)((tr->ps_flags) & (0x00010000))) {
348 error = EPERM1;
349 goto fail;
350 }
351
352 /*
353 * (3) it's already being traced, or
354 */
355 if (ISSET(tr->ps_flags, PS_TRACED)((tr->ps_flags) & (0x00000200))) {
356 error = EBUSY16;
357 goto fail;
358 }
359
360 /*
361 * (4) it's in the middle of execve(2)
362 */
363 if (ISSET(tr->ps_flags, PS_INEXEC)((tr->ps_flags) & (0x00000004))) {
364 error = EAGAIN35;
365 goto fail;
366 }
367
368 /*
369 * (5) it's not owned by you, or the last exec
370 * gave us setuid/setgid privs (unless
371 * you're root), or...
372 *
373 * [Note: once PS_SUGID or PS_SUGIDEXEC gets set in
374 * execve(), they stay set until the process does
375 * another execve(). Hence this prevents a setuid
376 * process which revokes its special privileges using
377 * setuid() from being traced. This is good security.]
378 */
379 if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
380 ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)((tr->ps_flags) & (0x00000020 | 0x00000010))) &&
381 (error = suser(p)) != 0)
382 goto fail;
383
384 /*
385 * (5.5) it's not a child of the tracing process.
386 */
387 if (global_ptrace == 0 && !inferior(tr, p->p_p) &&
388 (error = suser(p)) != 0)
389 goto fail;
390
391 /*
392 * (6) ...it's init, which controls the security level
393 * of the entire system, and the system was not
394 * compiled with permanently insecure mode turned
395 * on.
396 */
397 if ((tr->ps_pid == 1) && (securelevel > -1)) {
398 error = EPERM1;
399 goto fail;
400 }
401
402 /*
403 * (7) it's an ancestor of the current process and
404 * not init (because that would create a loop in
405 * the process graph).
406 */
407 if (tr->ps_pid != 1 && inferior(p->p_p, tr)) {
408 error = EINVAL22;
409 goto fail;
410 }
411 }
412
413 switch (req) {
414
415#ifdef PT_STEP(32 + 0)
416 case PT_STEP(32 + 0):
417 /*
418 * From the 4.4BSD PRM:
419 * "Execution continues as in request PT_CONTINUE; however
420 * as soon as possible after execution of at least one
421 * instruction, execution stops again. [ ... ]"
422 */
423#endif
424 case PT_CONTINUE7:
425 /*
426 * From the 4.4BSD PRM:
427 * "The data argument is taken as a signal number and the
428 * child's execution continues at location addr as if it
429 * incurred that signal. Normally the signal number will
430 * be either 0 to indicate that the signal that caused the
431 * stop should be ignored, or that value fetched out of
432 * the process's image indicating which signal caused
433 * the stop. If addr is (int *)1 then execution continues
434 * from where it stopped."
435 */
436
437 if (pid < THREAD_PID_OFFSET100000 && tr->ps_single)
438 t = tr->ps_single;
439
440 /* If the address parameter is not (int *)1, set the pc. */
441 if ((int *)addr != (int *)1)
442 if ((error = process_set_pc(t, addr)) != 0)
443 goto fail;
444
445#ifdef PT_STEP(32 + 0)
446 /*
447 * Arrange for a single-step, if that's requested and possible.
448 */
449 error = process_sstep(t, req == PT_STEP(32 + 0));
450 if (error)
451 goto fail;
452#endif
453 goto sendsig;
454
455 case PT_DETACH10:
456 /*
457 * From the 4.4BSD PRM:
458 * "The data argument is taken as a signal number and the
459 * child's execution continues at location addr as if it
460 * incurred that signal. Normally the signal number will
461 * be either 0 to indicate that the signal that caused the
462 * stop should be ignored, or that value fetched out of
463 * the process's image indicating which signal caused
464 * the stop. If addr is (int *)1 then execution continues
465 * from where it stopped."
466 */
467
468 if (pid < THREAD_PID_OFFSET100000 && tr->ps_single)
469 t = tr->ps_single;
470
471#ifdef PT_STEP(32 + 0)
472 /*
473 * Stop single stepping.
474 */
475 error = process_sstep(t, 0);
476 if (error)
477 goto fail;
478#endif
479
480 process_untrace(tr);
481 atomic_clearbits_intx86_atomic_clearbits_u32(&tr->ps_flags, PS_WAITED0x00000400);
482
483 sendsig:
484 memset(tr->ps_ptstat, 0, sizeof(*tr->ps_ptstat))__builtin_memset((tr->ps_ptstat), (0), (sizeof(*tr->ps_ptstat
)))
;
485
486 /* Finally, deliver the requested signal (or none). */
487 if (t->p_stat == SSTOP4) {
488 tr->ps_xsig = data;
489 SCHED_LOCK(s)do { s = splraise(0xc); __mp_lock(&sched_lock); } while (
0)
;
490 setrunnable(t);
491 SCHED_UNLOCK(s)do { __mp_unlock(&sched_lock); spllower(s); } while ( 0);
492 } else {
493 if (data != 0)
494 psignal(t, data);
495 }
496 break;
497
498 case PT_KILL8:
499 if (pid < THREAD_PID_OFFSET100000 && tr->ps_single)
500 t = tr->ps_single;
501
502 /* just send the process a KILL signal. */
503 data = SIGKILL9;
504 goto sendsig; /* in PT_CONTINUE, above. */
505
506 case PT_ATTACH9:
507 /*
508 * As was done in procfs:
509 * Go ahead and set the trace flag.
510 * Save the old parent (it's reset in
511 * _DETACH, and also in kern_exit.c:wait4()
512 * Reparent the process so that the tracing
513 * proc gets to see all the action.
514 * Stop the target.
515 */
516 atomic_setbits_intx86_atomic_setbits_u32(&tr->ps_flags, PS_TRACED0x00000200);
517 tr->ps_oppid = tr->ps_pptr->ps_pid;
518 process_reparent(tr, p->p_p);
519 if (tr->ps_ptstat == NULL((void *)0))
520 tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat),
521 M_SUBPROC42, M_WAITOK0x0001);
522 data = SIGSTOP17;
523 goto sendsig;
524 default:
525 KASSERTMSG(0, "%s: unhandled request %d", __func__, req)((0) ? (void)0 : panic("kernel %sassertion \"%s\" failed: file \"%s\", line %d"
" " "%s: unhandled request %d", "diagnostic ", "0", "/usr/src/sys/kern/sys_process.c"
, 525, __func__, req))
;
526 break;
527 }
528
529fail:
530 return error;
531}
532
533/*
534 * ptrace kernel-state requests: thread list, event mask, process state
535 */
536int
537ptrace_kstate(struct proc *p, int req, pid_t pid, void *addr)
538{
539 struct process *tr; /* target process */
540 struct ptrace_event *pe = addr;
541 int error;
542
543 KASSERT((p->p_flag & P_SYSTEM) == 0)(((p->p_flag & 0x00000200) == 0) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/kern/sys_process.c", 543, "(p->p_flag & P_SYSTEM) == 0"
))
;
544
545 /* Find the process we're supposed to be operating on. */
546 if ((tr = prfind(pid)) == NULL((void *)0))
547 return ESRCH3;
548
549 if ((error = process_checktracestate(p->p_p, tr, NULL((void *)0))))
550 return error;
551
552 switch (req) {
553 case PT_GET_THREAD_FIRST15:
554 case PT_GET_THREAD_NEXT16:
555 {
556 struct ptrace_thread_state *pts = addr;
557 struct proc *t;
558
559 if (req == PT_GET_THREAD_NEXT16) {
560 t = tfind(pts->pts_tid - THREAD_PID_OFFSET100000);
561 if (t == NULL((void *)0) || ISSET(t->p_flag, P_WEXIT)((t->p_flag) & (0x00002000)))
562 return ESRCH3;
563 if (t->p_p != tr)
564 return EINVAL22;
565 t = TAILQ_NEXT(t, p_thr_link)((t)->p_thr_link.tqe_next);
566 } else {
567 t = TAILQ_FIRST(&tr->ps_threads)((&tr->ps_threads)->tqh_first);
568 }
569
570 if (t == NULL((void *)0))
571 pts->pts_tid = -1;
572 else
573 pts->pts_tid = t->p_tid + THREAD_PID_OFFSET100000;
574 return 0;
575 }
576 }
577
578 switch (req) {
579 case PT_GET_EVENT_MASK13:
580 pe->pe_set_event = tr->ps_ptmask;
581 break;
582 case PT_SET_EVENT_MASK12:
583 tr->ps_ptmask = pe->pe_set_event;
584 break;
585 case PT_GET_PROCESS_STATE14:
586 if (tr->ps_single)
587 tr->ps_ptstat->pe_tid =
588 tr->ps_single->p_tid + THREAD_PID_OFFSET100000;
589 memcpy(addr, tr->ps_ptstat, sizeof *tr->ps_ptstat)__builtin_memcpy((addr), (tr->ps_ptstat), (sizeof *tr->
ps_ptstat))
;
590 break;
591 default:
592 KASSERTMSG(0, "%s: unhandled request %d", __func__, req)((0) ? (void)0 : panic("kernel %sassertion \"%s\" failed: file \"%s\", line %d"
" " "%s: unhandled request %d", "diagnostic ", "0", "/usr/src/sys/kern/sys_process.c"
, 592, __func__, req))
;
593 break;
594 }
595
596 return 0;
597}
598
599/*
600 * ptrace user-state requests: memory access, registers, stack cookie
601 */
602int
603ptrace_ustate(struct proc *p, int req, pid_t pid, void *addr, int data,
604 register_t *retval)
605{
606 struct proc *t; /* target thread */
607 struct process *tr; /* target process */
608 struct uio uio;
609 struct iovec iov;
610 int error, write;
611 int temp = 0;
612
613 KASSERT((p->p_flag & P_SYSTEM) == 0)(((p->p_flag & 0x00000200) == 0) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/kern/sys_process.c", 613, "(p->p_flag & P_SYSTEM) == 0"
))
;
614
615 /* Accept either PID or TID */
616 if ((tr = process_tprfind(pid, &t)) == NULL((void *)0))
617 return ESRCH3;
618
619 if ((error = process_checktracestate(p->p_p, tr, t)))
620 return error;
621
622 FIX_SSTEP(t);
623
624 /* Now do the operation. */
625 write = 0;
626
627 if ((error = process_checkioperm(p, tr)) != 0)
628 return error;
629
630 switch (req) {
631 case PT_WRITE_I4: /* XXX no separate I and D spaces */
632 case PT_WRITE_D5:
633 write = 1;
634 temp = data;
635 case PT_READ_I1: /* XXX no separate I and D spaces */
636 case PT_READ_D2:
637 /* write = 0 done above. */
638 iov.iov_base = (caddr_t)&temp;
639 iov.iov_len = sizeof(int);
640 uio.uio_iov = &iov;
641 uio.uio_iovcnt = 1;
642 uio.uio_offset = (off_t)(vaddr_t)addr;
643 uio.uio_resid = sizeof(int);
644 uio.uio_segflg = UIO_SYSSPACE;
645 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
646 uio.uio_procp = p;
647 error = process_domem(p, tr, &uio, write ? PT_WRITE_I4 :
648 PT_READ_I1);
649 if (write == 0)
650 *retval = temp;
651 return error;
652
653 case PT_IO11:
654 {
655 struct ptrace_io_desc *piod = addr;
656
657 iov.iov_base = piod->piod_addr;
658 iov.iov_len = piod->piod_len;
659 uio.uio_iov = &iov;
660 uio.uio_iovcnt = 1;
661 uio.uio_offset = (off_t)(vaddr_t)piod->piod_offs;
662 uio.uio_resid = piod->piod_len;
663 uio.uio_segflg = UIO_USERSPACE;
664 uio.uio_procp = p;
665 switch (piod->piod_op) {
666 case PIOD_READ_I3:
667 req = PT_READ_I1;
668 uio.uio_rw = UIO_READ;
669 break;
670 case PIOD_READ_D1:
671 req = PT_READ_D2;
672 uio.uio_rw = UIO_READ;
673 break;
674 case PIOD_WRITE_I4:
675 req = PT_WRITE_I4;
676 uio.uio_rw = UIO_WRITE;
677 break;
678 case PIOD_WRITE_D2:
679 req = PT_WRITE_D5;
680 uio.uio_rw = UIO_WRITE;
681 break;
682 case PIOD_READ_AUXV5:
683 req = PT_READ_D2;
684 uio.uio_rw = UIO_READ;
685 temp = ELF_AUX_WORDS(sizeof(Aux64Info) * 9 / sizeof(char *)) * sizeof(char *);
686 if (uio.uio_offset > temp)
687 return EIO5;
688 if (uio.uio_resid > temp - uio.uio_offset)
689 uio.uio_resid = temp - uio.uio_offset;
690 piod->piod_len = iov.iov_len = uio.uio_resid;
691 error = process_auxv_offset(p, tr, &uio);
692 if (error)
693 return error;
694 break;
695 default:
696 return EINVAL22;
697 }
698 error = process_domem(p, tr, &uio, req);
699 piod->piod_len -= uio.uio_resid;
700 return error;
701 }
702
703 case PT_SETREGS(32 + 2):
704 return process_write_regs(t, addr);
705 case PT_GETREGS(32 + 1):
706 return process_read_regs(t, addr);
707
708#ifdef PT_SETFPREGS(32 + 4)
709 case PT_SETFPREGS(32 + 4):
710 return process_write_fpregs(t, addr);
711#endif
712#ifdef PT_SETFPREGS(32 + 4)
713 case PT_GETFPREGS(32 + 3):
714 return process_read_fpregs(t, addr);
715#endif
716#ifdef PT_SETXMMREGS
717 case PT_SETXMMREGS:
718 return process_write_xmmregs(t, addr);
719#endif
720#ifdef PT_SETXMMREGS
721 case PT_GETXMMREGS:
722 return process_read_xmmregs(t, addr);
723#endif
724#ifdef PT_WCOOKIE
725 case PT_WCOOKIE:
726 *(register_t *)addr = process_get_wcookie(t);
727 return 0;
728#endif
729 default:
730 KASSERTMSG(0, "%s: unhandled request %d", __func__, req)((0) ? (void)0 : panic("kernel %sassertion \"%s\" failed: file \"%s\", line %d"
" " "%s: unhandled request %d", "diagnostic ", "0", "/usr/src/sys/kern/sys_process.c"
, 730, __func__, req))
;
731 break;
732 }
733
734 return 0;
735}
736
737
738/*
739 * Helper for doing "it could be a PID or TID" lookup. On failure
740 * returns NULL; on success returns the selected process and sets *tp
741 * to an appropriate thread in that process.
742 */
743static inline struct process *
744process_tprfind(pid_t tpid, struct proc **tp)
745{
746 if (tpid > THREAD_PID_OFFSET100000) {
747 struct proc *t = tfind(tpid - THREAD_PID_OFFSET100000);
748
749 if (t == NULL((void *)0))
750 return NULL((void *)0);
751 *tp = t;
752 return t->p_p;
753 } else {
754 struct process *tr = prfind(tpid);
755
756 if (tr == NULL((void *)0))
757 return NULL((void *)0);
758 *tp = TAILQ_FIRST(&tr->ps_threads)((&tr->ps_threads)->tqh_first);
759 return tr;
760 }
761}
762
763
764/*
765 * Check whether 'tr' is currently traced by 'curpr' and in a state
766 * to be manipulated. If 't' is supplied then it must be stopped and
767 * waited for.
768 */
769static inline int
770process_checktracestate(struct process *curpr, struct process *tr,
771 struct proc *t)
772{
773 /*
774 * You can't do what you want to the process if:
775 * (1) It's not being traced at all,
776 */
777 if (!ISSET(tr->ps_flags, PS_TRACED)((tr->ps_flags) & (0x00000200)))
778 return EPERM1;
779
780 /*
781 * (2) it's not being traced by _you_, or
782 */
783 if (tr->ps_pptr != curpr)
784 return EBUSY16;
785
786 /*
787 * (3) it's in the middle of execve(2)
788 */
789 if (ISSET(tr->ps_flags, PS_INEXEC)((tr->ps_flags) & (0x00000004)))
790 return EAGAIN35;
791
792 /*
793 * (4) if a thread was specified and it's not currently stopped.
794 */
795 if (t != NULL((void *)0) &&
796 (t->p_stat != SSTOP4 || !ISSET(tr->ps_flags, PS_WAITED)((tr->ps_flags) & (0x00000400))))
797 return EBUSY16;
798
799 return 0;
800}
801
802
803/*
804 * Check if a process is allowed to fiddle with the memory of another.
805 *
806 * p = tracer
807 * tr = tracee
808 *
809 * 1. You can't attach to a process not owned by you or one that has raised
810 * its privileges.
811 * 1a. ...unless you are root.
812 *
813 * 2. init is always off-limits because it can control the securelevel.
814 * 2a. ...unless securelevel is permanently set to insecure.
815 *
816 * 3. Processes that are in the process of doing an exec() are always
817 * off-limits because of the can of worms they are. Just wait a
818 * second.
819 */
820int
821process_checkioperm(struct proc *p, struct process *tr)
822{
823 int error;
824
825 if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
826 ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)((tr->ps_flags) & (0x00000020 | 0x00000010))) &&
827 (error = suser(p)) != 0)
828 return (error);
829
830 if ((tr->ps_pid == 1) && (securelevel > -1))
831 return (EPERM1);
832
833 if (ISSET(tr->ps_flags, PS_INEXEC)((tr->ps_flags) & (0x00000004)))
834 return (EAGAIN35);
835
836 return (0);
837}
838
839int
840process_domem(struct proc *curp, struct process *tr, struct uio *uio, int req)
841{
842 struct vmspace *vm;
843 int error;
844 vaddr_t addr;
845 vsize_t len;
846
847 len = uio->uio_resid;
848 if (len == 0)
849 return 0;
850
851 if ((error = process_checkioperm(curp, tr)) != 0)
852 return error;
853
854 vm = tr->ps_vmspace;
855 if ((tr->ps_flags & PS_EXITING0x00000008) || (vm->vm_refcnt < 1))
856 return EFAULT14;
857 addr = uio->uio_offset;
Value stored to 'addr' is never read
858
859 uvmspace_addref(vm);
860
861 error = uvm_io(&vm->vm_map, uio,
862 (uio->uio_rw == UIO_WRITE) ? UVM_IO_FIXPROT0x01 : 0);
863
864 uvmspace_free(vm);
865
866 if (error == 0 && req == PT_WRITE_I4)
867 pmap_proc_iflush(tr, addr, len);
868
869 return error;
870}
871
872int
873process_auxv_offset(struct proc *curp, struct process *tr, struct uio *uiop)
874{
875 struct vmspace *vm;
876 struct ps_strings pss;
877 struct iovec iov;
878 struct uio uio;
879 int error;
880
881 iov.iov_base = &pss;
882 iov.iov_len = sizeof(pss);
883 uio.uio_iov = &iov;
884 uio.uio_iovcnt = 1;
885 uio.uio_offset = (off_t)tr->ps_strings;
886 uio.uio_resid = sizeof(pss);
887 uio.uio_segflg = UIO_SYSSPACE;
888 uio.uio_rw = UIO_READ;
889 uio.uio_procp = curp;
890
891 vm = tr->ps_vmspace;
892 if ((tr->ps_flags & PS_EXITING0x00000008) || (vm->vm_refcnt < 1))
893 return EFAULT14;
894
895 uvmspace_addref(vm);
896 error = uvm_io(&vm->vm_map, &uio, 0);
897 uvmspace_free(vm);
898
899 if (error != 0)
900 return error;
901
902 if (pss.ps_envstr == NULL((void *)0))
903 return EIO5;
904
905 uiop->uio_offset += (off_t)(vaddr_t)(pss.ps_envstr + pss.ps_nenvstr + 1);
906#ifdef MACHINE_STACK_GROWS_UP
907 if (uiop->uio_offset < (off_t)tr->ps_strings)
908 return EIO5;
909#else
910 if (uiop->uio_offset > (off_t)tr->ps_strings)
911 return EIO5;
912 if ((uiop->uio_offset + uiop->uio_resid) > (off_t)tr->ps_strings)
913 uiop->uio_resid = (off_t)tr->ps_strings - uiop->uio_offset;
914#endif
915
916 return 0;
917}
918#endif