On 12/22, Oleg Nesterov wrote:
>
> On 12/22, caiq...@redhat.com wrote:
> >
> > and a different syscall number when syscall-from-clone failed.
>
> This is not clear to me, will take a look.

Should I say I know nothing about s390 and can't read its asm?

First of all, I think syscall-from-clone is wrong on s390 and
needs a fix,

        #elif defined __s390__
        # define REGISTER_CALLNO        offsetof (struct user_regs_struct, 
orig_gpr2)
        # define REGISTER_RETVAL        offsetof (struct user_regs_struct, 
gprs[2])

This doesn't look right. I did a simple test-case (below), and
with or without utrace it prints

        syscall=1234 ret=6              <----- __NR_close
        syscall=1234 ret=-9             <----- -EBADF, this is correct

Apparently, 1234 is the argument for close(1234).

So: it is not clear to me how to get "callno" on SYSCALL_EXIT,
and I don't know whether it is OK or not that syscall-from-clone
sees different ->orig_gpr2 after return from fork() on s390

        -unexpected syscall 0x5ee9      <---- without utrace
        +unexpected syscall 0           <---- with utrace
        
syscall_get_nr() returns regs->svcnr, but there is no "svcnr" in
user_regs_struct on s390.

Still investigating...

Oleg.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stddef.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <assert.h>
#include <sys/user.h>
#include <asm/ptrace.h>


#ifdef __s390__
#define REGISTER_CALLNO         offsetof(struct user_regs_struct, orig_gpr2)
#define REGISTER_RETVAL         offsetof(struct user_regs_struct, gprs[2])
#else
#define REGISTER_CALLNO         offsetof(struct user_regs_struct, orig_rax)
#define REGISTER_RETVAL         offsetof(struct user_regs_struct, rax)
#endif

int main(void)
{
        int pid, status, i;
        long scn, ret;

        pid = fork();
        if (!pid) {
                assert(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0);
                kill(getpid(), SIGUSR1);

                close(1234);

                return 0x66;
        }

        assert(pid == wait(&status));
        assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGUSR1);
        assert(ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == 0);

        for (i = 0; i < 2; ++i) {
                ptrace(PTRACE_SYSCALL, pid, 0,0);
                assert(pid == wait(&status));
                assert(status == 0x857f);

                scn = ptrace(PTRACE_PEEKUSER, pid, REGISTER_CALLNO, NULL);
                ret = ptrace(PTRACE_PEEKUSER, pid, REGISTER_RETVAL, NULL);

                printf("syscall=%ld ret=%ld\n", scn, ret);

        }

        kill(pid, SIGKILL);

        return 0;
}

Reply via email to