From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, Oleg Nesterov <oleg@redhat.com>,
Salman Qazi <sqazi@google.com>,
Suleiman Souhlal <suleiman@google.com>,
Linus Torvalds <torvalds@linux-foundation.org>
Subject: [ 36/66] ptrace: ensure arch_ptrace/ptrace_request can never race with SIGKILL
Date: Sun, 17 Feb 2013 22:50:37 +0000 [thread overview]
Message-ID: <20130217225005.814374232@decadent.org.uk> (raw)
In-Reply-To: <20130217225001.621306883@decadent.org.uk>
3.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <oleg@redhat.com>
commit 9899d11f654474d2d54ea52ceaa2a1f4db3abd68 upstream.
putreg() assumes that the tracee is not running and pt_regs_access() can
safely play with its stack. However a killed tracee can return from
ptrace_stop() to the low-level asm code and do RESTORE_REST, this means
that debugger can actually read/modify the kernel stack until the tracee
does SAVE_REST again.
set_task_blockstep() can race with SIGKILL too and in some sense this
race is even worse, the very fact the tracee can be woken up breaks the
logic.
As Linus suggested we can clear TASK_WAKEKILL around the arch_ptrace()
call, this ensures that nobody can ever wakeup the tracee while the
debugger looks at it. Not only this fixes the mentioned problems, we
can do some cleanups/simplifications in arch_ptrace() paths.
Probably ptrace_unfreeze_traced() needs more callers, for example it
makes sense to make the tracee killable for oom-killer before
access_process_vm().
While at it, add the comment into may_ptrace_stop() to explain why
ptrace_stop() still can't rely on SIGKILL and signal_pending_state().
Reported-by: Salman Qazi <sqazi@google.com>
Reported-by: Suleiman Souhlal <suleiman@google.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
arch/x86/kernel/step.c | 9 ++++---
kernel/ptrace.c | 64 ++++++++++++++++++++++++++++++++++++++++--------
kernel/signal.c | 5 ++++
3 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index cd3b243..9b4d51d 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -165,10 +165,11 @@ void set_task_blockstep(struct task_struct *task, bool on)
* Ensure irq/preemption can't change debugctl in between.
* Note also that both TIF_BLOCKSTEP and debugctl should
* be changed atomically wrt preemption.
- * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
- * wrong if task != current, SIGKILL can wakeup the stopped
- * tracee and set/clear can play with the running task, this
- * can confuse the next __switch_to_xtra().
+ *
+ * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if
+ * task is current or it can't be running, otherwise we can race
+ * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but
+ * PTRACE_KILL is not safe.
*/
local_irq_disable();
debugctl = get_debugctlmsr();
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 62f7c27..6cbeaae 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -122,6 +122,40 @@ void __ptrace_unlink(struct task_struct *child)
spin_unlock(&child->sighand->siglock);
}
+/* Ensure that nothing can wake it up, even SIGKILL */
+static bool ptrace_freeze_traced(struct task_struct *task)
+{
+ bool ret = false;
+
+ /* Lockless, nobody but us can set this flag */
+ if (task->jobctl & JOBCTL_LISTENING)
+ return ret;
+
+ spin_lock_irq(&task->sighand->siglock);
+ if (task_is_traced(task) && !__fatal_signal_pending(task)) {
+ task->state = __TASK_TRACED;
+ ret = true;
+ }
+ spin_unlock_irq(&task->sighand->siglock);
+
+ return ret;
+}
+
+static void ptrace_unfreeze_traced(struct task_struct *task)
+{
+ if (task->state != __TASK_TRACED)
+ return;
+
+ WARN_ON(!task->ptrace || task->parent != current);
+
+ spin_lock_irq(&task->sighand->siglock);
+ if (__fatal_signal_pending(task))
+ wake_up_state(task, __TASK_TRACED);
+ else
+ task->state = TASK_TRACED;
+ spin_unlock_irq(&task->sighand->siglock);
+}
+
/**
* ptrace_check_attach - check whether ptracee is ready for ptrace operation
* @child: ptracee to check for
@@ -151,24 +185,29 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
* be changed by us so it's not changing right after this.
*/
read_lock(&tasklist_lock);
- if ((child->ptrace & PT_PTRACED) && child->parent == current) {
+ if (child->ptrace && child->parent == current) {
+ WARN_ON(child->state == __TASK_TRACED);
/*
* child->sighand can't be NULL, release_task()
* does ptrace_unlink() before __exit_signal().
*/
- spin_lock_irq(&child->sighand->siglock);
- WARN_ON_ONCE(task_is_stopped(child));
- if (ignore_state || (task_is_traced(child) &&
- !(child->jobctl & JOBCTL_LISTENING)))
+ if (ignore_state || ptrace_freeze_traced(child))
ret = 0;
- spin_unlock_irq(&child->sighand->siglock);
}
read_unlock(&tasklist_lock);
- if (!ret && !ignore_state)
- ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
+ if (!ret && !ignore_state) {
+ if (!wait_task_inactive(child, __TASK_TRACED)) {
+ /*
+ * This can only happen if may_ptrace_stop() fails and
+ * ptrace_stop() changes ->state back to TASK_RUNNING,
+ * so we should not worry about leaking __TASK_TRACED.
+ */
+ WARN_ON(child->state == __TASK_TRACED);
+ ret = -ESRCH;
+ }
+ }
- /* All systems go.. */
return ret;
}
@@ -900,6 +939,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
goto out_put_task_struct;
ret = arch_ptrace(child, request, addr, data);
+ if (ret || request != PTRACE_DETACH)
+ ptrace_unfreeze_traced(child);
out_put_task_struct:
put_task_struct(child);
@@ -1039,8 +1080,11 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
ret = ptrace_check_attach(child, request == PTRACE_KILL ||
request == PTRACE_INTERRUPT);
- if (!ret)
+ if (!ret) {
ret = compat_arch_ptrace(child, request, addr, data);
+ if (ret || request != PTRACE_DETACH)
+ ptrace_unfreeze_traced(child);
+ }
out_put_task_struct:
put_task_struct(child);
diff --git a/kernel/signal.c b/kernel/signal.c
index 6e97aa6..3d09cf6 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1794,6 +1794,10 @@ static inline int may_ptrace_stop(void)
* If SIGKILL was already sent before the caller unlocked
* ->siglock we must see ->core_state != NULL. Otherwise it
* is safe to enter schedule().
+ *
+ * This is almost outdated, a task with the pending SIGKILL can't
+ * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported
+ * after SIGKILL was already dequeued.
*/
if (unlikely(current->mm->core_state) &&
unlikely(current->mm == current->parent->mm))
@@ -1919,6 +1923,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
if (gstop_done)
do_notify_parent_cldstop(current, false, why);
+ /* tasklist protects us from ptrace_freeze_traced() */
__set_current_state(TASK_RUNNING);
if (clear_code)
current->exit_code = 0;
next prev parent reply other threads:[~2013-02-17 23:00 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-17 22:50 [ 00/66] 3.2.39-stable review Ben Hutchings
2013-02-17 22:50 ` [ 01/66] drm/i915: Fix misplaced intel_mark_page_flip_active() Ben Hutchings
2013-02-17 22:50 ` [ 02/66] xhci: Fix isoc TD encoding Ben Hutchings
2013-02-17 22:50 ` [ 03/66] xhci: Fix TD size for isochronous URBs Ben Hutchings
2013-02-17 22:50 ` [ 04/66] USB: XHCI: fix memory leak of URB-private data Ben Hutchings
2013-02-17 22:50 ` [ 05/66] usb: Prevent dead ports when xhci is not enabled Ben Hutchings
2013-02-17 22:50 ` [ 06/66] sched/rt: Use root_domain of rt_rq not current processor Ben Hutchings
2013-02-17 22:50 ` [ 07/66] rtlwifi: Fix the usage of the wrong variable in usb.c Ben Hutchings
2013-02-17 22:50 ` [ 08/66] drm/radeon: add quirk for RV100 board Ben Hutchings
2013-02-17 22:50 ` [ 09/66] USB: qcserial: add Telit Gobi QDL device Ben Hutchings
2013-02-17 22:50 ` [ 10/66] USB: option: add support for Telit LE920 Ben Hutchings
2013-02-17 22:50 ` [ 11/66] mwifiex: fix incomplete scan in case of IE parsing error Ben Hutchings
2013-02-17 22:50 ` [ 12/66] USB: EHCI: fix bug in scheduling periodic split transfers Ben Hutchings
2013-02-17 22:50 ` [ 13/66] x86-64: Replace left over sti/cli in ia32 audit exit code Ben Hutchings
2013-02-17 22:50 ` [ 14/66] Bluetooth: Fix handling of unexpected SMP PDUs Ben Hutchings
2013-02-17 22:50 ` [ 15/66] drm/radeon: Calling object_unrefer() when creating fb failure Ben Hutchings
2013-02-17 22:50 ` [ 16/66] drm/radeon: prevent crash in the ring space allocation Ben Hutchings
2013-02-17 22:50 ` [ 17/66] can: c_can: Set reserved bit in IFx_MASK2 to 1 on write Ben Hutchings
2013-02-17 22:50 ` [ 18/66] USB: ftdi_sio: add PID/VID entries for ELV WS 300 PC II Ben Hutchings
2013-02-17 22:50 ` [ 19/66] USB: option: add Changhong CH690 Ben Hutchings
2013-02-17 22:50 ` [ 20/66] USB: ftdi_sio: add Zolix FTDI PID Ben Hutchings
2013-02-17 22:50 ` [ 21/66] USB: storage: Define a new macro for USB storage match rules Ben Hutchings
2013-02-17 22:50 ` [ 22/66] USB: storage: optimize to match the Huawei USB storage devices and support new switch command Ben Hutchings
2013-02-17 22:50 ` [ 23/66] nilfs2: fix fix very long mount time issue Ben Hutchings
2013-02-17 22:50 ` [ 24/66] drivers/rtc/rtc-isl1208.c: call rtc_update_irq() from the alarm irq handler Ben Hutchings
2013-02-17 22:50 ` [ 25/66] drivers/rtc/rtc-pl031.c: fix the missing operation on enable Ben Hutchings
2013-02-17 22:50 ` [ 26/66] virtio_console: Dont access uninitialized data Ben Hutchings
2013-02-17 22:50 ` [ 27/66] wireless: rt2x00: rt{2500,73}usb.c put back duplicate id Ben Hutchings
2013-02-17 22:50 ` [ 28/66] Wireless: rt2x00: Add device id for Sweex LW323 to rt2800usb.c Ben Hutchings
2013-02-17 22:50 ` [ 29/66] rt2800usb: Add support for 2001:3c1e (D-Link DWA-125 rev B1) USB Wi-Fi adapter Ben Hutchings
2013-02-17 22:50 ` [ 30/66] [media] gspca_kinect: add Kinect for Windows USB id Ben Hutchings
2013-02-17 22:50 ` [ 31/66] ahci: support the STA2X11 I/O Hub Ben Hutchings
2013-02-17 22:50 ` [ 32/66] [libata] ahci: Add support for Enmotus Bobcat device Ben Hutchings
2013-02-17 22:50 ` [ 33/66] ptrace/x86: Introduce set_task_blockstep() helper Ben Hutchings
2013-02-17 22:50 ` [ 34/66] ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic Ben Hutchings
2013-02-17 22:50 ` [ 35/66] ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up() Ben Hutchings
2013-02-17 22:50 ` Ben Hutchings [this message]
2013-02-17 22:50 ` [ 37/66] wake_up_process() should be never used to wakeup a TASK_STOPPED/TRACED task Ben Hutchings
2013-02-17 22:50 ` [ 38/66] Bluetooth: Fix sending HCI commands after reset Ben Hutchings
2013-02-17 22:50 ` [ 39/66] HID: usbhid: quirk for Formosa IR receiver Ben Hutchings
2013-02-17 22:50 ` [ 40/66] kernel/resource.c: fix stack overflow in __reserve_region_with_split() Ben Hutchings
2013-02-17 22:50 ` [ 41/66] net: prevent setting ttl=0 via IP_TTL Ben Hutchings
2013-02-17 22:50 ` [ 42/66] ipv6: fix the noflags test in addrconf_get_prefix_route Ben Hutchings
2013-02-17 22:50 ` [ 43/66] MAINTAINERS: Stephen Hemminger email change Ben Hutchings
2013-02-17 22:50 ` [ 44/66] ipv6: fix header length calculation in ip6_append_data() Ben Hutchings
2013-02-17 22:50 ` [ 45/66] isdn/gigaset: fix zero size border case in debug dump Ben Hutchings
2013-02-17 22:50 ` [ 46/66] netxen: fix off by one bug in netxen_release_tx_buffer() Ben Hutchings
2013-02-17 22:50 ` [ 47/66] r8169: remove the obsolete and incorrect AMD workaround Ben Hutchings
2013-02-17 22:50 ` [ 48/66] net: loopback: fix a dst refcounting issue Ben Hutchings
2013-02-17 22:50 ` [ 49/66] pktgen: correctly handle failures when adding a device Ben Hutchings
2013-02-17 22:50 ` [ 50/66] ipv6: do not create neighbor entries for local delivery Ben Hutchings
2013-02-17 22:50 ` [ 51/66] packet: fix leakage of tx_ring memory Ben Hutchings
2013-02-17 22:50 ` [ 52/66] atm/iphase: rename fregt_t -> ffreg_t Ben Hutchings
2013-02-17 22:50 ` [ 53/66] sctp: refactor sctp_outq_teardown to insure proper re-initalization Ben Hutchings
2013-02-17 22:50 ` [ 54/66] net: sctp: sctp_setsockopt_auth_key: use kzfree instead of kfree Ben Hutchings
2013-02-17 22:50 ` [ 55/66] net: sctp: sctp_endpoint_free: zero out secret key data Ben Hutchings
2013-02-17 22:50 ` [ 56/66] xen/netback: shutdown the ring if it contains garbage Ben Hutchings
2013-02-17 22:50 ` [ 57/66] xen/netback: dont leak pages on failure in xen_netbk_tx_check_gop Ben Hutchings
2013-02-17 22:50 ` [ 58/66] xen/netback: free already allocated memory on failure in xen_netbk_get_requests Ben Hutchings
2013-02-17 22:51 ` [ 59/66] netback: correct netbk_tx_err to handle wrap around Ben Hutchings
2013-02-17 22:51 ` [ 60/66] tcp: frto should not set snd_cwnd to 0 Ben Hutchings
2013-02-17 22:51 ` [ 61/66] tcp: fix for zero packets_in_flight was too broad Ben Hutchings
2013-02-17 22:51 ` [ 62/66] tcp: fix MSG_SENDPAGE_NOTLAST logic Ben Hutchings
2013-02-17 22:51 ` [ 63/66] bridge: Pull ip header into skb->data before looking into ip header Ben Hutchings
2013-02-17 22:51 ` [ 64/66] tg3: Avoid null pointer dereference in tg3_interrupt in netconsole mode Ben Hutchings
2013-02-17 22:51 ` [ 65/66] tg3: Fix crc errors on jumbo frame receive Ben Hutchings
2013-02-17 22:51 ` [ 66/66] x86/xen: dont assume %ds is usable in xen_iret for 32-bit PVOPS Ben Hutchings
2013-02-18 0:02 ` [ 00/66] 3.2.39-stable review Ben Hutchings
2013-02-19 22:25 ` Satoru Takeuchi
2013-02-20 2:59 ` Ben Hutchings
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130217225005.814374232@decadent.org.uk \
--to=ben@decadent.org.uk \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oleg@redhat.com \
--cc=sqazi@google.com \
--cc=stable@vger.kernel.org \
--cc=suleiman@google.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox