Re: utrace_report_syscall_entry() finish_report()

2009-11-12 Thread Oleg Nesterov
On 11/11, Roland McGrath wrote:

  I saw you have utrace-syscall-resumed branch but never looked at it.

 For those not concerned with its purpose, there is one thing you must
 know.  Every report_syscall_entry callback must do:

   if (utrace_syscall_action(action) == UTRACE_SYSCALL_RESUMED)
   return UTRACE_RESUME;

 to avoid being confused by the new extra callbacks.

OK, thanks.

  Then I fix utrace-ptrace. I _think_ this will be easy too.
  ptrace_report_syscall_exit() can notice ctx-resume == UTRACE_SINGLESTEP
  and send the trap if utrace_control() doesn't set TIF_SINGLESTEP
  synchronously.
 
  (And this means with utrace tracehook_report_syscall_exit() can do
   nothing except utrace_report_syscall_exit()).

 Today we don't call into utrace unless UTRACE_EVENT(SYSCALL_EXIT) is set.
 So if nothing changes in the utrace layer, this means that ptrace will
 enable UTRACE_EVENT(SYSCALL_EXIT) (i.e. TIF_SYSCALL) for PTRACE_SINGLE*.
 Is that what you had in mind?

Yes, exactly.

 There are two possible issues with doing it that way.

 The first is purely from a ptrace perspective.  Today PTRACE_SINGLE* does
 not set TIF_SYSCALL.  On x86 this doesn't really make a difference in the
 underlying code, because TIF_SINGLESTEP takes the same path.  So probably
 this is fine.  But on other machines I'm not entirely sure that TIF_SYSCALL
 won't take a slower path than single-step alone caused already for syscall
 entries.  This surely pales in comparison to the overhead of the ptrace
 stop and context switch and all, but still, it could be a change.  On x86
 I'm not sure there's any reason not to optimize that better in the future,

I see.

 The other issue comes from the utrace API perspective.  Here it just seems
 entirely wrong to require the engine (ptrace or any other) to do any
 syscall-exit magic of its own to make UTRACE_SINGLESTEP work on a syscall
 insn like it does on other insns.  The utrace layer should make that trap
 appear transparently like the normal traps seen for UTRACE_SINGLESTEP.

 So, we could have tracehook_report_syscall_exit send the signal as it does
 now upstream.  But probably better is to do it all in the utrace layer,

Indeed!

 i.e. pass the step flag to utrace_report_syscall_exit.

The problem is, we can't use step flag. step == TIF_SINGLESTEP, and it
can be unset despite the fact ptrace (or other engine) did
utrace_control(UTRACE_SINGLESTEP) to resume.

Simple example. The tracee stopped in syscall-entry. the tracer does
PTRACE_SINGLESTEP. With the recent changes in utrace-cleanup
utrace_control() doesn't set TIF_SINGLESTEP, and the tracee passes
syscall_trace_leave() without TIF_SINGLESTEP.

But I guess utrace_report_syscall_exit() can look at utrace-resume
and notice UTRACE_SINGLESTEP ?

 That approximates the check that yesterday's x86 code does:

   if (test_thread_flag(TIF_SINGLESTEP) 
   tracehook_consider_fatal_signal(current, SIGTRAP))
   send_sigtrap(current, regs, 0, TRAP_BRKPT);

 But still we are queuing a real signal here.  That is no different from the
 real hardware trap case, so perhaps that is the right thing to do for now.
 (Eventually we want to have a way for all these traps to avoid becoming
 real signals at all, but that is a subject for another day.)  Like a real
 signal, that has the problem of still being queued if the tracer detaches
 immediately thereafter (so it gets delivered to the user).  We could avoid
 that for this fake signal by just setting some flag that tells
 utrace_get_signal to synthesize it before dequeuing real signals.
 It's probably not worth bothering with that complexity now.

Yes, I think we have more important problems ;)

Oleg.



Re: utrace_report_syscall_entry() finish_report()

2009-11-12 Thread Roland McGrath
 Simple example. The tracee stopped in syscall-entry. the tracer does
 PTRACE_SINGLESTEP. With the recent changes in utrace-cleanup
 utrace_control() doesn't set TIF_SINGLESTEP, and the tracee passes
 syscall_trace_leave() without TIF_SINGLESTEP.

Ah, yes.  Well, the point of the arch/tracehook tweaks was that the utrace
layer has all the information and can decide what to do.

 But I guess utrace_report_syscall_exit() can look at utrace-resume
 and notice UTRACE_SINGLESTEP ?

Yes.  Unlike ptrace, at the utrace layer we can have both syscall-exit and
single-step going on at the same time (even by unrelated engines).  If some
engine doesn't care about syscall-exit, it will still get report_quiesce
there and should reassert UTRACE_SINGLESTEP with its return value.  But
that makes it a bit unclear whether a UTRACE_SINGLESTEP return from
report_syscall_exit wants a fresh step after the next insn, or wants a
synthetic trap immediately after the syscall insn.  

So I wonder if what might be right is to have utrace_report_syscall_exit
look at -resume before its reporting.  If it's single/block-step it can
synthesize the trap there, so the signal is queued before the syscall-exit
report is made.


Thanks,
Roland



Re: utrace_report_syscall_entry() finish_report()

2009-11-11 Thread Oleg Nesterov
On 11/10, Roland McGrath wrote:

 Ok.  I realize it's largely separate, but I think we want to hash through
 this along with the other set of after-report-behavior problems.

 Also, it doesn't seem sensible to fiddle with utrace_report_syscall_entry
 separate from resolving UTRACE_SYSCALL_RESUMED change to the API.  There
 was not much feedback about that change, but IIRC nobody was against it.
 So I've decided to merge the old utrace-syscall-resumed branch into
 utrace-cleanup.

