Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Feb 2010 11:37:38 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r203608 - in stable/8/sys: amd64/amd64 amd64/ia32 i386/i386 kern sys
Message-ID:  <201002071137.o17BbcxP008531@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Feb  7 11:37:38 2010
New Revision: 203608
URL: http://svn.freebsd.org/changeset/base/203608

Log:
  MFC r202882:
  For i386, amd64 and ia32 on amd64 MD syscall(), reread syscall number
  and arguments after ptracestop(), if debugger modified anything in the
  process environment.

Modified:
  stable/8/sys/amd64/amd64/trap.c
  stable/8/sys/amd64/ia32/ia32_syscall.c
  stable/8/sys/i386/i386/trap.c
  stable/8/sys/kern/sys_process.c
  stable/8/sys/sys/proc.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/amd64/amd64/trap.c
==============================================================================
--- stable/8/sys/amd64/amd64/trap.c	Sun Feb  7 10:51:17 2010	(r203607)
+++ stable/8/sys/amd64/amd64/trap.c	Sun Feb  7 11:37:38 2010	(r203608)
@@ -884,95 +884,131 @@ dblfault_handler(struct trapframe *frame
 	panic("double fault");
 }
 
-/*
- *	syscall -	system call request C handler
- *
- *	A system call is essentially treated as a trap.
- */
-void
-syscall(struct trapframe *frame)
-{
-	caddr_t params;
+struct syscall_args {
+	u_int code;
 	struct sysent *callp;
-	struct thread *td = curthread;
-	struct proc *p = td->td_proc;
-	register_t orig_tf_rflags;
-	int error;
-	int narg;
 	register_t args[8];
 	register_t *argp;
-	u_int code;
-	int reg, regcnt;
-	ksiginfo_t ksi;
-
-	PCPU_INC(cnt.v_syscall);
+	int narg;
+};
 
-#ifdef DIAGNOSTIC
-	if (ISPL(frame->tf_cs) != SEL_UPL) {
-		panic("syscall");
-		/* NOT REACHED */
-	}
-#endif
+static int
+fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+	struct proc *p;
+	struct trapframe *frame;
+	caddr_t params;
+	int reg, regcnt, error;
 
+	p = td->td_proc;
+	frame = td->td_frame;
 	reg = 0;
 	regcnt = 6;
-	td->td_pticks = 0;
-	td->td_frame = frame;
-	if (td->td_ucred != p->p_ucred) 
-		cred_update_thread(td);
+
 	params = (caddr_t)frame->tf_rsp + sizeof(register_t);
-	code = frame->tf_rax;
-	orig_tf_rflags = frame->tf_rflags;
+	sa->code = frame->tf_rax;
 
 	if (p->p_sysent->sv_prepsyscall) {
-		(*p->p_sysent->sv_prepsyscall)(frame, (int *)args, &code, &params);
+		(*p->p_sysent->sv_prepsyscall)(frame, (int *)sa->args,
+		    &sa->code, &params);
 	} else {
-		if (code == SYS_syscall || code == SYS___syscall) {
-			code = frame->tf_rdi;
+		if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
+			sa->code = frame->tf_rdi;
 			reg++;
 			regcnt--;
 		}
 	}
-
  	if (p->p_sysent->sv_mask)
- 		code &= p->p_sysent->sv_mask;
+ 		sa->code &= p->p_sysent->sv_mask;
 
- 	if (code >= p->p_sysent->sv_size)
- 		callp = &p->p_sysent->sv_table[0];
+ 	if (sa->code >= p->p_sysent->sv_size)
+ 		sa->callp = &p->p_sysent->sv_table[0];
   	else
- 		callp = &p->p_sysent->sv_table[code];
+ 		sa->callp = &p->p_sysent->sv_table[sa->code];
 
-	narg = callp->sy_narg;
-	KASSERT(narg <= sizeof(args) / sizeof(args[0]),
+	sa->narg = sa->callp->sy_narg;
+	KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
 	    ("Too many syscall arguments!"));
 	error = 0;
-	argp = &frame->tf_rdi;
-	argp += reg;
-	bcopy(argp, args, sizeof(args[0]) * regcnt);
-	if (narg > regcnt) {
+	sa->argp = &frame->tf_rdi;
+	sa->argp += reg;
+	bcopy(sa->argp, sa->args, sizeof(sa->args[0]) * regcnt);
+	if (sa->narg > regcnt) {
 		KASSERT(params != NULL, ("copyin args with no params!"));
-		error = copyin(params, &args[regcnt],
-	    		(narg - regcnt) * sizeof(args[0]));
+		error = copyin(params, &sa->args[regcnt],
+	    	    (sa->narg - regcnt) * sizeof(sa->args[0]));
 	}
-	argp = &args[0];
+	sa->argp = &sa->args[0];
 
+	/*
+	 * This may result in two records if debugger modified
+	 * registers or memory during sleep at stop/ptrace point.
+	 */
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSCALL))
-		ktrsyscall(code, narg, argp);
+		ktrsyscall(sa->code, sa->narg, sa->argp);
 #endif
