> Neat. Although returning just UTRACE_SYSCALL_ABORT doesn't work. 

I'm sorry, I was imprecise.  Every utrace callback's return value is a
combination of 'enum utrace_resume_action' bits OR'd together with more
bits that are specific to the callback.  What I said was meant only to say
that UTRACE_SYSCALL_ABORT is the 'enum utrace_syscall_action' portion of
the return value.  You always need to use UTRACE_RESUME (or something else
appropriate for your case) in the return value too.

In fact, the main reason UTRACE_STOP has the value zero is so that if a
careless or confused engine-writer forgets to OR in the intended value, the
result will be something that immediately obvious to be other than what the
engine probably expected, forcing you to go back and figure out the interface.

> You probably didn't mention that because it was obvious but honestly it
> wasn't that clear for me and didn't see it was mentioned in the
> documentation.

The kerneldoc for 'struct utrace_engine_ops' describes this generally
(aka http://people.redhat.com/roland/utrace/DocBook/re10.html).

> Neat^2. I think documenting this is a good idea as well. Maybe I should
> start writing a patch for the documentation to make it easier for
> new-comers like me :)

Please do!  I think most or all of these things are mentioned somewhere in
the documentation, but it may not be easy to find without reading it all
start to finish.  I tend towards concision more than verbosity in my
kerneldoc comments (in contrast to my occasionally gargantuan rambling
email treatises ;-).  I'm also the worst possible person to judge what
makes the documentation more or less clear, since all of it says things
that I already know.

> One question about report_syscall_exit, I'm trying to change the errno
> to EPERM for aborted system calls but I think I'm doing it wrong:
> 
> static u32
> ubox_syscall_exit(u32 action, struct utrace_engine *engine, struct pt_regs 
> *regs)
> {
>       enum utrace_syscall_action decision;
> 
>       decision = utrace_syscall_action(action);
>       switch (decision) {
>       case UTRACE_SYSCALL_ABORT:
>               syscall_set_return_value(current, regs, -EPERM, -1);
>               /* fall through */
>       default:
>               return UTRACE_RESUME;
>       }
> }
> 
> The decision argument is never set to UTRACE_SYSCALL_ABORT for me. It's
> always 0 aka UTRACE_SYSCALL_RUN.

report_syscall_exit does not receive any 'enum utrace_syscall_action' bits
in its argument.  utrace_syscall_action only applies to the
report_syscall_entry callback.  There what you receive is the action chosen
by any other previous utrace engine also attached to the same thread,
showing what decision now prevails for the same syscall-entry about to
happen.  By the time you get the report_syscall_exit callback, there is no
more decision to be made--the system call has already happened (or not).

On x86, the register state left by the report_syscall_entry callback stays
unchanged through to the system call exit (if no actual syscall is made).
That is, the incoming syscall_get_error() result is -ENOSYS and that's what
user mode will see unless you change it.  

However, on other machines, these details differ and you may indeed need to
apply your changes in the report_syscall_exit callback.  In that case, your
engine needs to track its own state to decide what to do.  e.g. you could
hang something off engine->data.

> Thanks for answering, I really appreciate it.

Thanks for your interest in utrace.  We really have no idea what the likely
future of utrace or anything like it will be.  But it can't hurt to have
more people doing experiments and finding new ways in which it's useful
to have such facilities.


Thanks,
Roland

Reply via email to