Re: svn commit: r202882 - in head/sys: amd64/amd64 amd64/ia32 i386/i386 kern sys

2010-01-23 Thread Kostik Belousov
On Sat, Jan 23, 2010 at 11:45:35AM +, Konstantin Belousov wrote:
> Author: kib
> Date: Sat Jan 23 11:45:35 2010
> New Revision: 202882
> URL: http://svn.freebsd.org/changeset/base/202882
> 
> Log:
>   For PT_TO_SCE stop that stops the ptraced process upon syscall entry,
>   syscall arguments are collected before ptracestop() is called. As a
>   consequence, debugger cannot modify syscall or its arguments.
>   
>   For i386, amd64 and ia32 on amd64 MD syscall(), reread syscall number
>   and arguments after ptracestop(), if debugger modified anything in the
>   process environment. Since procfs stopeven requires number of syscall
>   arguments in p_xstat, this cannot be solved by moving stop/trace point
>   before argument fetching.
I am willing to help architecture maintainers to implement this for
corresponding architectures, if any help is needed.


pgpVPmDRqpnJ1.pgp
Description: PGP signature


svn commit: r202882 - in head/sys: amd64/amd64 amd64/ia32 i386/i386 kern sys

2010-01-23 Thread Konstantin Belousov
Author: kib
Date: Sat Jan 23 11:45:35 2010
New Revision: 202882
URL: http://svn.freebsd.org/changeset/base/202882

Log:
  For PT_TO_SCE stop that stops the ptraced process upon syscall entry,
  syscall arguments are collected before ptracestop() is called. As a
  consequence, debugger cannot modify syscall or its arguments.
  
  For i386, amd64 and ia32 on amd64 MD syscall(), reread syscall number
  and arguments after ptracestop(), if debugger modified anything in the
  process environment. Since procfs stopeven requires number of syscall
  arguments in p_xstat, this cannot be solved by moving stop/trace point
  before argument fetching.
  
  Move the code to read arguments into separate function
  fetch_syscall_args() to avoid code duplication. Note that ktrace point
  for modified syscall is intentionally recorded twice, once with original
  arguments, and second time with the arguments set by debugger.
  
  PT_TO_SCX stop is executed after cpu_syscall_set_retval() already.
  
  Reported by:  Ali Polatel 
  Briefly discussed with:   jhb
  MFC after:3 weeks

Modified:
  head/sys/amd64/amd64/trap.c
  head/sys/amd64/ia32/ia32_syscall.c
  head/sys/i386/i386/trap.c
  head/sys/kern/sys_process.c
  head/sys/sys/proc.h

Modified: head/sys/amd64/amd64/trap.c
==
--- head/sys/amd64/amd64/trap.c Sat Jan 23 11:43:30 2010(r202881)
+++ head/sys/amd64/amd64/trap.c Sat Jan 23 11:45:35 2010(r202882)
@@ -885,95 +885,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, 
¶ms);
+   (*p->p_sysent->sv_prepsyscall)(frame, (int *)sa->args,
+   &sa->code, ¶ms);
} 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
+