+	return (error);
+}
 
-	CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
-	    td->td_proc->p_pid, td->td_name, code);
+/*
+ *	syscall -	system call request C handler
+ *
+ *	A system call is essentially treated as a trap.
+ */
+void
+syscall(struct trapframe *frame)
+{
+	struct thread *td;
+	struct proc *p;
+	struct syscall_args sa;
+	register_t orig_tf_rflags;
+	int error;
+	ksiginfo_t ksi;
 
+	PCPU_INC(cnt.v_syscall);
+	td = curthread;
+	p = td->td_proc;
 	td->td_syscalls++;
 
+#ifdef DIAGNOSTIC
+	if (ISPL(frame->tf_cs) != SEL_UPL) {
+		panic("syscall");
+		/* NOT REACHED */
+	}
+#endif
+
+	td->td_pticks = 0;
+	td->td_frame = frame;
+	if (td->td_ucred != p->p_ucred) 
+		cred_update_thread(td);
+	orig_tf_rflags = frame->tf_rflags;
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &= ~TDB_USERWR;
+		PROC_UNLOCK(p);
+	}
+	error = fetch_syscall_args(td, &sa);
+
+	CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
+	    td->td_proc->p_pid, td->td_name, sa.code);
+
 	if (error == 0) {
 		td->td_retval[0] = 0;
 		td->td_retval[1] = frame->tf_rdx;
 
-		STOPEVENT(p, S_SCE, narg);
-
+		STOPEVENT(p, S_SCE, sa.narg);
 		PTRACESTOP_SC(p, td, S_PT_SCE);
+		if (td->td_dbgflags & TDB_USERWR) {
+			/*
+			 * Reread syscall number and arguments if
+			 * debugger modified registers or memory.
+			 */
+			error = fetch_syscall_args(td, &sa);
+			if (error != 0)
+				goto retval;
+			td->td_retval[1] = frame->tf_rdx;
+		}
 
 #ifdef KDTRACE_HOOKS
 		/*
@@ -980,13 +1016,13 @@ syscall(struct trapframe *frame)
 		 * callback and if there is a probe active for the
 		 * syscall 'entry', process the probe.
 		 */
-		if (systrace_probe_func != NULL && callp->sy_entry != 0)
-			(*systrace_probe_func)(callp->sy_entry, code, callp,
-			    args);
+		if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
+			(*systrace_probe_func)(sa.callp->sy_entry, sa.code,
+			    sa.callp, sa.args);
 #endif
 
-		AUDIT_SYSCALL_ENTER(code, td);
-		error = (*callp->sy_call)(td, argp);
+		AUDIT_SYSCALL_ENTER(sa.code, td);
+		error = (*sa.callp->sy_call)(td, sa.argp);
 		AUDIT_SYSCALL_EXIT(error, td);
 
 		/* Save the latest error return value. */
@@ -998,12 +1034,12 @@ syscall(struct trapframe *frame)
 		 * callback and if there is a probe active for the
 		 * syscall 'return', process the probe.
 		 */
-		if (systrace_probe_func != NULL && callp->sy_return != 0)
-			(*systrace_probe_func)(callp->sy_return, code, callp,
-			    args);
+		if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
+			(*systrace_probe_func)(sa.callp->sy_return, sa.code,
+			    sa.callp, sa.args);
 #endif
 	}
