From owner-freebsd-bugs@FreeBSD.ORG Sun Dec 27 20:10:02 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5CB9C1065672 for ; Sun, 27 Dec 2009 20:10:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 3A8328FC18 for ; Sun, 27 Dec 2009 20:10:02 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id nBRKA2ts022314 for ; Sun, 27 Dec 2009 20:10:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id nBRKA2RZ022313; Sun, 27 Dec 2009 20:10:02 GMT (envelope-from gnats) Resent-Date: Sun, 27 Dec 2009 20:10:02 GMT Resent-Message-Id: <200912272010.nBRKA2RZ022313@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Gleb Kurtsou Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 75DCC1065670 for ; Sun, 27 Dec 2009 20:02:05 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 65C548FC17 for ; Sun, 27 Dec 2009 20:02:05 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id nBRK25eK016748 for ; Sun, 27 Dec 2009 20:02:05 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id nBRK25I2016747; Sun, 27 Dec 2009 20:02:05 GMT (envelope-from nobody) Message-Id: <200912272002.nBRK25I2016747@www.freebsd.org> Date: Sun, 27 Dec 2009 20:02:05 GMT From: Gleb Kurtsou To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/142082: [patch] [panic] linuxulator: getppid: use after free X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Dec 2009 20:10:02 -0000 >Number: 142082 >Category: kern >Synopsis: [patch] [panic] linuxulator: getppid: use after free >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Dec 27 20:10:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Gleb Kurtsou >Release: >Organization: >Environment: FreeBSD tops 9.0-CURRENT FreeBSD 9.0-CURRENT #0 r199870+5a33f3d: Thu Dec 24 08:46:34 EET 2009 root@tops:/usr/obj/usr/freebsd-src/local/sys/TOPS amd64 >Description: Process that caused panic was skype. I've seen the panic only once. Looks like one threads calls exec while another calls getppid. emuldata is getting freed by exec handler, but pointer to it remains active for a small period of time (proc struct gets unlocked). Unread portion of the kernel message buffer: Fatal trap 9: general protection fault while in kernel mode cpuid = 0; apic id = 00 instruction pointer = 0x20:0xffffffff8053cffe stack pointer = 0x28:0xffffff80e605eb00 frame pointer = 0x28:0xffffff80e605eb30 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 15730 (bash) trap number = 9 panic: general protection fault cpuid = 0 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2a panic() at panic+0x17d trap_fatal() at trap_fatal+0x2ad trap() at trap+0xfa calltrap() at calltrap+0x8 --- trap 0x9, rip = 0xffffffff8053cffe, rsp = 0xffffff80e605eb00, rbp = 0xffffff80e605eb30 --- linux_getppid() at linux_getppid+0x141 ia32_syscall() at ia32_syscall+0x15f Xint0x80_syscall() at Xint0x80_syscall+0x95 --- syscall (64, Linux ELF32, linux_getppid), rip = 0x281e1777, rsp = 0xffffd5ec, rbp = 0xffffd618 --- Uptime: 2h26m34s Physical memory: 3047 MB Dumping 2645 MB: 2630 2614 (CTRL-C to abort) (CTRL-C to abort) (CTRL-C to abort) (CTRL-C to abort) 2598 2582 2566 2550 2534 2518 2502 2486 2470 2454 2438 2422 2406 2390 2374 2358 2342 2326 2310 2294 2278 2262 2246 2230 2214 2198 2182 2166 2150 2134 2118 2102 2086 2070 2054 2038 2022 2006 1990 1974 1958 1942 1926 1910 1894 1878 1862 1846 1830 1814 1798 1782 1766 1750 1734 1718 1702 1686 1670 1654 1638 1622 1606 1590 1574 1558 1542 1526 1510 1494 1478 1462 1446 1430 1414 1398 1382 1366 1350 1334 1318 1302 1286 1270 1254 1238 1222 1206 1190 1174 1158 1142 1126 1110 1094 1078 1062 1046 1030 1014 998 982 966 950 934 918 902 886 870 854 838 822 806 790 774 758 742 726 710 694 678 662 646 630 614 598 582 566 550 534 518 502 486 470 454 438 422 406 390 374 358 342 326 310 294 278 262 246 230 214 198 182 166 150 134 118 102 86 70 54 38 22 6 Reading symbols from /boot/kernel/zfs.ko...Reading symbols from /.bootfs/boot/kernel/zfs.ko.symbols...done. done. Loaded symbols for /boot/kernel/zfs.ko Reading symbols from /boot/kernel/opensolaris.ko...Reading symbols from /.bootfs/boot/kernel/opensolaris.ko.symbols...done. done. Loaded symbols for /boot/kernel/opensolaris.ko Reading symbols from /boot/modules/nvidia.ko...done. Loaded symbols for /boot/modules/nvidia.ko Reading symbols from /boot/kernel/linprocfs.ko...Reading symbols from /.bootfs/boot/kernel/linprocfs.ko.symbols...done. done. Loaded symbols for /boot/kernel/linprocfs.ko Reading symbols from /boot/kernel/tmpfs.ko...Reading symbols from /.bootfs/boot/kernel/tmpfs.ko.symbols...done. done. Loaded symbols for /boot/kernel/tmpfs.ko Reading symbols from /boot/kernel/pf.ko...Reading symbols from /.bootfs/boot/kernel/pf.ko.symbols...done. done. Loaded symbols for /boot/kernel/pf.ko Reading symbols from /boot/kernel/pefs.ko...Reading symbols from /.bootfs/boot/kernel/pefs.ko.symbols...done. done. Loaded symbols for /boot/kernel/pefs.ko #0 doadump () at pcpu.h:223 223 pcpu.h: No such file or directory. in pcpu.h (kgdb) bt #0 doadump () at pcpu.h:223 #1 0xffffffff803273fd in boot (howto=260) at /usr/freebsd-src/local/sys/kern/kern_shutdown.c:416 #2 0xffffffff8032787b in panic (fmt=Variable "fmt" is not available. ) at /usr/freebsd-src/local/sys/kern/kern_shutdown.c:579 #3 0xffffffff80504403 in trap_fatal (frame=0x9, eva=Variable "eva" is not available. ) at /usr/freebsd-src/local/sys/amd64/amd64/trap.c:858 #4 0xffffffff80504d5c in trap (frame=0xffffff80e605ea50) at /usr/freebsd-src/local/sys/amd64/amd64/trap.c:647 #5 0xffffffff804ebe93 in calltrap () at /usr/freebsd-src/local/sys/amd64/amd64/exception.S:224 #6 0xffffffff8053cffe in linux_getppid (td=0xffffff0005dafa80, args=Variable "args" is not available. ) at /usr/freebsd-src/local/sys/compat/linux/linux_misc.c:1588 #7 0xffffffff80527bb2 in ia32_syscall (frame=0xffffff80e605ec80) at /usr/freebsd-src/local/sys/amd64/ia32/ia32_syscall.c:182 #8 0xffffffff804ec395 in Xint0x80_syscall () at ia32_exception.S:72 #9 0x00000000281e1777 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 6 #6 0xffffffff8053cffe in linux_getppid (td=0xffffff0005dafa80, args=Variable "args" is not available. ) at /usr/freebsd-src/local/sys/compat/linux/linux_misc.c:1588 warning: Source file is more recent than executable. 1588 td->td_retval[0] = em->shared->group_pid; (kgdb) l 1583 /* if its also linux process */ 1584 if (pp->p_sysent == &elf_linux_sysvec) { 1585 em = em_find(pp, EMUL_DONTLOCK); 1586 KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); 1587 1588 td->td_retval[0] = em->shared->group_pid; 1589 } else 1590 td->td_retval[0] = pp->p_pid; 1591 1592 PROC_UNLOCK(pp); (kgdb) p *em $1 = {pid = -559038242, child_set_tid = 0xdeadc0dedeadc0de, child_clear_tid = 0xdeadc0dedeadc0de, shared = 0xdeadc0dedeadc0de, pdeath_signal = -559038242, used_requeue = -559038242, robust_futexes = 0xdeadc0dedeadc0de, threads = {le_next = 0xdeadc0dedeadc0de, le_prev = 0xffffffff80a3c500}} (kgdb) p (struct linux_emuldata *)p->p_emul There is no member named p_emul. (kgdb) p (struct linux_emuldata *)p->p_emuldata $2 = (struct linux_emuldata *) 0xffffff003e8a8240 (kgdb) p (struct linux_emuldata *)p->p_emuldata $3 = {pid = 15730, child_set_tid = 0x0, child_clear_tid = 0x0, shared = 0xffffff005ed3a160, pdeath_signal = 0, used_requeue = 0, robust_futexes = 0x0, threads = {le_next = 0x0, le_prev = 0xffffff005ed3a168}} (kgdb) p *(struct linux_emuldata *)p->p_emuldata $4 = {pid = -559038242, child_set_tid = 0xdeadc0dedeadc0de, child_clear_tid = 0xdeadc0dedeadc0de, shared = 0xdeadc0dedeadc0de, pdeath_signal = -559038242, used_requeue = -559038242, robust_futexes = 0xdeadc0dedeadc0de, threads = {le_next = 0xdeadc0dedeadc0de, le_prev = 0xffffffff80a3c500}} (kgdb) p/x p->p_flag $5 = 0x10004000 ^^^ P_EXEC (kgdb) p/x pp->p_flag $6 = 0x10002000 ^^^ P_WEXIT >How-To-Repeat: >Fix: Patch set p->emuldata=NULL after free and checks p->emuldata!=NULL in getppid instead of panicing. Patch attached with submission follows: diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c index dc81553..88c0064 100644 --- a/sys/compat/linux/linux_emul.c +++ b/sys/compat/linux/linux_emul.c @@ -203,6 +203,7 @@ linux_proc_exit(void *arg __unused, struct proc *p) error = copyout(&null, child_clear_tid, sizeof(null)); if (error) { free(em, M_LINUX); + p->p_emuldata = NULL; return; } @@ -224,6 +225,7 @@ linux_proc_exit(void *arg __unused, struct proc *p) /* clean the stuff up */ free(em, M_LINUX); + p->p_emuldata = NULL; /* this is a little weird but rewritten from exit1() */ sx_xlock(&proctree_lock); @@ -286,6 +288,7 @@ linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp) EMUL_SHARED_WUNLOCK(&emul_shared_lock); free(em, M_LINUX); + p->p_emuldata = NULL; } } diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 1d5eaf8..bd8be89 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1581,10 +1581,8 @@ linux_getppid(struct thread *td, struct linux_getppid_args *args) PROC_UNLOCK(p); /* if its also linux process */ - if (pp->p_sysent == &elf_linux_sysvec) { - em = em_find(pp, EMUL_DONTLOCK); - KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); - + if (pp->p_sysent == &elf_linux_sysvec && + (em = em_find(pp, EMUL_DONTLOCK)) != NULL) { td->td_retval[0] = em->shared->group_pid; } else td->td_retval[0] = pp->p_pid; >Release-Note: >Audit-Trail: >Unformatted: