NetBSD Problem Report #43681

From www@NetBSD.org  Wed Jul 28 11:20:59 2010
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id D78BE63BB39
	for <gnats-bugs@gnats.NetBSD.org>; Wed, 28 Jul 2010 11:20:58 +0000 (UTC)
Message-Id: <20100728112058.842E363BB37@www.NetBSD.org>
Date: Wed, 28 Jul 2010 11:20:58 +0000 (UTC)
From: aanisimov@inbox.ru
Reply-To: aanisimov@inbox.ru
To: gnats-bugs@NetBSD.org
Subject: PT_SYSCALL appears to be broken
X-Send-Pr-Version: www-1.0

>Number:         43681
>Category:       kern
>Synopsis:       PT_SYSCALL appears to be broken
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jul 28 11:25:00 +0000 2010
>Closed-Date:    Sun Jun 17 19:48:13 +0000 2012
>Last-Modified:  Sun Jun 17 19:48:13 +0000 2012
>Originator:     Artem Anisimov
>Release:        -current
>Organization:
>Environment:
NetBSD netbsd-i386.vault13 5.99.37 NetBSD 5.99.37 (GENERIC) #0: Tue Jul 13 00:15:02 MSD 2010  artem@netbsd-i386.vault13:/home/artem/obj/sys/arch/i386/compile/GENERIC i386
>Description:
I've been experimenting with ptrace() and found out that simply following man (2) ptrace is not enough.

  The attached problem is supposed to run "/bin/ls /" and stop at every system call it makes. The problem is that ptrace(PT_SYSCALL,...) at the end of the main loop seems simply to resume the child and make it run until it exits, but not until it makes a system call.

  Attached program works as expected under FreeBSD and Linux, so I believe there is some detail that needs to be taken into account for NetBSD and that I have missed.

  I've posted a question regarding usage of PT_SYSCALL to tech-kern and Christos Zoulas suggested that I file a bug report.

  Here is a program in question:

--------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <errno.h>

#if defined(BSD)
        #define REQ_TRACE_ME    PT_TRACE_ME
        #define REQ_SYSCALL     PT_SYSCALL
        #define REQ_KILL        PT_KILL
        #define CONT_ADDR       (caddr_t)1
#elif defined(LINUX)
        #define REQ_TRACE_ME    PTRACE_TRACEME
        #define REQ_SYSCALL     PTRACE_SYSCALL
        #define REQ_KILL        PTRACE_KILL
        #define CONT_ADDR       NULL
#else
        #error "Define BSD or LINUX."
#endif

static void __attribute__((noreturn)) die(const char *msg)
{
        printf("%s, errno=%d\n",msg,errno);
        _exit(1);
}

static void child()
{
const char      *args[] =       {"/bin/ls","/",NULL};
const char      *env[]  =       {NULL};

        if(0>ptrace(REQ_TRACE_ME,0,NULL,0))
                die("failed to trace myself");

        execve(args[0],(char * const *)args,(char * const *)env);
        die("failed to start the child");
}

int main()
{
pid_t   p;
int     status;
int     sig;

        p=fork();
        if(p<0)
                die("failed to fork");

        if(!p)
                child();

        for(;;)
        {
                if(0>waitpid(p,&status,0))
                        die("failed to wait for child");
                if(WIFSTOPPED(status))
                {
                        sig=WSTOPSIG(status);
                        printf("child stopped by signal %d (%s)\n",sig,strsignal(sig));
                        if(sig!=SIGTRAP)
                        {
                                printf("signal is not SIGTRAP; killing 
child\n");
                                if(0>ptrace(REQ_KILL,p,NULL,0))
                                        die("failed to kill the child");
                                break;
                        }
                }
                else if(WIFSIGNALED(status))
                {
                        sig=WTERMSIG(status);
                        printf("child was signaled by signal %d (%d)\n",
                                sig,strsignal(sig));
                        if(0>ptrace(REQ_KILL,p,NULL,0))
                                die("failed to kill the child");
                        break;
                }
                else if(WIFEXITED(status))
                {
                        printf("child exited with status 
%d\n",WEXITSTATUS(status));
                        break;
                }
                else
                {
                        printf("neither stopped, nor signaled, nor killed?\n");
                        if(0>ptrace(PT_KILL,p,NULL,0))
                                die("failed to kill the child");
                        break;
                }

                printf("resuming the child\n");
                if(0>ptrace(REQ_SYSCALL,p,CONT_ADDR,0))
                        die("failed to resume the child");
        }

        return 0;
}

>How-To-Repeat:
Compile the attached program and run it.
>Fix:

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: kern-bug-people->jmcneill
Responsible-Changed-By: jmcneill@NetBSD.org
Responsible-Changed-When: Mon, 29 Aug 2011 17:32:56 +0000
Responsible-Changed-Why:
I just checked in a fix for this, can you re-test?


State-Changed-From-To: open->feedback
State-Changed-By: jmcneill@NetBSD.org
State-Changed-When: Mon, 29 Aug 2011 17:32:56 +0000
State-Changed-Why:


From: "Jared D. McNeill" <jmcneill@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/43681 CVS commit: src/sys/kern
Date: Mon, 29 Aug 2011 17:31:51 +0000

 Module Name:	src
 Committed By:	jmcneill
 Date:		Mon Aug 29 17:31:51 UTC 2011

 Modified Files:
 	src/sys/kern: sys_process.c

 Log Message:
 PR# kern/43681: PT_SYSCALL appears to be broken

 sys_ptrace: For PT_CONTINUE/PT_SYSCALL/PT_DETACH, modify the p_trace_enabled
 flag of the target process, not the calling process.


 To generate a diff of this commit:
 cvs rdiff -u -r1.157 -r1.158 src/sys/kern/sys_process.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: =?utf-8?b?0JDRgNGC0LXQvCDQkNC90LjRgdC40LzQvtCy?= <aanisimov@inbox.ru>
To: gnats-bugs@gnats.netbsd.org
Cc: 
Subject: Re: kern/43681
Date: Mon, 5 Sep 2011 09:40:15 +0400

 Re-tested. Now ptrace() works as expected.

State-Changed-From-To: feedback->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Mon, 05 Sep 2011 08:21:29 +0000
State-Changed-Why:
Confirmed fixed ,thanks.


State-Changed-From-To: closed->pending-pullups
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sat, 05 Nov 2011 13:05:44 +0000
State-Changed-Why:
pullup-5 #1668


Responsible-Changed-From-To: jmcneill->kern-bug-people
Responsible-Changed-By: spz@NetBSD.org
Responsible-Changed-When: Tue, 24 Jan 2012 21:57:01 +0000
Responsible-Changed-Why:
back to group
.


From: "Manuel Bouyer" <bouyer@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/43681 CVS commit: [netbsd-5] src/sys
Date: Sat, 4 Feb 2012 16:58:00 +0000

 Module Name:	src
 Committed By:	bouyer
 Date:		Sat Feb  4 16:58:00 UTC 2012

 Modified Files:
 	src/sys/arch/amd64/amd64 [netbsd-5]: syscall.c
 	src/sys/arch/i386/i386 [netbsd-5]: syscall.c trap.c
 	src/sys/kern [netbsd-5]: kern_sig.c kern_sleepq.c kern_subr.c
 	    sys_process.c
 	src/sys/secmodel/bsd44 [netbsd-5]: secmodel_bsd44_suser.c
 	src/sys/sys [netbsd-5]: proc.h ptrace.h

 Log Message:
 Apply patch, requested by jmcneill in ticket #1668:
 	sys/arch/amd64/amd64/syscall.c			patch
 	sys/arch/i386/i386/syscall.c			patch
 	sys/arch/i386/i386/trap.c			patch
 	sys/kern/kern_sig.c				patch
 	sys/kern/kern_sleepq.c				patch
 	sys/kern/kern_subr.c				patch
 	sys/kern/sys_process.c				patch
 	sys/secmodel/bsd44/secmodel_bsd44_suser.c	patch
 	sys/sys/proc.h					patch
 	sys/sys/ptrace.h				patch

 arch/i386/i386/machdep.c, arch/amd64/amd64/machdep.c (from
 arch/x86/x86/machdep.c) by christos:
 Remove code that was used to avoid register spills. setcontext(2) can change
 the registers, so re-fetching will produce the wrong result for trace_exit().
 arch/i386/i386/trap.c by reinoud:
 Fix the illegal instruction return address. It was using the value of the
 cpu's %cr2 register but thats not valid:

 CR2 Contains a value called Page Fault Linear Address (PFLA). When a page
 fault occurs, the address the program attempted to access is stored in the CR2
 register.

 And this is thus NOT the illegal instruction address!
 kern/kern_sig.c by christos:
 PR kern/45327: Jared McNeill: ptrace: siginfo doesn't work with traced processes
 When saving the signal in p->p_xstat, clear it from the pending mask, but
 don't remove it from the siginfo queue, so that next time the debugger
 delivers it, the original information is found.
 When posting a signal from the debugger l->l_sigpendset is not set, so we
 use the process pending signal and add it back to the process pending set.
 Split sigget into sigget() and siggetinfo(). When a signal comes from the
 debugger (l->l_sigpendset == NULL), using siggetinfo() try to fetch the
 siginfo information from l->l_sigpend and then from p->p_sigpend if it
 was not found. This allows us to pass siginfo information for traps from
 the debugger.
 don't delete signal from the debugger.
 kern/kern_sleepq.c by christos:
 PR kern/40594: Antti Kantee: Don't call issignal() here to determine what errno
 to set for the interrupted syscall, because issignal() will consume the signal
 and it will not be delivered to the process afterwards. Instead call
 sigispending() (which now returns the first pending signal) and does not
 consume the signal.
 We need to process SA_STOP signals immediately, and not deliver them to
 the process. Instead of re-structuring the code to do that, call issignal()
 like before in that case. (tail -F /file^Zfg should not get interrupted).
 kern/kern_subr.c by jmcneill, christos:
 PR kern/45312: ptrace: PT_SETREGS can't alter system calls

 Add a new PT_SYSCALLEMU request that cancels the current syscall, for
 use with PT_SYSCALL.
 For PT_SYSCALLEMU, no need to stop again on syscall exit.
 ifdef unused variable with -UPTRACE

 kern/sys_process.c, sys/proc.h, sys/ptrace.h, secmodel/bsd44/secmodel_bsd44_suser.c by jmcneill, christos:
 PR kern/43681: PT_SYSCALL appears to be broken

 sys_ptrace: For PT_CONTINUE/PT_SYSCALL/PT_DETACH, modify the p_trace_enabled
 flag of the target process, not the calling process.
 Process the signal now, otherwise calling issignal() and ignoring
 the return will lose the signal if it came from the debugger
 (issignal() clears p->p_xstat)
 PR kern/45312: ptrace: PT_SETREGS can't alter system calls

 Add a new PT_SYSCALLEMU request that cancels the current syscall, for
 use with PT_SYSCALL.
 PR kern/45330: ptrace: signals can alter syscall return values

 process_stoptrace: defer signal processing to userret, ok christos@


 To generate a diff of this commit:
 cvs rdiff -u -r1.44 -r1.44.4.1 src/sys/arch/amd64/amd64/syscall.c
 cvs rdiff -u -r1.57 -r1.57.4.1 src/sys/arch/i386/i386/syscall.c
 cvs rdiff -u -r1.241.4.3 -r1.241.4.4 src/sys/arch/i386/i386/trap.c
 cvs rdiff -u -r1.289.4.6 -r1.289.4.7 src/sys/kern/kern_sig.c
 cvs rdiff -u -r1.35 -r1.35.4.1 src/sys/kern/kern_sleepq.c
 cvs rdiff -u -r1.192.4.1 -r1.192.4.2 src/sys/kern/kern_subr.c
 cvs rdiff -u -r1.143.4.1 -r1.143.4.2 src/sys/kern/sys_process.c
 cvs rdiff -u -r1.59 -r1.59.4.1 src/sys/secmodel/bsd44/secmodel_bsd44_suser.c
 cvs rdiff -u -r1.282 -r1.282.4.1 src/sys/sys/proc.h
 cvs rdiff -u -r1.40 -r1.40.20.1 src/sys/sys/ptrace.h

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: pending-pullups->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sun, 17 Jun 2012 19:48:13 +0000
State-Changed-Why:
pullup was done in february and I've been behind on cleaning up


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.