On Sun, 10 Oct 2010 11:35:02 -0700 (PDT), Roland McGrath <rol...@redhat.com> 
wrote:
> > 1. From what I've read in the DocBook pages I've figured out that I have
> > to have two report entries. One for syscall_entry and one for
> > syscall_exit. On syscall_entry I should use syscall_get_nr() and check
> > if this number is equal to __NR_socket and return UTRACE_SYSCALL_ABORT
> > in that case and on syscall_exit, I need to call syscall_rollback() to
> > rollback the registers if utrace_syscall_action(action) returns
> > UTRACE_SYSCALL_ABORT. Is this correct?
> 
> The report_syscall_entry hook is the only one you need to prevent the
> system call from running.  If it returns UTRACE_SYSCALL_ABORT, then the
> system call will fail with the ENOSYS error code.  You only need to use a
> report_syscall_exit hook if you want the registers the user process sees
> after attempting the system call to be different from that.

Neat. Although returning just UTRACE_SYSCALL_ABORT doesn't work. It just
makes the process hang for me. I had to do:
return (no == SYS_socket)
  ? UTRACE_SYSCALL_ABORT | UTRACE_RESUME
  : UTRACE_SYSCALL_RUN | UTRACE_RESUME;
to make it work. 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.

> > 2. First I've read the documentation from Roland's page and figured out
> > it's out of date. report_syscall_entry callback used to have a struct
> > task_struct argument but now it doesn't. How should I get a "struct
> > task_struct" to pass to syscall_get_nr? Am I supposed to keep a
> > reference to the "struct pid" I used in init_module() and use
> > pid_task(pid, PIDTYPE_PID) or should I use find_get_pid() just as I used
> > in the init_module()?
> 
> Those callbacks are made in the affected thread itself.  
> So you can just use the magic variable 'current'.

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 :)
 
> I've updated the web copy of the documentation.  If you install the
> kernel-doc rpm on a Fedora system, that contains the version of this same
> documentation that goes with the kernel you have.

Thanks, appreciated.
 
> > 3. In the report_syscall_exit callback, is the "struct pt_regs" argument
> > there so that the user can directly pass it to syscall_rollback() or do
> > I have to save the registers I had in report_syscall_entry() callback
> > and use them instead?
> 
> You can just pass that pointer directly.  In fact, the same pointer to
> 'struct pt_regs' will be passed to both callbacks.  This is always the same
> pointer that 'task_pt_regs(current)' would return, just made quicker to
> access by having the argument to the callbacks.

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.

> > 4. __NR_socket is available on some architectures and it's implemented
> > on top of __NR_socketcall on others. I'm running this example on x86_64.
> > How should my module figure out which mode the target process is running
> > in? I suppose this is related to the CS register. 
> 
> There are several ways to go about this, depending on how arch-specific you
> want to make it.  On x86-64 it's possible for 32-bit processes to make
> 64-bit system calls and vice versa, though normal user programs will never
> actually do this.  Perhaps the easiest and cleanest way, that both covers
> this arcane possibility and also works on other architectures, is to call
> is_compat_task() (under #ifdef CONFIG_COMPAT).

I'll check out is_compat_task(), thanks.
 
> > Having figured that how am I supposed to include system call numbers from
> > both architectures and use __NR_socketcall for 32bit mode and __NR_socket
> > for 64bit?
> 
> Unfortunately, there is no clean way to refer to the 32-bit syscall numbers
> in code inside the 64-bit kernel.  socketcall is not one of the few listed
> in asm/ia32_unistd.h, so off hand I think you'd just have to hard-code the
> i386 __NR_socketcall value in your module.

Not perfect but WFM.
 
> > 5. Is there any project in the outer-space that does something like
> > this, sandboxing or monitoring system calls, from which I can learn
> > more?
> 
> Renzo Davoli's umview/kmview is just such an animal.
> See http://wiki.virtualsquare.org for details.

Looks like really nice example for me! I'm reading it now :)

> 
> Thanks,
> Roland
> 

Thanks for answering, I really appreciate it.

-- 
Regards,
Ali Polatel

Attachment: pgpRh83B0Q9Ul.pgp
Description: PGP signature

Reply via email to