From patchwork Fri Dec 4 10:03:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 57704 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp450663lbb; Fri, 4 Dec 2015 02:04:08 -0800 (PST) X-Received: by 10.66.227.129 with SMTP id sa1mr20149960pac.132.1449223448364; Fri, 04 Dec 2015 02:04:08 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id tb10si18517890pab.83.2015.12.04.02.04.08; Fri, 04 Dec 2015 02:04:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756030AbbLDKEF (ORCPT + 28 others); Fri, 4 Dec 2015 05:04:05 -0500 Received: from foss.arm.com ([217.140.101.70]:53144 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755969AbbLDKD7 (ORCPT ); Fri, 4 Dec 2015 05:03:59 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 71C0E3A8; Fri, 4 Dec 2015 02:03:38 -0800 (PST) Received: from arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 126FC3F267; Fri, 4 Dec 2015 02:03:57 -0800 (PST) Date: Fri, 4 Dec 2015 10:03:58 +0000 From: Will Deacon To: John Blackwood Cc: linux-kernel@vger.kernel.org, oleg@redhat.com, fweisbec@gmail.com Subject: Re: [PATCH] ARM64: Clear out any singlestep state on a ptrace detach operation Message-ID: <20151204100357.GA26172@arm.com> References: <5660A08B.6030204@ccur.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <5660A08B.6030204@ccur.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Dec 03, 2015 at 02:05:31PM -0600, John Blackwood wrote: > Hello Will, Hi John, Thanks for the patch. > I have a patch for a ptrace(2) issue that we encountered on arm64 kernels. > If a debugger singlesteps a ptraced task, and then does a ptrace(2) > PTRACE_DETACH command, the task will not resume successfully. It seems > that clearing out the singlestep state, as something like a ptrace(2) > PTRACE_CONT does, gets this working. > > Thank you for your time and considerations. I think you're correct that we should be doing this, but actually, why isn't this done by the core code? It looks to me like this should be part of ptrace_detach, just like it is part of ptrace_resume when a PTRACE_CONT request is handled. That would also be a step towards making ptrace_disable optional (since x86 and powerpc are doing stuff that could be done in core code too). I hacked up a quick patch below (not even compile-tested), but I'm not sure what to do about hardware {break,watch}points. Some architectures explicitly clear those on detach, whereas others appear to leave them alone. Thoughts? Will --->8 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index d9ee81769899..05feb398b7bb 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -260,16 +260,6 @@ void user_disable_single_step(struct task_struct *child) ptrace_cancel_bpt(child); } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure the single step bit is not set. - */ -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 4442204fe238..8b0aa193ab11 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -210,10 +210,6 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_arc_view; } -void ptrace_disable(struct task_struct *child) -{ -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index ef9119f7462e..b839e6f10ef5 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -190,14 +190,6 @@ put_user_reg(struct task_struct *task, int offset, long data) } /* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ - /* Nothing to do. */ -} - -/* * Handle hitting a breakpoint. */ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 1971f491bb90..ff5a743afe10 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -53,13 +53,6 @@ * in exit.c or in signal.c. */ -/* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ -} - #ifdef CONFIG_HAVE_HW_BREAKPOINT /* * Handle hitting a HW-breakpoint. diff --git a/arch/avr32/include/asm/ptrace.h b/arch/avr32/include/asm/ptrace.h index 630e4f9bf5f0..ae2b3531d9b0 100644 --- a/arch/avr32/include/asm/ptrace.h +++ b/arch/avr32/include/asm/ptrace.h @@ -17,6 +17,7 @@ #define arch_has_single_step() (1) #define arch_ptrace_attach(child) ocd_enable(child) +#define arch_ptrace_detach(child) ocd_disable(child) #define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER) #define instruction_pointer(regs) ((regs)->pc) diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 4aedcab7cd4b..4233ff8c1d32 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c @@ -51,19 +51,8 @@ void user_enable_single_step(struct task_struct *tsk) void user_disable_single_step(struct task_struct *child) { - /* XXX(hch): a no-op here seems wrong.. */ -} - -/* - * Called by kernel/ptrace.c when detaching - * - * Make sure any single step bits, etc. are not set - */ -void ptrace_disable(struct task_struct *child) -{ clear_tsk_thread_flag(child, TIF_SINGLE_STEP); clear_tsk_thread_flag(child, TIF_BREAKPOINT); - ocd_disable(child); } /* diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h index c00491594b46..6fc6f0b61511 100644 --- a/arch/blackfin/include/asm/ptrace.h +++ b/arch/blackfin/include/asm/ptrace.h @@ -15,8 +15,6 @@ #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1))) #define arch_has_single_step() (1) -/* common code demands this function */ -#define ptrace_disable(child) user_disable_single_step(child) #define current_user_stack_pointer() rdusp() extern int is_user_addr_valid(struct task_struct *child, diff --git a/arch/c6x/kernel/ptrace.c b/arch/c6x/kernel/ptrace.c index 3c494e84444d..62083738c1bc 100644 --- a/arch/c6x/kernel/ptrace.c +++ b/arch/c6x/kernel/ptrace.c @@ -20,14 +20,6 @@ #define PT_REG_SIZE (sizeof(struct pt_regs)) /* - * Called by kernel/ptrace.c when detaching. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do */ -} - -/* * Get a register number from live pt_regs for the specified task. */ static inline long get_reg(struct task_struct *task, int regno) diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index bfddfb99401f..923f3569b38a 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -55,18 +55,6 @@ inline int put_reg(struct task_struct *task, unsigned int regno, return 0; } -/* - * Called by kernel/ptrace.c when detaching. - * - * Make sure the single step bit is not set. - */ -void -ptrace_disable(struct task_struct *child) -{ - /* Todo - pending singlesteps? */ - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -} - /* * Note that this implementation of ptrace behaves differently from vanilla * ptrace. Contrary to what the man page says, in the PTRACE_PEEKTEXT, diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index f085229cf870..2fa464eef608 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -29,7 +29,6 @@ static int put_debugreg(long pid, unsigned int regno, long data); static long get_debugreg(long pid, unsigned int regno); static unsigned long get_pseudo_pc(struct task_struct *child); -void deconfigure_bp(long pid); extern unsigned long cris_signal_return_page; @@ -106,23 +105,6 @@ void user_disable_single_step(struct task_struct *child) } } -/* - * Called by kernel/ptrace.c when detaching. - * - * Make sure the single step bit is not set. - */ -void -ptrace_disable(struct task_struct *child) -{ - /* Deconfigure SPC and S-bit. */ - user_disable_single_step(child); - put_reg(child, PT_SPC, 0); - - /* Deconfigure any watchpoints associated with the child. */ - deconfigure_bp(child->pid); -} - - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/cris/include/asm/ptrace.h b/arch/cris/include/asm/ptrace.h index 9e788d04a4ef..01cfd4e3bf63 100644 --- a/arch/cris/include/asm/ptrace.h +++ b/arch/cris/include/asm/ptrace.h @@ -11,4 +11,9 @@ #define profile_pc(regs) instruction_pointer(regs) #define current_user_stack_pointer() rdusp() +#ifdef CONFIG_ETRAX_ARCH_V32 +void deconfigure_bp(long pid); +#define arch_ptrace_detach(child) deconfigure_bp(child->pid); +#endif /* CONFIG_ETRAX_ARCH_V32 */ + #endif /* _CRIS_PTRACE_H */ diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index 3987ff88dab0..bd04ae38e640 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -248,11 +248,6 @@ void user_disable_single_step(struct task_struct *child) child->thread.frame0->__status &= ~REG__STATUS_STEP; } -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index 92075544a19a..da23531e8050 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -154,11 +154,6 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_h8300_native_view; } -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c index 390a9ad14ca1..39c35c82afe9 100644 --- a/arch/hexagon/kernel/ptrace.c +++ b/arch/hexagon/kernel/ptrace.c @@ -192,12 +192,6 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &hexagon_user_view; } -void ptrace_disable(struct task_struct *child) -{ - /* Boilerplate - resolves to null inline if no HW single-step */ - user_disable_single_step(child); -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 6f54d511cc50..cd68bb684ec1 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1137,17 +1137,6 @@ user_disable_single_step (struct task_struct *child) child_psr->tb = 0; } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure the single step bit is not set. - */ -void -ptrace_disable (struct task_struct *child) -{ - user_disable_single_step(child); -} - long arch_ptrace (struct task_struct *child, long request, unsigned long addr, unsigned long data) diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 51f5e9aa4901..69a006094645 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -609,16 +609,6 @@ void user_disable_single_step(struct task_struct *child) invalidate_cache(); } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do.. */ -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 1bc10e62b9af..04b4cb07372b 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -130,14 +130,6 @@ static inline void singlestep_disable(struct task_struct *child) clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); } -/* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ - singlestep_disable(child); -} - void user_enable_single_step(struct task_struct *child) { unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c index 7563628822bd..ae9db2e0f574 100644 --- a/arch/metag/kernel/ptrace.c +++ b/arch/metag/kernel/ptrace.c @@ -367,16 +367,6 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_metag_view; } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do.. */ -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index 8cfa98cadf3d..b77c5d5efc7b 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -162,8 +162,3 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); } - -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do */ -} diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index f6fc6aac5496..12b84503bf6f 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -191,4 +191,6 @@ static inline void user_stack_pointer_set(struct pt_regs *regs, regs->regs[29] = val; } +#define arch_ptrace_detach(child) clear_tsk_thread_flag(child, TIF_LOAD_WATCH) + #endif /* _ASM_PTRACE_H */ diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 4f0ac78d17f1..53891dc334e0 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -69,17 +69,6 @@ static void init_fp_ctx(struct task_struct *target) } /* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* Don't load the watchpoint registers for the ex-child. */ - clear_tsk_thread_flag(child, TIF_LOAD_WATCH); -} - -/* * Read a general register set. We always use the 64-bit format, even * for 32-bit kernels and for 32-bit processes on a 64-bit kernel. * Registers are sign extended to fill the available space. diff --git a/arch/mn10300/kernel/ptrace.c b/arch/mn10300/kernel/ptrace.c index 5bd58514e739..a5adcd1914cb 100644 --- a/arch/mn10300/kernel/ptrace.c +++ b/arch/mn10300/kernel/ptrace.c @@ -286,11 +286,6 @@ void user_disable_single_step(struct task_struct *child) #endif } -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - /* * handle the arch-specific side of process tracing */ diff --git a/arch/nios2/kernel/ptrace.c b/arch/nios2/kernel/ptrace.c index 681dda92eff1..7da1fa5f0b26 100644 --- a/arch/nios2/kernel/ptrace.c +++ b/arch/nios2/kernel/ptrace.c @@ -138,11 +138,6 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &nios2_user_view; } -void ptrace_disable(struct task_struct *child) -{ - -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c index 4f59fa4e34e5..8ddb36b46ab0 100644 --- a/arch/openrisc/kernel/ptrace.c +++ b/arch/openrisc/kernel/ptrace.c @@ -142,20 +142,6 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) * in exit.c or in signal.c. */ - -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure the single step bit is not set. - */ -void ptrace_disable(struct task_struct *child) -{ - pr_debug("ptrace_disable(): TODO\n"); - - user_disable_single_step(child); - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 9585c81f755f..0cbdcecbca07 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -31,11 +31,10 @@ #define USER_PSW_BITS (PSW_N | PSW_B | PSW_V | PSW_CB) /* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. + * The following functions are called by ptrace_resume() when + * enabling or disabling single/block tracing. */ -void ptrace_disable(struct task_struct *task) +void user_disable_single_step(struct task_struct *task) { clear_tsk_thread_flag(task, TIF_SINGLESTEP); clear_tsk_thread_flag(task, TIF_BLOCKSTEP); @@ -47,15 +46,6 @@ void ptrace_disable(struct task_struct *task) pa_psw(task)->l = 0; } -/* - * The following functions are called by ptrace_resume() when - * enabling or disabling single/block tracing. - */ -void user_disable_single_step(struct task_struct *task) -{ - ptrace_disable(task); -} - void user_enable_single_step(struct task_struct *task) { clear_tsk_thread_flag(task, TIF_BLOCKSTEP); @@ -73,7 +63,7 @@ void user_enable_single_step(struct task_struct *task) pa_psw(task)->y = 0; pa_psw(task)->z = 0; pa_psw(task)->b = 0; - ptrace_disable(task); + user_disable_single_step(task); /* Don't wake up the task, but let the parent know something happened. */ si.si_code = TRAP_TRACE; diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 737c0d0b53ac..9080469ee684 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -1056,17 +1056,6 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, return 0; } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* make sure the single step bit is not set. */ - user_disable_single_step(child); -} - #ifdef CONFIG_PPC_ADV_DEBUG_REGS static long set_instruction_bp(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 37cbc50947f2..60f10335d820 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -148,6 +148,9 @@ static inline int test_pt_regs_flag(struct pt_regs *regs, int flag) #define arch_has_single_step() (1) #define arch_has_block_step() (1) +void arch_ptrace_detach(struct task_struct *task); +#define arch_ptrace_detach arch_ptrace_detach + #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define user_stack_pointer(regs)((regs)->gprs[15]) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 01c37b36caf9..a7ac6e44531f 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -121,11 +121,10 @@ void user_enable_block_step(struct task_struct *task) * * Clear all debugging related fields. */ -void ptrace_disable(struct task_struct *task) +void arch_ptrace_detach(struct task_struct *task) { memset(&task->thread.per_user, 0, sizeof(task->thread.per_user)); memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); - clear_tsk_thread_flag(task, TIF_SINGLE_STEP); clear_pt_regs_flag(task_pt_regs(task), PIF_PER_TRAP); task->thread.per_flags = 0; } diff --git a/arch/score/kernel/ptrace.c b/arch/score/kernel/ptrace.c index 55836188b217..3ef83188450d 100644 --- a/arch/score/kernel/ptrace.c +++ b/arch/score/kernel/ptrace.c @@ -319,11 +319,6 @@ void user_disable_single_step(struct task_struct *child) child->thread.ss_nextcnt = 0; } -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index c1a6b89bfe70..d036e820f677 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -125,16 +125,6 @@ void user_disable_single_step(struct task_struct *child) clear_tsk_thread_flag(child, TIF_SINGLESTEP); } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - static int genregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 5cea973a65b2..1e6be45b6f24 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -566,13 +566,3 @@ BUILD_TRAP_HANDLER(breakpoint) force_sig(SIGTRAP, current); regs->pc += 4; } - -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c index a331fdc11a2c..52f5cea94e01 100644 --- a/arch/sparc/kernel/ptrace_32.c +++ b/arch/sparc/kernel/ptrace_32.c @@ -30,16 +30,6 @@ /* #define ALLOW_INIT_TRACING */ -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do */ -} - enum sparc_regset { REGSET_GENERAL, REGSET_FP, diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 9ddc4928a089..022127c824d8 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -46,16 +46,6 @@ /* #define ALLOW_INIT_TRACING */ -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do */ -} - /* To get the necessary page struct, access_process_vm() first calls * get_user_pages(). This has done a flush_dcache_page() on the * accessed page. Then our caller (copy_{to,from}_user_page()) did diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index bdc126faf741..6d5fbf1cc5bb 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c @@ -40,20 +40,6 @@ void user_disable_single_step(struct task_struct *child) } /* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); - - /* - * These two are currently unused, but will be set by arch_ptrace() - * and used in the syscall assembly when we do support them. - */ - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -} - -/* * Get registers from task and ready the result for userspace. * Note that we localize the API issues to getregs() and putregs() at * some cost in performance, e.g. we need a full pt_regs copy for diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 6a826cbb15c4..2e7e0597de8a 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -30,14 +30,6 @@ void user_disable_single_step(struct task_struct *child) #endif } -/* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - extern int peek_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data); diff --git a/arch/unicore32/kernel/ptrace.c b/arch/unicore32/kernel/ptrace.c index 9f07c08da050..4e46339db6f0 100644 --- a/arch/unicore32/kernel/ptrace.c +++ b/arch/unicore32/kernel/ptrace.c @@ -51,13 +51,6 @@ put_user_reg(struct task_struct *task, int offset, long data) } /* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ -} - -/* * We actually access the pt_regs stored on the kernel stack. */ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 558f50edebca..8277c5e37279 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -793,19 +793,6 @@ static int ioperm_get(struct task_struct *target, 0, IO_BITMAP_BYTES); } -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure the single step bit is not set. - */ -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -#ifdef TIF_SYSCALL_EMU - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); -#endif -} - #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION static const struct user_regset_view user_x86_32_view; /* Initialized below. */ #endif diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 4d54b481123b..2496b5325452 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -40,15 +40,6 @@ void user_disable_single_step(struct task_struct *child) child->ptrace &= ~PT_SINGLESTEP; } -/* - * Called by kernel/ptrace.c when detaching to disable single stepping. - */ - -void ptrace_disable(struct task_struct *child) -{ - /* Nothing to do.. */ -} - int ptrace_getregs(struct task_struct *child, void __user *uregs) { struct pt_regs *regs = task_pt_regs(child); diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 061265f92876..e04a1367f9ff 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -46,7 +46,6 @@ extern long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); -extern void ptrace_disable(struct task_struct *); extern int ptrace_request(struct task_struct *child, long request, unsigned long addr, unsigned long data); extern void ptrace_notify(int exit_code); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index b760bae64cf1..1b61ecea4857 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -454,13 +454,20 @@ static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) return dead; } +#ifndef arch_ptrace_detach +#define arch_ptrace_detach(child) do { } while (0) +#endif + static int ptrace_detach(struct task_struct *child, unsigned int data) { if (!valid_signal(data)) return -EIO; - /* Architecture-specific hardware disable .. */ - ptrace_disable(child); + arch_ptrace_detach(child); + user_disable_single_step(child); +#ifdef TIF_SYSCALL_EMU + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); +#endif clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); write_lock_irq(&tasklist_lock);