From owner-freebsd-hackers@FreeBSD.ORG Fri May 14 12:57:37 2010 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F2567106564A; Fri, 14 May 2010 12:57:37 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from mail.zoral.com.ua (mx0.zoral.com.ua [91.193.166.200]) by mx1.freebsd.org (Postfix) with ESMTP id 126EA8FC1A; Fri, 14 May 2010 12:57:36 +0000 (UTC) Received: from deviant.kiev.zoral.com.ua (root@deviant.kiev.zoral.com.ua [10.1.1.148]) by mail.zoral.com.ua (8.14.2/8.14.2) with ESMTP id o4ECviq0081185 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 14 May 2010 15:57:44 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: from deviant.kiev.zoral.com.ua (kostik@localhost [127.0.0.1]) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4) with ESMTP id o4ECvVnN023328; Fri, 14 May 2010 15:57:31 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: (from kostik@localhost) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4/Submit) id o4ECvVsi023327; Fri, 14 May 2010 15:57:31 +0300 (EEST) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: deviant.kiev.zoral.com.ua: kostik set sender to kostikbel@gmail.com using -f Date: Fri, 14 May 2010 15:57:31 +0300 From: Kostik Belousov To: John Baldwin Message-ID: <20100514125731.GP83316@deviant.kiev.zoral.com.ua> References: <20100508111509.GB8186@harikalardiyari> <20100508123626.GC83316@deviant.kiev.zoral.com.ua> <20100509053303.GD8186@harikalardiyari> <20100509135807.GH83316@deviant.kiev.zoral.com.ua> <20100509182851.GE8186@harikalardiyari> <20100509214359.GJ83316@deviant.kiev.zoral.com.ua> <20100510164847.GF8186@harikalardiyari> <20100510170947.GP83316@deviant.kiev.zoral.com.ua> <20100511103500.GH8186@harikalardiyari> <4BED2B27.2020902@FreeBSD.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="9rkt7tfZQigMla7f" Content-Disposition: inline In-Reply-To: <4BED2B27.2020902@FreeBSD.org> User-Agent: Mutt/1.4.2.3i X-Virus-Scanned: clamav-milter 0.95.2 at skuns.kiev.zoral.com.ua X-Virus-Status: Clean X-Spam-Status: No, score=-2.4 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_50, DNS_FROM_OPENWHOIS autolearn=no version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on skuns.kiev.zoral.com.ua Cc: Ali Polatel , freebsd-hackers@freebsd.org Subject: Re: Ability to tell the difference between normal and syscall traps X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 May 2010 12:57:38 -0000 --9rkt7tfZQigMla7f Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, May 14, 2010 at 06:51:19AM -0400, John Baldwin wrote: > Ali Polatel wrote: > >Kostik Belousov yazm????: > >>On Mon, May 10, 2010 at 07:48:47PM +0300, Ali Polatel wrote: > >>>Another question is how hard is it to implement PL_EVENT_EXEC? > >>>This could be useful for truss as it updates the execution type of the > >>>process after successful execve() calls afaict. > >>Is this needed ? The question is not rhetorical, I am trying to > >>understand what prevents use of PT_TO_SCE and checking the syscall > >>number ? You would screen for SYS_execve or SYS_fexecve and > >>reset the debugger state on SIGTRAP that is supplied to the debugger > >>before first instruction of new image is executed. > >> > > > >Not really needed, just cleaner imo. As system call numbers may be > >different for different execution types and you need to look it up from > >a table using a string as argument which is slow. >=20 > I agree that this would be cleaner. Having worked on the ptrace/procfs= =20 > stuff in other tools like strace and truss, exec truly is an important=20 > event to a debugger aside from just being another system call as it=20 > signals that the address space has been changed. Ok, I would not much object. But I finally tired of adding the same code to three places (ignoring !x86 arches). diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index d5ddc59..39eb435 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -170,7 +170,7 @@ static int prot_fault_translation =3D 0; SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW, &prot_fault_translation, 0, "Select signal to deliver on protection fault= "); =20 -extern char *syscallnames[]; +extern const char *syscallnames[]; =20 /* * Exception, fault, and trap interface to the FreeBSD kernel. @@ -884,7 +884,7 @@ syscall(struct trapframe *frame) struct proc *p; struct syscall_args sa; register_t orig_tf_rflags; - int error; + int error, traced; ksiginfo_t ksi; =20 PCPU_INC(cnt.v_syscall); @@ -905,10 +905,13 @@ syscall(struct trapframe *frame) cred_update_thread(td); orig_tf_rflags =3D frame->tf_rflags; if (p->p_flag & P_TRACED) { + traced =3D 1; PROC_LOCK(p); td->td_dbgflags &=3D ~TDB_USERWR; + td->td_dbgflags |=3D TDB_SCE; PROC_UNLOCK(p); - } + } else + traced =3D 0; error =3D fetch_syscall_args(td, &sa); =20 CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td, @@ -961,6 +964,11 @@ syscall(struct trapframe *frame) #endif } retval: + if (traced) { + PROC_LOCK(p); + td->td_dbgflags &=3D ~TDB_SCE; + PROC_UNLOCK(p); + } cpu_set_syscall_retval(td, error); =20 /* @@ -975,40 +983,5 @@ syscall(struct trapframe *frame) trapsignal(td, &ksi); } =20 - /* - * Check for misbehavior. - */ - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???"); - KASSERT(td->td_critnest =3D=3D 0, - ("System call %s returning in a critical section", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???")); - KASSERT(td->td_locks =3D=3D 0, - ("System call %s returning with %d locks held", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???", td->td_locks)); - - /* - * Handle reschedule and other end-of-syscall issues - */ - userret(td, frame); - - CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td, - td->td_proc->p_pid, td->td_name, sa.code); - -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(sa.code, error, td->td_retval[0]); -#endif - - /* - * This works because errno is findable through the - * register set. If we ever support an emulation where this - * is not the case, this code will need to be revisited. - */ - STOPEVENT(p, S_SCX, sa.code); - - PTRACESTOP_SC(p, td, S_PT_SCX); + syscallret(td, error, sa.code, syscallnames); } diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index aa1ae6c..ad82210 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -170,7 +170,7 @@ ia32_syscall(struct trapframe *frame) struct proc *p; struct ia32_syscall_args sa; register_t orig_tf_rflags; - int error; + int error, traced; ksiginfo_t ksi; =20 PCPU_INC(cnt.v_syscall); @@ -184,10 +184,13 @@ ia32_syscall(struct trapframe *frame) cred_update_thread(td); orig_tf_rflags =3D frame->tf_rflags; if (p->p_flag & P_TRACED) { + traced =3D 1; PROC_LOCK(p); td->td_dbgflags &=3D ~TDB_USERWR; + td->td_dbgflags |=3D TDB_SCE; PROC_UNLOCK(p); - } + } else + traced =3D 0; error =3D fetch_ia32_syscall_args(td, &sa); =20 CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td, @@ -218,6 +221,11 @@ ia32_syscall(struct trapframe *frame) td->td_errno =3D error; } retval: + if (traced) { + PROC_LOCK(p); + td->td_dbgflags &=3D ~TDB_SCE; + PROC_UNLOCK(p); + } cpu_set_syscall_retval(td, error); =20 /* @@ -232,44 +240,9 @@ ia32_syscall(struct trapframe *frame) trapsignal(td, &ksi); } =20 - /* - * Check for misbehavior. - */ - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - freebsd32_syscallnames[sa.code] : "???"); - KASSERT(td->td_critnest =3D=3D 0, - ("System call %s returning in a critical section", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - freebsd32_syscallnames[sa.code] : "???")); - KASSERT(td->td_locks =3D=3D 0, - ("System call %s returning with %d locks held", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - freebsd32_syscallnames[sa.code] : "???", td->td_locks)); - - /* - * Handle reschedule and other end-of-syscall issues - */ - userret(td, frame); - - CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td, - td->td_proc->p_pid, td->td_proc->p_comm, sa.code); -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(sa.code, error, td->td_retval[0]); -#endif - - /* - * This works because errno is findable through the - * register set. If we ever support an emulation where this - * is not the case, this code will need to be revisited. - */ - STOPEVENT(p, S_SCX, sa.code); -=20 - PTRACESTOP_SC(p, td, S_PT_SCX); + syscallret(td, error, sa.code, freebsd32_syscallnames); } =20 - static void ia32_syscall_enable(void *dummy) { diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index a11daa6..35df54b 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -184,7 +184,7 @@ static int prot_fault_translation =3D 0; SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW, &prot_fault_translation, 0, "Select signal to deliver on protection fault= "); =20 -extern char *syscallnames[]; +extern const char *syscallnames[]; =20 /* * Exception, fault, and trap interface to the FreeBSD kernel. @@ -1051,7 +1051,7 @@ syscall(struct trapframe *frame) struct proc *p; struct syscall_args sa; register_t orig_tf_eflags; - int error; + int error, traced; ksiginfo_t ksi; =20 PCPU_INC(cnt.v_syscall); @@ -1072,10 +1072,13 @@ syscall(struct trapframe *frame) cred_update_thread(td); orig_tf_eflags =3D frame->tf_eflags; if (p->p_flag & P_TRACED) { + traced =3D 1; PROC_LOCK(p); td->td_dbgflags &=3D ~TDB_USERWR; + td->td_dbgflags |=3D TDB_SCE; PROC_UNLOCK(p); - } + } else + traced =3D 0; error =3D fetch_syscall_args(td, &sa); =20 CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td, @@ -1128,6 +1131,11 @@ syscall(struct trapframe *frame) #endif } retval: + if (traced) { + PROC_LOCK(p); + td->td_dbgflags &=3D ~TDB_SCE; + PROC_UNLOCK(p); + } cpu_set_syscall_retval(td, error); =20 /* @@ -1142,41 +1150,6 @@ syscall(struct trapframe *frame) trapsignal(td, &ksi); } =20 - /* - * Check for misbehavior. - */ - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???"); - KASSERT(td->td_critnest =3D=3D 0, - ("System call %s returning in a critical section", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???")); - KASSERT(td->td_locks =3D=3D 0, - ("System call %s returning with %d locks held", - (sa.code >=3D 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???", td->td_locks)); - - /* - * Handle reschedule and other end-of-syscall issues - */ - userret(td, frame); - - CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td, - td->td_proc->p_pid, td->td_name, sa.code); - -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(sa.code, error, td->td_retval[0]); -#endif - - /* - * This works because errno is findable through the - * register set. If we ever support an emulation where this - * is not the case, this code will need to be revisited. - */ - STOPEVENT(p, S_SCX, sa.code); - - PTRACESTOP_SC(p, td, S_PT_SCX); + syscallret(td, error, sa.code, syscallnames); } =20 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index fc87d63..149e6df 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -871,6 +871,10 @@ exec_fail_dealloc: free(imgp->freepath, M_TEMP); =20 if (error =3D=3D 0) { + PROC_LOCK(p); + td->td_dbgflags |=3D TDB_EXEC; + PROC_UNLOCK(p); + /* * Stop the process here if its stop event mask has * the S_EXEC bit set. diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 4d20ebd..ea6b0ae 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -58,9 +58,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include +#include #include #include #ifdef KTRACE @@ -253,3 +256,61 @@ ast(struct trapframe *framep) userret(td, framep); mtx_assert(&Giant, MA_NOTOWNED); } + +void +syscallret(struct thread *td, int error, u_int sa_code __unused, + const char *scnames[] __unused) +{ + struct proc *p; + int traced; + + p =3D td->td_proc; + + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (sa_code >=3D 0 && sa_code < SYS_MAXSYSCALL) ? + scnames[sa_code] : "???"); + KASSERT(td->td_critnest =3D=3D 0, + ("System call %s returning in a critical section", + (sa_code >=3D 0 && sa_code < SYS_MAXSYSCALL) ? + scnames[sa_code] : "???")); + KASSERT(td->td_locks =3D=3D 0, + ("System call %s returning with %d locks held", + (sa_code >=3D 0 && sa_code < SYS_MAXSYSCALL) ? + scnames[sa_code] : "???", td->td_locks)); + + /* + * Handle reschedule and other end-of-syscall issues + */ + userret(td, td->td_frame); + + CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td, + td->td_proc->p_pid, td->td_name, sa_code); + +#ifdef KTRACE + if (KTRPOINT(td, KTR_SYSRET)) + ktrsysret(sa_code, error, td->td_retval[0]); +#endif + + if (p->p_flag & P_TRACED) { + traced =3D 1; + PROC_LOCK(p); + td->td_dbgflags |=3D TDB_SCX; + PROC_UNLOCK(p); + } else + traced =3D 0; + /* + * This works because errno is findable through the + * register set. If we ever support an emulation where this + * is not the case, this code will need to be revisited. + */ + STOPEVENT(p, S_SCX, sa_code); + PTRACESTOP_SC(p, td, S_PT_SCX); + if (traced || (td->td_dbgflags & TDB_EXEC) !=3D 0) { + PROC_LOCK(p); + td->td_dbgflags &=3D ~(TDB_SCX | TDB_EXEC); + PROC_UNLOCK(p); + } +} diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index d8cc4f0..6decc02 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1105,9 +1105,13 @@ kern_ptrace(struct thread *td, int req, pid_t pid, v= oid *addr, int data) pl->pl_lwpid =3D td2->td_tid; if (td2->td_dbgflags & TDB_XSIG) pl->pl_event =3D PL_EVENT_SIGNAL; - else - pl->pl_event =3D 0; pl->pl_flags =3D 0; + if (td2->td_dbgflags & TDB_SCE) + pl->pl_flags |=3D PL_FLAG_SCE; + else if (td2->td_dbgflags & TDB_SCX) + pl->pl_flags |=3D PL_FLAG_SCX; + if (td2->td_dbgflags & TDB_EXEC) + pl->pl_flags |=3D PL_FLAG_EXEC; pl->pl_sigmask =3D td2->td_sigmask; pl->pl_siglist =3D td2->td_siglist; break; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index e32e494..c2b9f4a 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -364,6 +364,9 @@ do { \ #define TDB_SUSPEND 0x00000001 /* Thread is suspended by debugger */ #define TDB_XSIG 0x00000002 /* Thread is exchanging signal under trace */ #define TDB_USERWR 0x00000004 /* Debugger modified memory or registers */ +#define TDB_SCE 0x00000008 /* Thread performs syscall enter */ +#define TDB_SCX 0x00000010 /* Thread performs syscall exit */ +#define TDB_EXEC 0x00000020 /* TDB_SCX from exec(2) family */ =20 /* * "Private" flags kept in td_pflags: @@ -837,6 +840,7 @@ void cpu_switch(struct thread *, struct thread *, struc= t mtx *); void cpu_throw(struct thread *, struct thread *) __dead2; void unsleep(struct thread *); void userret(struct thread *, struct trapframe *); +void syscallret(struct thread *, int, u_int, const char *[]); =20 void cpu_exit(struct thread *); void exit1(struct thread *, int) __dead2; diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h index b30447c..a6dbe2c 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -99,6 +99,9 @@ struct ptrace_lwpinfo { int pl_flags; /* LWP flags. */ #define PL_FLAG_SA 0x01 /* M:N thread */ #define PL_FLAG_BOUND 0x02 /* M:N bound thread */ +#define PL_FLAG_SCE 0x04 /* syscall enter point */ +#define PL_FLAG_SCX 0x08 /* syscall leave point */ +#define PL_FLAG_EXEC 0x10 /* exec(2) succeeded */ sigset_t pl_sigmask; /* LWP signal mask */ sigset_t pl_siglist; /* LWP pending signal */ }; --9rkt7tfZQigMla7f Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (FreeBSD) iEYEARECAAYFAkvtSLoACgkQC3+MBN1Mb4iVmgCgzRauK+Y3x7gaHKyV262osh3Z 3D4AoMtpanSlq/21vCDALp0zc+zWABGv =EuVN -----END PGP SIGNATURE----- --9rkt7tfZQigMla7f--