-
+ retval:
 	cpu_set_syscall_retval(td, error);
 
 	/*
@@ -1022,14 +1058,16 @@ syscall(struct trapframe *frame)
 	 * Check for misbehavior.
 	 */
 	WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     syscallnames[sa.code] : "???");
 	KASSERT(td->td_critnest == 0,
 	    ("System call %s returning in a critical section",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     syscallnames[sa.code] : "???"));
 	KASSERT(td->td_locks == 0,
 	    ("System call %s returning with %d locks held",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
-	    td->td_locks));
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     syscallnames[sa.code] : "???", td->td_locks));
 
 	/*
 	 * Handle reschedule and other end-of-syscall issues
@@ -1037,11 +1075,11 @@ syscall(struct trapframe *frame)
 	userret(td, frame);
 
 	CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
-	    td->td_proc->p_pid, td->td_name, code);
+	    td->td_proc->p_pid, td->td_name, sa.code);
 
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSRET))
-		ktrsysret(code, error, td->td_retval[0]);
+		ktrsysret(sa.code, error, td->td_retval[0]);
 #endif
 
 	/*
@@ -1049,7 +1087,7 @@ syscall(struct trapframe *frame)
 	 * register set.  If we ever support an emulation where this
 	 * is not the case, this code will need to be revisited.
 	 */
-	STOPEVENT(p, S_SCX, code);
+	STOPEVENT(p, S_SCX, sa.code);
 
 	PTRACESTOP_SC(p, td, S_PT_SCX);
 }

Modified: stable/8/sys/amd64/ia32/ia32_syscall.c
==============================================================================
--- stable/8/sys/amd64/ia32/ia32_syscall.c	Sun Feb  7 10:51:17 2010	(r203607)
+++ stable/8/sys/amd64/ia32/ia32_syscall.c	Sun Feb  7 11:37:38 2010	(r203608)
@@ -88,101 +88,136 @@ extern const char *freebsd32_syscallname
 
 void ia32_syscall(struct trapframe *frame);	/* Called from asm code */
 
