MOKB-20-11-2006 OMG! PWNIES! M4C BUGS NOW COME IN P1NK!

Bug details
Title: Mac OS X Apple UDIF Disk Image Kernel Memory Corruption (1) Warning - wet floor!
Description: Mac OS X com.apple.AppleDiskImageController fails to properly handle corrupted DMG image structures, leading to an exploitable memory corruption condition with potential kernel-mode arbitrary code execution by unprivileged users.

This issue is remotely exploitable as Safari loads DMG files from external sources (ex. visiting an URL). This can be prevented by changing the Preferences and deactivating the functionality for 'opening "safe" files after downloading'.

Right now, Apple doesn't provide a public specification for the DMG format, nor source and/or API reference for com.apple.AppleDiskImageController. Although, the binary-form code can be found at /System/Library/Extensions/IOHDIXController.kext/Contents/MacOS/IOHDIXController.


Author/Contributor: NA<NA[at] info-pull.com> - discovery, MoKB release, debugging.
Kevin Finisterre <kf [at] digitalmunition.com> - moral support, forthcoming panty-less hookers, and other PPC debugging innuendo.
References:
Proof of concept or exploit: The following DMG image can be used to reproduce the bug: MOKB-20-11-2006.dmg.bz2
bunzip2 MOKB-20-11-2006.dmg.bz2 && hdiutil attach MOKB-20-11-2006.dmg
Kevin is hosting it uncompressed as well, for those Safari users feeling lucky, at: http://www.digitalmunition.com/MOKB-20.dmg
Debugging information:

It's been tested on an up-to-date (20-11-2006) Mac OS X installation, running on an Intel "shipping" Mac.

brubg:/tmp feuckstevo$ gdb /Volumes/KernelDebugKit/mach_kernel -c core-xnu-792.13.8-172.16.0.10-1d8d44d
GNU gdb 6.3.50-20050815 (Apple version gdb-573) (Fri Oct 20 15:50:43 GMT 2006)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...
#0  Debugger (message=0x3c9540 "panic") at /SourceCache/xnu/xnu-792.13.8/osfmk/i386/AT386/model_dep.c:770
Line number 770 out of range; /SourceCache/xnu/xnu-792.13.8/osfmk/i386/AT386/model_dep.c has 312 lines.
(gdb) bt
#0  Debugger (message=0x3c9540 "panic") at /SourceCache/xnu/xnu-792.13.8/osfmk/i386/AT386/model_dep.c:770
#1  0x00128d1f in panic (str=0x3ccb64 "pmap_enter: mapping not in pv_list!") at /SourceCache/xnu/xnu-792.13.8/osfmk/kern/debug.c:202
#2  0x0019447d in pmap_enter (pmap=0x4af700, vaddr=701254872, pn=17063, prot=7, flags=2, wired=0)
    at /SourceCache/xnu/xnu-792.13.8/osfmk/i386/pmap.c:2216
#3  0x00160aaf in vm_fault (map=0x13d1f3c, vaddr=701254872, fault_type=3, change_wiring=0, interruptible=0, caller_pmap=0x0,
    caller_pmap_addr=0) at /SourceCache/xnu/xnu-792.13.8/osfmk/vm/vm_fault.c:2426
#4  0x003a3571 in IOMemoryDescriptor::handleFault (this=0x2dba900, _pager=0x0, addressMap=0x13d1f3c, address=701254872,
    sourceOffset=216, length=1024, options=1) at /SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:2619
#5  0x003a3800 in IOMemoryDescriptor::doMap (this=0x2dba900, addressMap=0x13d1f3c, atAddress=0x13fd3eac, options=1,
    sourceOffset=0, length=1024) at /SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:2497
#6  0x003a317e in _IOMemoryMap::initWithDescriptor (this=0x2662fc0, _memory=0x2dba900, intoTask=0x25bada0, toAddress=0,
    _options=1, _offset=0, _length=1024) at /SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:2281
