secretsquirrel / google-security-research

Automatically exported from code.google.com/p/google-security-research
3 stars 0 forks source link

OS X IOKit kernel code execution due to NULL pointer dereference in IOHIKeyboardMapper::stickyKeysfree #41

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
When setting a new keyboard mapping the following code will be reached:

    IOHIKeyboardMapper * IOHIKeyboardMapper::keyboardMapper(
                                                            IOHIKeyboard * delegate,
                                                            const UInt8 *  mapping,
                                                            UInt32       mappingLength,
                                                            bool       mappingShouldBeFreed )
    {
      IOHIKeyboardMapper * me = new IOHIKeyboardMapper;

      if (me && !me->init(delegate, mapping, mappingLength, mappingShouldBeFreed))
      {
        me->free();

If the init method returns false, IOHIKeyboardMapper::free will be called.

    bool IOHIKeyboardMapper::init(  IOHIKeyboard *delegate,
                                  const UInt8 *map,
                                  UInt32 mappingLen,
                                  bool mappingShouldBeFreed )
    {
      if (!super::init())  return false;

      _delegate         = delegate;

      if (!parseKeyMapping(map, mappingLen, &_parsedMapping)) return false;
    ...
      _reserved = IONew(ExpansionData, 1);

If the parseKeyMapping method returns false (by supplying a malformed key 
mapping),
the init function will return early, and won't initialize the _reserved member.

The IOHIKeyboardMapper::free method will call stickyKeysfree() (both 
_parsedMapping.mapping and _parsedMapping.mappingLen
are non-zero) :

    void IOHIKeyboardMapper::free()
    {
        if (!_parsedMapping.mapping || !_parsedMapping.mappingLen)
            return;

        stickyKeysfree();

stickyKeysfree attempts to release all member objects which have been 
initialized:

    void IOHIKeyboardMapper::stickyKeysfree (void)
    {
      // release shift toggle struct
      if (_stickyKeys_ShiftToggle)
        stickyKeysFreeToggleInfo(_stickyKeys_ShiftToggle);

      // release option toggle struct
      if (_stickyKeys_OptionToggle)
        stickyKeysFreeToggleInfo(_stickyKeys_OptionToggle);

      // release on param dict
      if (_onParamDict)
        _onParamDict->release();

      // release off param dict
      if (_offParamDict)
        _offParamDict->release();

    // release off fn param dict
    if (_offFnParamDict)                 <-- (a)
    _offFnParamDict->release();          <-- (b)

However, at (a) _offFnParamDict isn't actually a member but the following macro:

    #define _offFnParamDict       _reserved->offFnParamDict

Since we returned early from IOHIKeyboardMapper::init before _reserved was 
allocated it's null.
By mapping the null page we can control the value of the offFnParamDict pointer 
and therefore
control the virtual function call at (b)

Original issue reported on code.google.com by ianb...@google.com on 30 Jun 2014 at 3:25

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by ianb...@google.com on 30 Jun 2014 at 3:32

GoogleCodeExporter commented 9 years ago

Original comment by ianb...@google.com on 22 Aug 2014 at 9:38

GoogleCodeExporter commented 9 years ago
http://support.apple.com/kb/HT6441 (i.e. also affected iOS)
No mention of CVE in OS X update (http://support.apple.com/kb/HT6443) ??

Original comment by cev...@google.com on 23 Sep 2014 at 9:39

GoogleCodeExporter commented 9 years ago

Original comment by ianb...@google.com on 24 Sep 2014 at 9:43

GoogleCodeExporter commented 9 years ago
Interesting case.
Looks like it wasn't fixed in OS X until Yosemite: 
https://support.apple.com/kb/HT6535. Therefore, it can be observed:

1) By declaring this in the earlier iOS patch, Apple dropped on bug on their 
own OS X software.

2) The original report was against OS X, not iOS, so this definitely went well 
over deadline. Marking as such.

Original comment by cev...@google.com on 17 Oct 2014 at 7:03