-void
-ia32_syscall(struct trapframe *frame)
-{
+struct ia32_syscall_args {
+	u_int code;
 	caddr_t params;
-	int i;
 	struct sysent *callp;
-	struct thread *td = curthread;
-	struct proc *p = td->td_proc;
-	register_t orig_tf_rflags;
-	int error;
+	u_int64_t args64[8];
 	int narg;
+};
+
+static int
+fetch_ia32_syscall_args(struct thread *td, struct ia32_syscall_args *sa)
+{
+	struct proc *p;
+	struct trapframe *frame;
 	u_int32_t args[8];
-	u_int64_t args64[8];
-	u_int code;
-	ksiginfo_t ksi;
+	int error, i;
 
-	PCPU_INC(cnt.v_syscall);
-	td->td_pticks = 0;
-	td->td_frame = frame;
-	if (td->td_ucred != p->p_ucred) 
-		cred_update_thread(td);
-	params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
-	code = frame->tf_rax;
-	orig_tf_rflags = frame->tf_rflags;
+	p = td->td_proc;
+	frame = td->td_frame;
+
+	sa->params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
+	sa->code = frame->tf_rax;
 
 	if (p->p_sysent->sv_prepsyscall) {
 		/*
 		 * The prep code is MP aware.
 		 */
-		(*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
+		(*p->p_sysent->sv_prepsyscall)(frame, args, &sa->code,
+		    &sa->params);
 	} else {
 		/*
 		 * Need to check if this is a 32 bit or 64 bit syscall.
 		 * fuword is MP aware.
 		 */
-		if (code == SYS_syscall) {
+		if (sa->code == SYS_syscall) {
 			/*
 			 * Code is first argument, followed by actual args.
 			 */
-			code = fuword32(params);
-			params += sizeof(int);
-		} else if (code == SYS___syscall) {
+			sa->code = fuword32(sa->params);
+			sa->params += sizeof(int);
+		} else if (sa->code == SYS___syscall) {
 			/*
 			 * Like syscall, but code is a quad, so as to maintain
 			 * quad alignment for the rest of the arguments.
 			 * We use a 32-bit fetch in case params is not
 			 * aligned.
 			 */
-			code = fuword32(params);
-			params += sizeof(quad_t);
+			sa->code = fuword32(sa->params);
+			sa->params += sizeof(quad_t);
 		}
 	}
-
  	if (p->p_sysent->sv_mask)
- 		code &= p->p_sysent->sv_mask;
-
- 	if (code >= p->p_sysent->sv_size)
- 		callp = &p->p_sysent->sv_table[0];
+ 		sa->code &= p->p_sysent->sv_mask;
+ 	if (sa->code >= p->p_sysent->sv_size)
+ 		sa->callp = &p->p_sysent->sv_table[0];
   	else
- 		callp = &p->p_sysent->sv_table[code];
-
-	narg = callp->sy_narg;
+ 		sa->callp = &p->p_sysent->sv_table[sa->code];
+	sa->narg = sa->callp->sy_narg;
 
-	/*
-	 * copyin and the ktrsyscall()/ktrsysret() code is MP-aware
-	 */
-	if (params != NULL && narg != 0)
-		error = copyin(params, (caddr_t)args,
-		    (u_int)(narg * sizeof(int)));
+	if (sa->params != NULL && sa->narg != 0)
+		error = copyin(sa->params, (caddr_t)args,
+		    (u_int)(sa->narg * sizeof(int)));
 	else
 		error = 0;
 
-	for (i = 0; i < narg; i++)
-		args64[i] = args[i];
+	for (i = 0; i < sa->narg; i++)
+		sa->args64[i] = args[i];
 
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSCALL))
-		ktrsyscall(code, narg, args64);
+		ktrsyscall(sa->code, sa->narg, sa->args64);
 #endif
+
+	return (error);
+}
+
+void
+ia32_syscall(struct trapframe *frame)
+{
+	struct thread *td;
+	struct proc *p;
+	struct ia32_syscall_args sa;
+	register_t orig_tf_rflags;
+	int error;
+	ksiginfo_t ksi;
+
+	PCPU_INC(cnt.v_syscall);
+	td = curthread;
+	p = td->td_proc;
+	td->td_syscalls++;
+
+	td->td_pticks = 0;
+	td->td_frame = frame;
+	if (td->td_ucred != p->p_ucred) 
+		cred_update_thread(td);
+	orig_tf_rflags = frame->tf_rflags;
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &= ~TDB_USERWR;
+		PROC_UNLOCK(p);
+	}
+	error = fetch_ia32_syscall_args(td, &sa);
+
 	CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
-	    td->td_proc->p_pid, td->td_proc->p_comm, code);
+	    td->td_proc->p_pid, td->td_name, sa.code);
 
 	if (error == 0) {
 		td->td_retval[0] = 0;
 		td->td_retval[1] = frame->tf_rdx;
 
-		STOPEVENT(p, S_SCE, narg);
-
+		STOPEVENT(p, S_SCE, sa.narg);
 		PTRACESTOP_SC(p, td, S_PT_SCE);
+		if (td->td_dbgflags & TDB_USERWR) {
+			/*
+			 * Reread syscall number and arguments if
+			 * debugger modified registers or memory.
+			 */
+			error = fetch_ia32_syscall_args(td, &sa);
+			if (error != 0)
+				goto retval;
+			td->td_retval[1] = frame->tf_rdx;
+		}
 
-		AUDIT_SYSCALL_ENTER(code, td);
-		error = (*callp->sy_call)(td, args64);
+		AUDIT_SYSCALL_ENTER(sa.code, td);
+		error = (*sa.callp->sy_call)(td, sa.args64);
 		AUDIT_SYSCALL_EXIT(error, td);
-	}
 