#7  0x003a4121 in IOMemoryDescriptor::makeMapping (this=0x2dba900, owner=0x2dba900, intoTask=0x25bada0, toAddress=0,
    options=1, offset=0, length=1024) at /SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:3179
#8  0x003a3e7f in IOMemoryDescriptor::map (this=0x2dba900, options=0) at
    /SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:2996
#9  0x29e6a7c1 in ?? ()
(gdb) info registers
eax            0x0      0
ecx            0x0      0
edx            0x0      0
ebx            0x1      1
esp            0x13fd3abc       0x13fd3abc
ebp            0x13fd3b48       0x13fd3b48
esi            0x1      1
edi            0x1000   4096
eip            0x1a8674 0x1a8674 
eflags         0x0      0
cs             0x0      0
ss             0x0      0
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) source /Volumes/KernelDebugKit/kgmacros
Loading Kernel GDB Macros package.  Type "help kgm" for more info.

(gdb) showcurrentstacks
task        vm_map      ipc_space  #acts   pid  proc        command
0x025bada0  0x013d1f3c  0x02584ef0   51      0  0x004d2200  kernel_task
            activation  thread      pri  state  wait_queue  wait_event
            0x02e32900  0x02e32900   81  R
                reserved_stack=0x13fd0000
                kernel_stack=0x13fd0000
                stacktop=0x13fd3b48
                0x13fd3b48  0x128d1f <panic+382>
                0x13fd3b88  0x19447d <pmap_enter+1054>
                0x13fd3c18  0x160aaf <vm_fault+1280>
                0x13fd3d68  0x3a3571 <IOMemoryDescriptor::handleFault(void*, vm_map*, unsigned int,
                                                                         unsigned long, unsigned long,
                                                                         unsigned long)+521>
                0x13fd3dd8  0x3a3800 <IOMemoryDescriptor::doMap(vm_map*, unsigned int*, unsigned long,
                                                                         unsigned long, unsigned long)+556>
                0x13fd3e48  0x3a317e <_IOMemoryMap::initWithDescriptor(IOMemoryDescriptor*, task*,
                                                                         unsigned int, unsigned long,
                                                                         unsigned long, unsigned long)+240>
                0x13fd3e98  0x3a4121 <IOMemoryDescriptor::makeMapping(IOMemoryDescriptor*, task*,
                                                                          unsigned int, unsigned long,
                                                                          unsigned long, unsigned long)+583>
                0x13fd3ef8  0x3a3e7f <IOMemoryDescriptor::map(unsigned long)+77>
                0x13fd3f38  0x29e6a7c1 <com.apple.AppleDiskImageController + 0xf7c1> <---------------

                0x13fd3fc8  0x19a74c <call_continuation+28>
                stackbottom=0x13fd3fc8

task        vm_map      ipc_space  #acts   pid  proc        command
0x025bada0  0x013d1f3c  0x02584ef0   51      0  0x004d2200  kernel_task
            activation  thread      pri  state  wait_queue  wait_event
            0x025d5f5c  0x025d5f5c    0  IR
                reserved_stack=0x13ea0000
                kernel_stack=0x13f08000
                stacktop=0x13f0bf18
                0x13f0bf18  0x1a42f5 <machine_idle_cstate+32>
                0x13f0bf38  0x19d871 <machine_idle+128>
                0x13f0bf58  0x135f23 <idle_thread+96>
                0x13f0bfc8  0x19a74c <call_continuation+28>
                stackbottom=0x13f0bfc8

--------
$ kextstat  | grep com.apple.AppleDiskImageController
   99    0 0x29e4b000 0x2c000    0x2b000    com.apple.AppleDiskImageController (113.3) <39 6 5 4 3 2>
--------

