On 01/07, Roland McGrath wrote:
>
> > I am confused as well. Yes, I thought about regs->psw.mask change too,
> > but I don't understand why it helps..
> [...]
> > But. Acoording to the testing I did (unless I did something wrong
> > again) this patch doesn't make any difference in this particular
> > case. 6580807da14c423f0d0a708108e6df6ebc8bc83d does.
>
> Those results are quite mysterious to me.
> I think we'll have to get Martin to sort it out definitively.

I did the testing again with 2.6.32-5.el6 + Martin's
        c3311c13adc1021e986fef12609ceb395ffc5014
        f8d5faf718c9ff2c04eb8484585d4963c4111cd7
patches.

the same test-case:

        #include <stdio.h>
        #include <unistd.h>
        #include <signal.h>
        #include <sys/ptrace.h>
        #include <sys/wait.h>
        #include <assert.h>

        int main(void)
        {
                int pid, status;

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

                        if (!fork())
                                return 43;

                        wait(&status);
                        return WEXITSTATUS(status);
                }


                for (;;) {
                        assert(pid == wait(&status));
                        if (WIFEXITED(status))
                                break;
                        assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0);
                }

                assert(WEXITSTATUS(status) == 43);
                return 0;
        }

with the simple debugging patch below I did

        # perl -e 'syscall 172, 666, 0,0'; ./xxx
        # perl -e 'syscall 172, 666, 0,1'; ./xxx
        # perl -e 'syscall 172, 666, 1,0'; ./xxx
        # perl -e 'syscall 172, 666, 1,1'; ./xxx

and dmesg reports:

        XXX disable_step=0, clear_flag=0
        XXX: xxx/1868 0
        [... 799 times ...]
        XXX disable_step=0, clear_flag=1
        XXX: xxx/1905 0
        [... 799 times ...]
        XXX disable_step=1, clear_flag=0
        XXX disable_step=1, clear_flag=1

Just in case, I did the testing with and without CONFIG_UTRACE,
result is the same.

IOW, copy_thread()->clear_tsk_thread_flag(TIF_SINGLE_STEP) doesn't
make any difference, copy_process()->user_disable_single_step() does.

Although I need to re-read Martin's explanations about psw magic,
perhaps this was already explained...

Oleg.

--- K/kernel/sys.c~     2010-01-21 14:16:15.366639654 -0500
+++ K/kernel/sys.c      2010-01-21 14:30:35.131591879 -0500
@@ -1453,6 +1453,8 @@ SYSCALL_DEFINE1(umask, int, mask)
        return mask;
 }
 
+int xxx_disable_step, xxx_clear_flag;
+
 SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
                unsigned long, arg4, unsigned long, arg5)
 {
@@ -1466,6 +1468,13 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
 
        error = 0;
        switch (option) {
+               case 666:
+                       xxx_disable_step = arg2;
+                       xxx_clear_flag = arg3;
+                       printk(KERN_INFO "XXX disable_step=%d, clear_flag=%d\n",
+                               xxx_disable_step, xxx_clear_flag);
+                       break;
+
                case PR_SET_PDEATHSIG:
                        if (!valid_signal(arg2)) {
                                error = -EINVAL;
--- K/kernel/fork.c~    2010-01-18 09:35:16.823811008 -0500
+++ K/kernel/fork.c     2010-01-21 14:29:39.131624971 -0500
@@ -964,6 +964,8 @@ static void posix_cpu_timers_init(struct
        INIT_LIST_HEAD(&tsk->cpu_timers[2]);
 }
 
+extern int xxx_disable_step;
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -1207,7 +1209,8 @@ static struct task_struct *copy_process(
         * Syscall tracing and stepping should be turned off in the
         * child regardless of CLONE_PTRACE.
         */
-       user_disable_single_step(p);
+       if (xxx_disable_step)
+               user_disable_single_step(p);
        clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
 #ifdef TIF_SYSCALL_EMU
        clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
--- K/arch/s390/kernel/process.c~       2010-01-21 14:32:38.541609793 -0500
+++ K/arch/s390/kernel/process.c        2010-01-21 14:34:10.461584130 -0500
@@ -161,6 +161,8 @@ void release_thread(struct task_struct *
 {
 }
 
+extern int xxx_clear_flag;
+
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
                unsigned long unused,
                struct task_struct *p, struct pt_regs *regs)
@@ -217,7 +219,8 @@ int copy_thread(unsigned long clone_flag
        p->thread.mm_segment = get_fs();
        /* Don't copy debug registers */
        memset(&p->thread.per_info, 0, sizeof(p->thread.per_info));
-       clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
+       if (xxx_clear_flag)
+               clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
        /* Initialize per thread user and system timer values */
        ti = task_thread_info(p);
        ti->user_timer = 0;

Reply via email to