+		/* Save the latest error return value. */
+		td->td_errno = error;
+	}
+ retval:
 	cpu_set_syscall_retval(td, error);
 
 	/*
@@ -201,14 +236,16 @@ ia32_syscall(struct trapframe *frame)
 	 * Check for misbehavior.
 	 */
 	WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???");
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     freebsd32_syscallnames[sa.code] : "???");
 	KASSERT(td->td_critnest == 0,
 	    ("System call %s returning in a critical section",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???"));
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     freebsd32_syscallnames[sa.code] : "???"));
 	KASSERT(td->td_locks == 0,
 	    ("System call %s returning with %d locks held",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???",
-	    td->td_locks));
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     freebsd32_syscallnames[sa.code] : "???", td->td_locks));
 
 	/*
 	 * Handle reschedule and other end-of-syscall issues
@@ -216,10 +253,10 @@ ia32_syscall(struct trapframe *frame)
 	userret(td, frame);
 
 	CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
-	    td->td_proc->p_pid, td->td_proc->p_comm, code);
+	    td->td_proc->p_pid, td->td_proc->p_comm, sa.code);
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSRET))
-		ktrsysret(code, error, td->td_retval[0]);
+		ktrsysret(sa.code, error, td->td_retval[0]);
 #endif
 
 	/*
@@ -227,7 +264,7 @@ ia32_syscall(struct trapframe *frame)
 	 * register set.  If we ever support an emulation where this
 	 * is not the case, this code will need to be revisited.
 	 */
-	STOPEVENT(p, S_SCX, code);
+	STOPEVENT(p, S_SCX, sa.code);
  
 	PTRACESTOP_SC(p, td, S_PT_SCX);
 }

Modified: stable/8/sys/i386/i386/trap.c
==============================================================================
--- stable/8/sys/i386/i386/trap.c	Sun Feb  7 10:51:17 2010	(r203607)
+++ stable/8/sys/i386/i386/trap.c	Sun Feb  7 11:37:38 2010	(r203608)
@@ -971,97 +971,130 @@ dblfault_handler()
 	panic("double fault");
 }
 
-/*
- *	syscall -	system call request C handler
- *
- *	A system call is essentially treated as a trap.
- */
-void
-syscall(struct trapframe *frame)
-{
-	caddr_t params;
+struct syscall_args {
+	u_int code;
 	struct sysent *callp;
-	struct thread *td = curthread;
-	struct proc *p = td->td_proc;
-	register_t orig_tf_eflags;
-	int error;
-	int narg;
 	int args[8];
-	u_int code;
-	ksiginfo_t ksi;
+	register_t *argp;
+	int narg;
+};
 
-	PCPU_INC(cnt.v_syscall);
+static int
+fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+	struct proc *p;
+	struct trapframe *frame;
+	caddr_t params;
+	int error;
 
-#ifdef DIAGNOSTIC
-	if (ISPL(frame->tf_cs) != SEL_UPL) {
-		panic("syscall");
-		/* NOT REACHED */
-	}
-#endif
+	p = td->td_proc;
+	frame = td->td_frame;
 
-	td->td_pticks = 0;
-	td->td_frame = frame;
-	if (td->td_ucred != p->p_ucred) 
-		cred_update_thread(td);
 	params = (caddr_t)frame->tf_esp + sizeof(int);
-	code = frame->tf_eax;
-	orig_tf_eflags = frame->tf_eflags;
+	sa->code = frame->tf_eax;
 
 	if (p->p_sysent->sv_prepsyscall) {
-		(*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
+		(*p->p_sysent->sv_prepsyscall)(frame, sa->args, &sa->code,
+		    &params);
 	} else {
 		/*
 		 * Need to check if this is a 32 bit or 64 bit syscall.
 		 */
-		if (code == SYS_syscall) {
+		if (sa->code == SYS_syscall) {
 			/*
 			 * Code is first argument, followed by actual args.
 			 */
-			code = fuword(params);
+			sa->code = fuword(params);
 			params += sizeof(int);
-		} else if (code == SYS___syscall) {
+		} else if (sa->code == SYS___syscall) {
 			/*
 			 * Like syscall, but code is a quad, so as to maintain
 			 * quad alignment for the rest of the arguments.
 			 */
-			code = fuword(params);
+			sa->code = fuword(params);
 			params += sizeof(quad_t);
 		}
 	}
 
  	if (p->p_sysent->sv_mask)
- 		code &= p->p_sysent->sv_mask;
-
- 	if (code >= p->p_sysent->sv_size)
- 		callp = &p->p_sysent->sv_table[0];
+ 		sa->code &= p->p_sysent->sv_mask;
+ 	if (sa->code >= p->p_sysent->sv_size)
+ 		sa->callp = &p->p_sysent->sv_table[0];
   	else
- 		callp = &p->p_sysent->sv_table[code];
+ 		sa->callp = &p->p_sysent->sv_table[sa->code];
+	sa->narg = sa->callp->sy_narg;
 
-	narg = callp->sy_narg;
-
-	if (params != NULL && narg != 0)
-		error = copyin(params, (caddr_t)args,
-		    (u_int)(narg * sizeof(int)));
+	if (params != NULL && sa->narg != 0)
+		error = copyin(params, (caddr_t)sa->args,
+		    (u_int)(sa->narg * sizeof(int)));
 	else
 		error = 0;
 		
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSCALL))
-		ktrsyscall(code, narg, args);
+		ktrsyscall(sa->code, sa->narg, sa->args);
 #endif
+	return (error);
+}
 