(gdb) paniclog
panic(cpu 0 caller 0x0019447D): pmap_enter: mapping not in pv_list!
Backtrace, Format - Frame : Return Address (4 potential args on stack)
0x13fd3b48 : 0x128d1f (0x3c9540 0x13fd3b6c 0x131df4 0x0)
0x13fd3b88 : 0x19447d (0x3ccb64 0x29cc4cd8 0x0 0x1a1ec0)
0x13fd3c18 : 0x160aaf (0x4af700 0x29cc4cd8 0x0 0x42a7)
0x13fd3d68 : 0x3a3571 (0x13d1f3c 0x29cc4cd8 0x0 0x3)
0x13fd3dd8 : 0x3a3800 (0x2dba900 0x0 0x13d1f3c 0x29cc4cd8)
0x13fd3e48 : 0x3a317e (0x2dba900 0x13d1f3c 0x13fd3eac 0x1)
0x13fd3e98 : 0x3a4121 (0x2662fc0 0x2dba900 0x25bada0 0x0)
0x13fd3ef8 : 0x3a3e7f (0x2dba900 0x2dba900 0x25bada0 0x0)
0x13fd3f38 : 0x29e6a7c1 (0x2dba900 0x0 0x0 0x2e3227c)
0x13fd3fc8 : 0x19a74c (0x2dc9500 0x0 0x19d0b5 0x2e32238) Backtrace terminated-invalid frame pointer 0x0
      Kernel loadable modules in backtrace (with dependencies):
         com.apple.AppleDiskImageController(113.3)@0x29e5b000
            dependency: com.apple.iokit.IOStorageFamily(1.5.1)@0x5ea000

Kernel version:
Darwin Kernel Version 8.8.1: Mon Sep 25 19:42:00 PDT 2006; root:xnu-792.13.8.obj~1/RELEASE_I386

(gdb) select-frame 8
Current language:  auto; currently c++
(gdb) info locals
this = (IOMemoryDescriptor * const) 0x2dba900
options = 1
(gdb) select-frame 9
(gdb) info locals
No symbol table info available.
(gdb) info registers
eax            0x0      0
ecx            0x0      0
edx            0x0      0
ebx            0xe00002ca       -536870198
esp            0x13fd3f40       0x13fd3f40
ebp            0x13fd3fc8       0x13fd3fc8
esi            0x264c380        40158080
edi            0x2dc9500        48010496
eip            0x29e6a7c1       0x29e6a7c1
eflags         0x0      0
cs             0x0      0
ss             0x0      0
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) x/5 $eip
0x29e6a7c1:     mov    %eax,-52(%ebp)
0x29e6a7c4:     test   %eax,%eax
0x29e6a7c6:     jne    0x29e6a7d1
0x29e6a7c8:     movl   $0x0,-84(%ebp)
0x29e6a7cf:     jmp    0x29e6a7e2

(gdb) list *0x003a3e7f
0x3a3e7f is in IOMemoryDescriptor::map(unsigned long) (/SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:2997).
2992            *length = 0;
2993
2994        if( offset >= _length)
2995            return( 0 );
2996
2997        address = _parent->getSourceSegment( offset + _start, &actualLength );
2998
2999        if( address && length)
3000            *length = min( _length - offset, actualLength );
3001

(gdb) frame 5
#5  0x003a3800 in IOMemoryDescriptor::doMap (this=0x2dba900, addressMap=0x13d1f3c,
    atAddress=0x13fd3eac, options=1, sourceOffset=0, length=1024) at
    /SourceCache/xnu/xnu-792.13.8/iokit/Kernel/IOMemoryDescriptor.cpp:2497
2497            memory->removeMapping( this);
(gdb) info registers
eax            0x0      0
ecx            0x0      0
edx            0x0      0
ebx            0xc00    3072
esp            0x13fd3de0       0x13fd3de0
ebp            0x13fd3e48       0x13fd3e48
esi            0x0      0
edi            0x2dba900        47950080
eip            0x3a3800 0x3a3800 <IOMemoryDescriptor::doMap(vm_map*, unsigned int*, unsigned long, unsigned long, unsigned long)+556>
eflags         0x0      0
cs             0x0      0
ss             0x0      0
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) info locals
this = (IOMemoryDescriptor * const) 0x2dba900
err = 0
pager = (memory_object_t) 0x0
logical = 0
pageOffset = 3072
ref = {
  sharedMem = 0x0,
  size = 4096,
  mapped = 701251584,
  sourceOffset = 0,
  options = 1
}
(gdb) showmap 0x13fd3eac
vm_map      pmap        vm_size    #ents rpage  hint        first_free
0x13fd3eac  0x13fd3ef8  0x0012d9b3  22207672  47950080  0x003a3eda  0x13fd3f38


