> Another question. How can ->report_signal(info) change info->si_signo
> (or other data in *info) when we have multiple engines? I mean, how
> can engines cooperate if they want to change ->si_signo.

This is just an instance of the general subject of engine cooperation when
engines do perturbation.  Each engine's report_signal callback gets
arguments saying what the previous engine decided to do.  This includes the
enum utrace_signal_action, the siginfo_t contents, and the sigaction--as
well as all of the user registers and memory.  Each engine can change any
of those how it sees fit.

> For example, ptrace_report_signal() sets ->si_signo = SIGTRAP. But
> if we have another engine attached before ptrace-engine, then its
> ->report_signal() was already called. This means that engine can't
> know about this SIGTRAP?

Well, there wasn't any SIGTRAP.  That engine doesn't know about the virtual
reality that the ptrace engine is creating.  In the same way, if that
engine A precedes an engine C whose report_quiesce(0) changes the user
registers, then A will never know that user-mode ran with different
register contents than what its report_quiesce(0) observed.  That's just
the fundamental nature of there being an ordering among engines.

Similarly, if engine C follows the ptrace engine, it will perceive(*) that
there was a SIGTRAP that the ptrace engine then decided to ignore.  

*unless it checks the orig_ka argument, which is NULL to indicate that
there this is a UTRACE_SIGNAL_{REPORT,HANDLER} pass without an original
real signal.

> In short. If any engine changes *info, how should it take into account
> other engines attached before?

If you are perturbing the state, then you've decided you don't really care
about what came before.  An engine like ptrace is not really trying to keep
out of the way of other engines, it's just doing what it does.  The intent
of the API is that every engine has the opportunity to be informed about
what other engines are doing, and make its own decisions.  The fact of
ordering and the linear nature of time means that each engine can't really
be aware of every other engine all the time, only the earlier ones in the
list (and indirectly see the effects of later ones after the fact through
means like UTRACE_REPORT).

> ptrace also changes *info via ->last_siginfo. IOW, the owner of engine
> plays with info, not ->report_signal(). I assume that ptrace is the only
> engine which "has rights" to play with *info outside of ->report_signal(),
> right?

Well, it certainly doesn't seem like all that clean a thing to do.
But the kerneldoc for the report_signal API does document:

                                 For a report without a new signal, @info
 *      is left uninitialized and must be set completely by an engine that
 *      chooses to deliver a signal; if there was a previous @report_signal
 *      callback ending in %UTRACE_STOP and it was just resumed using
 *      %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged
 *      from the previous callback.  In this way, the original signal can
 *      be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN
 *      and then found again when resuming @task with %UTRACE_INTERRUPT.

So I think the bottom line is that this is something that you can fiddle
with just like you can fiddle with the registers.  All sorts of such
fiddling are possible, and don't break any core assumptions of the utrace
API.  It's just a question of what fiddling is really a good idea and how
to mediate higher-level choices about that.  You don't risk any bad effects
beyond what some unhelpful engine (or just userland run wild) might do
anyway, i.e. scrambling user registers and siginfo_t so they foul up
application behavior.  But that's just a baseline limit on harm.  At higher
levels you want to cooperate with other engines so they all work together
usefully in practice.  

The API offers only one mechanism to synchronize with anyone else fiddling
such things.  That is to do the fiddling in your report_* callbacks where
you are explicitly serialized with the callbacks of other engines and have
specified ways to be sure you observe what they do.

I think it's entirely reasonable to say that only ptrace should fiddle with
siginfo_t outside of report_signal callbacks, just as a convention about
what's couth.  But that's beyond the scope of the utrace API level itself.


Thanks,
Roland

Reply via email to