-	CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
-	    td->td_proc->p_pid, td->td_name, code);
+/*
+ *	syscall -	system call request C handler
+ *
+ *	A system call is essentially treated as a trap.
+ */
+void
+syscall(struct trapframe *frame)
+{
+	struct thread *td;
+	struct proc *p;
+	struct syscall_args sa;
+	register_t orig_tf_eflags;
+	int error;
+	ksiginfo_t ksi;
 
+	PCPU_INC(cnt.v_syscall);
+	td = curthread;
+	p = td->td_proc;
 	td->td_syscalls++;
 
+#ifdef DIAGNOSTIC
+	if (ISPL(frame->tf_cs) != SEL_UPL) {
+		panic("syscall");
+		/* NOT REACHED */
+	}
+#endif
+
+	td->td_pticks = 0;
+	td->td_frame = frame;
+	if (td->td_ucred != p->p_ucred) 
+		cred_update_thread(td);
+	orig_tf_eflags = frame->tf_eflags;
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &= ~TDB_USERWR;
+		PROC_UNLOCK(p);
+	}
+	error = fetch_syscall_args(td, &sa);
+
+	CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
+	    td->td_proc->p_pid, td->td_name, sa.code);
+
 	if (error == 0) {
 		td->td_retval[0] = 0;
 		td->td_retval[1] = frame->tf_edx;
 
-		STOPEVENT(p, S_SCE, narg);
-
+		STOPEVENT(p, S_SCE, sa.narg);
 		PTRACESTOP_SC(p, td, S_PT_SCE);
+		if (td->td_dbgflags & TDB_USERWR) {
+			/*
+			 * Reread syscall number and arguments if
+			 * debugger modified registers or memory.
+			 */
+			error = fetch_syscall_args(td, &sa);
+			if (error != 0)
+				goto retval;
+			td->td_retval[1] = frame->tf_edx;
+		}
 
 #ifdef KDTRACE_HOOKS
 		/*
@@ -1069,13 +1102,13 @@ syscall(struct trapframe *frame)
 		 * callback and if there is a probe active for the
 		 * syscall 'entry', process the probe.
 		 */
-		if (systrace_probe_func != NULL && callp->sy_entry != 0)
-			(*systrace_probe_func)(callp->sy_entry, code, callp,
-			    args);
+		if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
+			(*systrace_probe_func)(sa.callp->sy_entry, sa.code,
+			    sa.callp, sa.args);
 #endif
 
-		AUDIT_SYSCALL_ENTER(code, td);
-		error = (*callp->sy_call)(td, args);
+		AUDIT_SYSCALL_ENTER(sa.code, td);
+		error = (*sa.callp->sy_call)(td, sa.args);
 		AUDIT_SYSCALL_EXIT(error, td);
 
 		/* Save the latest error return value. */
@@ -1087,12 +1120,12 @@ syscall(struct trapframe *frame)
 		 * callback and if there is a probe active for the
 		 * syscall 'return', process the probe.
 		 */
-		if (systrace_probe_func != NULL && callp->sy_return != 0)
-			(*systrace_probe_func)(callp->sy_return, code, callp,
-			    args);
+		if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
+			(*systrace_probe_func)(sa.callp->sy_return, sa.code,
+			    sa.callp, sa.args);
 #endif
 	}