(gdb) zprint
ZONE          COUNT   TOT_SZ   MAX_SZ ELT_SZ ALLOC_SZNAE
0x0152b000       95     2f80     3000     80     1000 zones X
0x0152df80     3654    79860    80000    136     1000 vm objects CX
0x0152df30     1115     5fa0    80000     20     1000 vm object hash entries CX
0x0152dee0       57     19c8     a000    100     3000 maps X
0x0152de90     3648    32f34   100000     44     1000 non-kernel map entries CX
0x0152de40      603   158ff0   159000     44     1000 kernel map entries
0x0152ddf0        0     1fe4     4000     52     2000 map copies CX
0x0152dda0       47     1ff0     b000    112     2000 pmap CX
0x0152dd50    16000    3f000    5a000     16     1000 pv_list CX
0x0152dd00       47     1000     7000     64     1000 pdpt CX
0x0152dcb0    21474    98000    99c60     16     1000 kalloc.16 CX
0x0152dc60    25917   14d000   16c800     32     1000 kalloc.32 CX
0x0152dc10    18527   17b000   1e6000     64     1000 kalloc.64 CX
0x0152dbc0     2988    63000    80000    128     1000 kalloc.128 CX
0x0152db70     2490    9d000   100000    256     1000 kalloc.256 CX
0x0152db20      338    2b000    80000    512     1000 kalloc.512 CX
0x0152dad0      334    57000   100000   1024     1000 kalloc.1024 CX
0x0152da80      121    44000   200000   2048     1000 kalloc.2048 CX
0x0152da30       65    43000   400000   4096     1000 kalloc.4096 CX
0x0152d9e0       50    70000  2000000   8192     2000 kalloc.8192 CX
0x0152d990   250915   a8841c        0     44     1000 vm pages HC
0x0152d940     1115     3000    10000      8     1000 mem_obj_control CX
0x0152d8f0       28      ff8    45000     28     1000 device node pager structures CX
0x0152d8a0       46     1ff8    17000     88     2000 ipc spaces CX
0x0152d850        1     1000   200000     32     1000 ipc tree entries CX
0x0152d800     1613    29970   509000    104     2000 ipc ports CX
0x0152d7b0       83     1fe0    38000     60     1000 ipc port sets HCX
0x0152d760       58     4000  c640000    256     1000 ipc kmsgs CX
0x0152d710      344     3ff0   111000     44     1000 semaphores CX
0x0152d6c0       28     1fd4    54000     84     2000 mk_timer CX
0x0152d670        1      ffc     c000     12     1000 host_notify CX
0x0152d620       44     9ea0    6c000    432     5000 tasks CX
0x0152d5d0      136    29f58   21f000    868     e000 threads CX
0x0152d580      137     5f50    3f000    100     3000 x86 saved state CX
0x0152d530        0        0    14000     32     1000 x86 debug state CX
0x0152d4e0       72     bfd0   14a000    528     4000 x86 fpsave state CX
0x0152d490      137     bec8    b9000    296     4000 uthreads CX
0x0152d440        0        0     1000     44     1000 alarms CX
0x0152d3f0      686     6078    7b000     36     1000 load_file_server H
0x0152d3a0        0        0   100000    256     1000 mbuf CX
0x0152d350       71     9e90   100000    344     5000 socket CX
0x0152d300        0     1fc8   100000     72     2000 zombie CX
0x0152d2b0        0     1000   100000   1024     1000 namei CX
0x0152d260        0        0   100000    128     1000 cred CX
0x0152d210       37      ff0   100000     24     1000 pgrp CX
0x0152d1c0       37     3f9c   100000    276     4000 session CX
0x0152d170        8     7e00   100000   2304     4000 mount CX
0x0152d120        0        0   100000     68     1000 NFS req CX
0x0152d0d0        3     2f88   100000    468     3000 NFS mount CX
0x0152d080        6     2fbc   100000    260     3000 NFS node CX
0x0152d030     2861    5ce8c   100000    132     1000 vnodes CX
0x0152cfe0     2475    1de20   100000     48     1000 namecache CX
0x0152cf90      316     2000   100000     16     1000 fileproc CX
0x0152cf40       43      ff0   100000     48     1000 file desc CX
0x0152cef0       43     6d60   100000    500     1000 proc CX
0x0152cea0       43     3f70   100000    280     2000 subproc CX
0x0152ce50        0        0   100000    212     4000 FFS node CX
0x0152ce00        0        0   100000     48     1000 NFS uid CX
0x0152cdb0        0        0   100000    136     1000 ISOFS node CX
0x0152cd60        0        0   100000    172     3000 NFSV3 srvdesc CX
0x0152cd10        0        0   100000    260     3000 NFSV3 diroff CX
0x0152ccc0        0        0   100000    264     2000 ttys CX
0x0152cc70       40     2000   100000    128     1000 ofile tabl CX
0x0152cc20        0        0   100000   2048     1000 mbuf clust CX
0x0152cbd0     2481    83844   100000    212     4000 HFS node CX
0x0152cb80     1352    23a60   100000    104     2000 HFS fork CX
0x0152cb30        0        0   100000     20     1000 VOLFS node CX
0x0152cae0        1     4f44   100000    228     5000 Journal CX
0x0152ca90        1     1fe4   100000     52     2000 Transaction CX
0x0152ca40      286     2fac   100000     36     1000 specinfo CX
0x0152c9f0        8     1ffc   100000     92     2000 kqueue CX
0x0152c9a0        7      fe4   100000     36     1000 HFS dirhint CX
0x0152c950      464     4000   100000     32     1000 cluster_read CX
0x0152c900       47     2fac   100000    108     3000 cluster_write CX
0x0152c8b0      213     5f50   100000    100     3000 fileglob CX
0x0152c860       16      ff0   100000     20     1000 unsafe_fsnode CX
0x0152c810        2     1000    10000    512     1000 buf.512 CX
0x0152c7c0        0        0    10000   1024     1000 buf.1024 CX
0x0152c770        0        0     8000   2048     1000 buf.2048 CX
0x0152c720       22    16000   200000   4096     1000 buf.4096 CX
0x0152c6d0        0        0     3000    144     3000 buf headers CX
0x0152c680     1080     9ee8    58000     36     1000 ubc_info zone CX
0x0152c630        0        0    2e000   1860     5000 audit_zone CX
0x0152c5e0       43     1fd4    a8000     84     2000 knote zone CX
0x0152c590        0        0     3000    136     1000 aiowq CX
0x0152c540        6     1fc8    90000     72     2000 pipe zone CX
0x0152c4f0       11     5e14  6615000    892     2000 socache zone CX
0x0152c4a0        0        0    1b000    108     3000 atpcb zone CX
0x0152c450       24     3f60   fdf000    208     2000 udpcb CX
0x0152c400        2     2fc8  3fa2000    556     3000 tcpcb CX
0x0152c3b0        0        0  3fa2000    556     3000 sack_hole zone CX
0x0152c360        0        0    1a000    208     2000 divzone CX
0x0152c310        2     1fb0    d0000    208     2000 ripzone CX
0x0152c2c0       43     1fe0   440000    136     1000 unpzone CX
0x0152c270     1080     5fa0    31000     20     1000 vnode pager structures CX
0x0152c220        0        0    c4000     80     1000 vstruct zone CX