I saw you have utrace-syscall-resumed branch but never looked at it.

I'll try to follow these changes once I fix utrace-ptrace. Now that
upstream problems with syscall_exit  trap are hopefully resolved
this should be easy.

Today I was distracted by workqueue bug (bluetooth driver actually),
will try tomorrow.

Roland, I guess utrace-cleanup becomes the master branch, yes?
I mean, utrace-ptrace should be updated according to the recent
changes in utrace-cleanup, and this is what you are going to send
upstream.

This means you should also merge utrace-cleanup into utrace-ptrace?
Then I fix utrace-ptrace. I _think_ this will be easy too.
ptrace_report_syscall_exit() can notice ctx-resume == UTRACE_SINGLESTEP
and send the trap if utrace_control() doesn't set TIF_SINGLESTEP
synchronously.

(And this means with utrace tracehook_report_syscall_exit() can do
 nothing except utrace_report_syscall_exit()).

Oleg.



Re: utrace_report_syscall_entry() finish_report()

2009-11-11 Thread Roland McGrath
 I saw you have utrace-syscall-resumed branch but never looked at it.

For those not concerned with its purpose, there is one thing you must
know.  Every report_syscall_entry callback must do:

if (utrace_syscall_action(action) == UTRACE_SYSCALL_RESUMED)
return UTRACE_RESUME;

to avoid being confused by the new extra callbacks.

 Roland, I guess utrace-cleanup becomes the master branch, yes?
 I mean, utrace-ptrace should be updated according to the recent
 changes in utrace-cleanup, and this is what you are going to send
 upstream.

Right.  I was waiting to be sure you didn't object.  But AFAICT we now seem
to be happy with this branch modulo more necessary fixes.

 This means you should also merge utrace-cleanup into utrace-ptrace?

Right.

 Then I fix utrace-ptrace. I _think_ this will be easy too.
 ptrace_report_syscall_exit() can notice ctx-resume == UTRACE_SINGLESTEP
 and send the trap if utrace_control() doesn't set TIF_SINGLESTEP
 synchronously.
 
 (And this means with utrace tracehook_report_syscall_exit() can do
  nothing except utrace_report_syscall_exit()).

Today we don't call into utrace unless UTRACE_EVENT(SYSCALL_EXIT) is set.
So if nothing changes in the utrace layer, this means that ptrace will
enable UTRACE_EVENT(SYSCALL_EXIT) (i.e. TIF_SYSCALL) for PTRACE_SINGLE*.
Is that what you had in mind?

There are two possible issues with doing it that way.

The first is purely from a ptrace perspective.  Today PTRACE_SINGLE* does
not set TIF_SYSCALL.  On x86 this doesn't really make a difference in the
underlying code, because TIF_SINGLESTEP takes the same path.  So probably
this is fine.  But on other machines I'm not entirely sure that TIF_SYSCALL
won't take a slower path than single-step alone caused already for syscall
entries.  This surely pales in comparison to the overhead of the ptrace
stop and context switch and all, but still, it could be a change.  On x86
I'm not sure there's any reason not to optimize that better in the future,
too.  Even in the most optimal circumstance imaginable, the whole point is
to handle a SIGTRAP signal after the syscall, so that too probably dwarfs
the overhead difference of the faster entry path.

The other issue comes from the utrace API perspective.  Here it just seems
entirely wrong to require the engine (ptrace or any other) to do any
syscall-exit magic of its own to make UTRACE_SINGLESTEP work on a syscall
insn like it does on other insns.  The utrace layer should make that trap
appear transparently like the normal traps seen for UTRACE_SINGLESTEP.

So, we could have tracehook_report_syscall_exit send the signal as it does
now upstream.  But probably better is to do it all in the utrace layer,
i.e. pass the step flag to utrace_report_syscall_exit.  Since today
single-step generates a plain (forced) SIGTRAP, we can synthesize that.
There are at least two options here.  One is to do:

if (step  (task-utrace_flags  UTRACE_SIGNAL_CORE)) {
force_sig_info(...);
}

That approximates the check that yesterday's x86 code does:

if (test_thread_flag(TIF_SINGLESTEP) 
tracehook_consider_fatal_signal(current, SIGTRAP))
send_sigtrap(current, regs, 0, TRAP_BRKPT);

But still we are queuing a real signal here.  That is no different from the
real hardware trap case, so perhaps that is the right thing to do for now.
(Eventually we want to have a way for all these traps to avoid becoming
real signals at all, but that is a subject for another day.)  Like a real
signal, that has the problem of still being queued if the tracer detaches
immediately thereafter (so it gets delivered to the user).  We could avoid
that for this fake signal by just setting some flag that tells
utrace_get_signal to synthesize it before dequeuing real signals.
It's probably not worth bothering with that complexity now.


Thanks,
Roland



Re: utrace_report_syscall_entry() finish_report()

2009-11-10 Thread Roland McGrath
Ok.  I realize it's largely separate, but I think we want to hash through
this along with the other set of after-report-behavior problems.  

Also, it doesn't seem sensible to fiddle with utrace_report_syscall_entry
separate from resolving UTRACE_SYSCALL_RESUMED change to the API.  There
was not much feedback about that change, but IIRC nobody was against it.
So I've decided to merge the old utrace-syscall-resumed branch into
utrace-cleanup.  We can consider the resume-action handling details given
that code.

I'll try to look at all this with, as you say, a fresh head, on Wednesday.


Thanks,
Roland