-
+ retval:
 	cpu_set_syscall_retval(td, error);
 
 	/*
@@ -1111,14 +1144,16 @@ syscall(struct trapframe *frame)
 	 * Check for misbehavior.
 	 */
 	WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     syscallnames[sa.code] : "???");
 	KASSERT(td->td_critnest == 0,
 	    ("System call %s returning in a critical section",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     syscallnames[sa.code] : "???"));
 	KASSERT(td->td_locks == 0,
 	    ("System call %s returning with %d locks held",
-	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
-	    td->td_locks));
+	    (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+	     syscallnames[sa.code] : "???", td->td_locks));
 
 	/*
 	 * Handle reschedule and other end-of-syscall issues
@@ -1126,11 +1161,11 @@ syscall(struct trapframe *frame)
 	userret(td, frame);
 
 	CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
-	    td->td_proc->p_pid, td->td_name, code);
+	    td->td_proc->p_pid, td->td_name, sa.code);
 
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSRET))
-		ktrsysret(code, error, td->td_retval[0]);
+		ktrsysret(sa.code, error, td->td_retval[0]);
 #endif
 
 	/*
@@ -1138,7 +1173,7 @@ syscall(struct trapframe *frame)
 	 * register set.  If we ever support an emulation where this
 	 * is not the case, this code will need to be revisited.
 	 */
-	STOPEVENT(p, S_SCX, code);
+	STOPEVENT(p, S_SCX, sa.code);
 
 	PTRACESTOP_SC(p, td, S_PT_SCX);
 }

Modified: stable/8/sys/kern/sys_process.c
==============================================================================
--- stable/8/sys/kern/sys_process.c	Sun Feb  7 10:51:17 2010	(r203607)
+++ stable/8/sys/kern/sys_process.c	Sun Feb  7 11:37:38 2010	(r203608)
@@ -809,6 +809,7 @@ kern_ptrace(struct thread *td, int req, 
 
 	case PT_WRITE_I:
 	case PT_WRITE_D:
+		td2->td_dbgflags |= TDB_USERWR;
 		write = 1;
 		/* FALLTHROUGH */
 	case PT_READ_I:
@@ -877,6 +878,7 @@ kern_ptrace(struct thread *td, int req, 
 			break;
 		case PIOD_WRITE_D:
 		case PIOD_WRITE_I:
+			td2->td_dbgflags |= TDB_USERWR;
 			uio.uio_rw = UIO_WRITE;
 			break;
 		default:
@@ -899,6 +901,7 @@ kern_ptrace(struct thread *td, int req, 
 		goto sendsig;	/* in PT_CONTINUE above */
 
 	case PT_SETREGS:
+		td2->td_dbgflags |= TDB_USERWR;
 		error = PROC_WRITE(regs, td2, addr);
 		break;
 
@@ -907,6 +910,7 @@ kern_ptrace(struct thread *td, int req, 
 		break;
 
 	case PT_SETFPREGS:
+		td2->td_dbgflags |= TDB_USERWR;
 		error = PROC_WRITE(fpregs, td2, addr);
 		break;
 
@@ -915,6 +919,7 @@ kern_ptrace(struct thread *td, int req, 
 		break;
 
 	case PT_SETDBREGS:
+		td2->td_dbgflags |= TDB_USERWR;
 		error = PROC_WRITE(dbregs, td2, addr);
 		break;
 

Modified: stable/8/sys/sys/proc.h
==============================================================================
--- stable/8/sys/sys/proc.h	Sun Feb  7 10:51:17 2010	(r203607)
+++ stable/8/sys/sys/proc.h	Sun Feb  7 11:37:38 2010	(r203608)
@@ -343,6 +343,7 @@ do {									\
 /* Userland debug flags */
 #define	TDB_SUSPEND	0x00000001 /* Thread is suspended by debugger */
 #define	TDB_XSIG	0x00000002 /* Thread is exchanging signal under trace */
+#define	TDB_USERWR	0x00000004 /* Debugger modified memory or registers */
 
 /*
  * "Private" flags kept in td_pflags:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002071137.o17BbcxP008531>