summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux/linux_ptrace.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2002-05-19 19:35:36 +0000
committermarcel <marcel@FreeBSD.org>2002-05-19 19:35:36 +0000
commit982963acb935ae0389976769dc093c1c286a132e (patch)
treea07cc756121cb6eeb364fcc14fd0a1a0e037c41f /sys/i386/linux/linux_ptrace.c
parentb834e5849a034f05db1e154792fe387afa5771ac (diff)
downloadFreeBSD-src-982963acb935ae0389976769dc093c1c286a132e.zip
FreeBSD-src-982963acb935ae0389976769dc093c1c286a132e.tar.gz
o Fix race condition caused by doing ptrace() for permission
checking, followed by a lookup of the process. Do not call ptrace() for permission checking, but do it inline. Spotted by: rwatson o While here, copy-in arguments before we lock. This fixes a possible permanent lock. Reviewed by: rwatson
Diffstat (limited to 'sys/i386/linux/linux_ptrace.c')
-rw-r--r--sys/i386/linux/linux_ptrace.c68
1 files changed, 44 insertions, 24 deletions
diff --git a/sys/i386/linux/linux_ptrace.c b/sys/i386/linux/linux_ptrace.c
index cf1101b..536188b 100644
--- a/sys/i386/linux/linux_ptrace.c
+++ b/sys/i386/linux/linux_ptrace.c
@@ -360,11 +360,17 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
break;
}
case PTRACE_SETFPXREGS:
+#ifdef CPU_ENABLE_SSA
+ error = copyin((caddr_t)uap->data, &r.fpxreg,
+ sizeof(r.fpxreg));
+ if (error)
+ break;
+#endif
+ /* FALL THROUGH */
case PTRACE_GETFPXREGS: {
#ifdef CPU_ENABLE_SSE
struct proc *p;
struct thread *td2;
- struct fpreg *bsd_r;
if (sizeof(struct linux_pt_fpxreg) != sizeof(struct savexmm)) {
static int once = 0;
@@ -376,23 +382,38 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
break;
}
- /*
- * Use FreeBSD PT_GETFPREGS for permisson testing. If it
- * fails, PTRACE_GETFPXREGS should fail for the same reason.
- */
- bsd_r = (struct fpreg*)stackgap_alloc(&sg, sizeof(*bsd_r));
- bsd_args.req = PT_GETFPREGS;
- bsd_args.addr = (caddr_t)bsd_r;
- bsd_args.data = 0;
- error = ptrace(td, &bsd_args);
- if (error != 0)
- break;
-
if ((p = pfind(uap->pid)) == NULL) {
error = ESRCH;
break;
}
+ if ((error = p_candebug(td, p)) != 0)
+ goto fail;
+
+ /* System processes can't be debugged. */
+ if ((p->p_flag & P_SYSTEM) != 0) {
+ error = EINVAL;
+ goto fail;
+ }
+
+ /* not being traced... */
+ if ((p->p_flag & P_TRACED) == 0) {
+ error = EPERM;
+ goto fail;
+ }
+
+ /* not being traced by YOU */
+ if (p->p_pptr != td->td_proc) {
+ error = EBUSY;
+ goto fail;
+ }
+
+ /* not currently stopped */
+ if (p->p_stat != SSTOP || (p->p_flag & P_WAITED) == 0) {
+ error = EBUSY;
+ goto fail;
+ }
+
td2 = FIRST_THREAD_IN_PROC(p);
if (uap->req == PTRACE_GETFPXREGS) {
_PHOLD(p);
@@ -403,18 +424,17 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
error = copyout(&r.fpxreg, (caddr_t)uap->data,
sizeof(r.fpxreg));
} else {
- error = copyin((caddr_t)uap->data, &r.fpxreg,
- sizeof(r.fpxreg));
- if (error == 0) {
- /* clear dangerous bits exactly as Linux does*/
- r.fpxreg.mxcsr &= 0xffbf;
- _PHOLD(p);
- error = linux_proc_write_fpxregs(
- td2, &r.fpxreg);
- _PRELE(p);
- PROC_UNLOCK(p);
- }
+ /* clear dangerous bits exactly as Linux does*/
+ r.fpxreg.mxcsr &= 0xffbf;
+ _PHOLD(p);
+ error = linux_proc_write_fpxregs(td2, &r.fpxreg);
+ _PRELE(p);
+ PROC_UNLOCK(p);
}
+ break;
+
+ fail:
+ PROC_UNLOCK(p);
#else
error = EIO;
#endif
OpenPOWER on IntegriCloud