Android ashmem hacking
/**********************************************************************
* Android ashmem hacking
* 声明:
* 最近有些东西涉及到binder,而binder又涉及到ashmem,于是先跟一下这
* 部分的内容。
*
* 2016-1-12 深圳 南山平山村 曾剑锋
*********************************************************************/ /**
* 参考文章:
* Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
* http://blog.csdn.net/luoshengyang/article/details/6664554
*/ /*
* ashmem_area - anonymous shared memory area
* Lifecycle: From our parent file's open() until its release()
* Locking: Protected by `ashmem_mutex'
* Big Note: Mappings do NOT pin this structure; it dies on close()
*/
struct ashmem_area {
char name[ASHMEM_FULL_NAME_LEN];/* optional name for /proc/pid/maps */
struct list_head unpinned_list; /* list of all ashmem areas */
struct file *file; /* the shmem-based backing file */
size_t size; /* size of the mapping, in bytes */
unsigned long prot_mask; /* allowed prot bits, as vm_flags */
}; /*
* ashmem_range - represents an interval of unpinned (evictable) pages
* Lifecycle: From unpin to pin
* Locking: Protected by `ashmem_mutex'
*/
struct ashmem_range {
struct list_head lru; /* entry in LRU list */
struct list_head unpinned; /* entry in its area's unpinned list */
struct ashmem_area *asma; /* associated area */
size_t pgstart; /* starting page, inclusive */
size_t pgend; /* ending page, inclusive */
unsigned int purged; /* ASHMEM_NOT or ASHMEM_WAS_PURGED */
}; module_init(ashmem_init); ----------+
module_exit(ashmem_exit); |
|
static int __init ashmem_init(void) <---------+
{
int ret; // static struct kmem_cache *ashmem_area_cachep __read_mostly;
ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
sizeof(struct ashmem_area),
, , NULL);
if (unlikely(!ashmem_area_cachep)) {
printk(KERN_ERR "ashmem: failed to create slab cache\n");
return -ENOMEM;
} ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
sizeof(struct ashmem_range),
, , NULL);
if (unlikely(!ashmem_range_cachep)) {
printk(KERN_ERR "ashmem: failed to create slab cache\n");
return -ENOMEM;
} ret = misc_register(&ashmem_misc); -------------------+
if (unlikely(ret)) { |
printk(KERN_ERR "ashmem: failed to register misc device!\n"); |
return ret; |
} |
|
register_shrinker(&ashmem_shrinker); |
|
printk(KERN_INFO "ashmem: initialized\n"); |
|
return ; |
} |
|
static struct file_operations ashmem_fops = { <-------+ |
.owner = THIS_MODULE, | |
.open = ashmem_open, -------*-+ |
.release = ashmem_release, | | |
.read = ashmem_read, | | |
.llseek = ashmem_llseek, | | |
.mmap = ashmem_mmap, ---------------*-*--------*---------+
.unlocked_ioctl = ashmem_ioctl, ---------------*-*--------*-------+ |
.compat_ioctl = ashmem_ioctl, | | | | |
}; | | | | |
| | | | |
static struct miscdevice ashmem_misc = { <-------*-*--------+ | |
.minor = MISC_DYNAMIC_MINOR, | | | |
.name = "ashmem", | | | |
.fops = &ashmem_fops, --------+ | | |
}; +-------------------------------------------+ | |
V | |
static int ashmem_open(struct inode *inode, struct file *file) | |
{ | |
struct ashmem_area *asma; | |
int ret; | |
| |
ret = generic_file_open(inode, file); | |
if (unlikely(ret)) | |
return ret; | |
| |
// static struct kmem_cache *ashmem_area_cachep __read_mostly; | |
// ashmem_area_cachep = kmem_cache_create("ashmem_area_cache", | |
// sizeof(struct ashmem_area), | |
// 0, 0, NULL); | |
asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL); | |
if (unlikely(!asma)) | |
return -ENOMEM; | |
| |
INIT_LIST_HEAD(&asma->unpinned_list); | |
// #define ASHMEM_NAME_PREFIX "dev/ashmem/" | |
// #define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1) | |
// #define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)| |
memcpy(asma->name, ASHMEM_NAME_PREFIX, ASHMEM_NAME_PREFIX_LEN); | |
// #define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE) | |
asma->prot_mask = PROT_MASK; | |
// can get this asma struct in other function | |
file->private_data = asma; | |
| |
return ; +-----------------------------------------------------------+ |
} | |
V |
static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)|
{ |
struct ashmem_area *asma = file->private_data; |
long ret = -ENOTTY; |
|
switch (cmd) { |
case ASHMEM_SET_NAME: |
ret = set_name(asma, (void __user *) arg); -------+ |
break; | |
case ASHMEM_GET_NAME: | |
ret = get_name(asma, (void __user *) arg); -------*-----+ |
break; | | |
case ASHMEM_SET_SIZE: | | |
ret = -EINVAL; | | |
if (!asma->file) { | | |
ret = ; | | |
asma->size = (size_t) arg; | | |
} | | |
break; | | |
case ASHMEM_GET_SIZE: | | |
ret = asma->size; | | |
break; | | |
case ASHMEM_SET_PROT_MASK: | | |
ret = set_prot_mask(asma, arg); | | |
break; | | |
case ASHMEM_GET_PROT_MASK: | | |
ret = asma->prot_mask; | | |
break; | | |
case ASHMEM_PIN: | | |
case ASHMEM_UNPIN: | | |
case ASHMEM_GET_PIN_STATUS: | | |
ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg);| | |
break; | | |
case ASHMEM_PURGE_ALL_CACHES: | | |
ret = -EPERM; | | |
if (capable(CAP_SYS_ADMIN)) { | | |
struct shrink_control sc = { | | |
.gfp_mask = GFP_KERNEL, | | |
.nr_to_scan = , | | |
}; | | |
ret = ashmem_shrink(&ashmem_shrinker, &sc); | | |
sc.nr_to_scan = ret; | | |
ashmem_shrink(&ashmem_shrinker, &sc); | | |
} | | |
break; | | |
} | | |
| | |
return ret; | | |
} +----------------------------------------------+ | |
V | |
static int set_name(struct ashmem_area *asma, void __user *name) | |
{ | |
int ret = ; | |
| |
mutex_lock(&ashmem_mutex); | |
| |
/* cannot change an existing mapping's name */ | |
if (unlikely(asma->file)) { | |
ret = -EINVAL; | |
goto out; | |
} | |
| |
if (unlikely(copy_from_user(asma->name + ASHMEM_NAME_PREFIX_LEN, | |
name, ASHMEM_NAME_LEN))) | |
ret = -EFAULT; | |
asma->name[ASHMEM_FULL_NAME_LEN-] = '\0'; | |
| |
out: | |
mutex_unlock(&ashmem_mutex); | |
| |
return ret; | |
} +------------------------------------------------------+ |
V |
static int get_name(struct ashmem_area *asma, void __user *name) |
{ |
int ret = ; |
|
mutex_lock(&ashmem_mutex); |
if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') { |
size_t len; |
|
/* |
* Copying only `len', instead of ASHMEM_NAME_LEN, bytes |
* prevents us from revealing one user's stack to another. |
*/ |
len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + ; |
if (unlikely(copy_to_user(name, |
asma->name + ASHMEM_NAME_PREFIX_LEN, len))) |
ret = -EFAULT; |
} else { |
if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF, |
sizeof(ASHMEM_NAME_DEF)))) |
ret = -EFAULT; |
} |
mutex_unlock(&ashmem_mutex); |
|
return ret; |
} |
|
static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) <--------+
{
struct ashmem_area *asma = file->private_data;
int ret = ; mutex_lock(&ashmem_mutex); /* user needs to SET_SIZE before mapping */
if (unlikely(!asma->size)) {
ret = -EINVAL;
goto out;
} /* requested protection bits must match our allowed protection mask */
if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask)) &
calc_vm_prot_bits(PROT_MASK))) {
ret = -EPERM;
goto out;
}
vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_mask); if (!asma->file) {
char *name = ASHMEM_NAME_DEF;
struct file *vmfile; if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')
name = asma->name; /* ... and allocate the backing shmem file */
vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
if (unlikely(IS_ERR(vmfile))) {
ret = PTR_ERR(vmfile);
goto out;
}
asma->file = vmfile;
}
// #define get_file(x) atomic_long_inc(&(x)->f_count)
get_file(asma->file); if (vma->vm_flags & VM_SHARED)
shmem_set_file(vma, asma->file); --------------+
else { |
if (vma->vm_file) |
fput(vma->vm_file); |
vma->vm_file = asma->file; |
} |
vma->vm_flags |= VM_CAN_NONLINEAR; |
|
out: |
mutex_unlock(&ashmem_mutex); |
return ret; |
} +------------------------------------------+
v
void shmem_set_file(struct vm_area_struct *vma, struct file *file)
{
if (vma->vm_file)
fput(vma->vm_file); -------------+
vma->vm_file = file; |
vma->vm_ops = &shmem_vm_ops; |
vma->vm_flags |= VM_CAN_NONLINEAR; |
} |
|
void fput(struct file *file) <------------+
{
if (atomic_long_dec_and_test(&file->f_count))
__fput(file);
}
Android ashmem hacking的更多相关文章
- Android - Ashmem驱动
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luosheng ...
- mokoid android open source HAL hacking in a picture
/************************************************************************** * mokoid android HAL hac ...
- Android 开发之 ---- 底层驱动开发(一) 【转】
转自:http://blog.csdn.net/jmq_0000/article/details/7372783 版权声明:本文为博主原创文章,未经博主允许不得转载. 驱动概述 说到 Android ...
- Android 开发之 ---- 底层驱动开发(一)
驱动概述 说到 android 驱动是离不开 Linux 驱动的.Android 内核采用的是 Linux2.6 内核 (最近Linux 3.3 已经包含了一些 Android 代码).但 Andro ...
- Android手机流量分析工具介绍
一.20 Best Android Hacking Apps And Tools Of 2018 首先罗列常见的Android手机hacking的工具 #1The Android Network Ha ...
- c++11 on Android
C++11 on Android The latest Andoird NDK r8e finally supports some of the most important C++11 librar ...
- Android native进程间通信实例-binder结合共享内存
在android源码的驱动目录下,一般会有共享内存的相关实现源码,目录是:kernel\drivers\staging\android\ashmem.c.但是本篇文章不是讲解android共享内存的功 ...
- GitHub awesome Resource
各种Awesome技术资源的资源聚合: https://github.com/sindresorhus/awesome Contents Platforms Programming Languages ...
- 所有语言的Awesome(2)
Curated list of awesome lists https://awesomeweekly.co https://github.com/sindresorhus/awesome ✨ Pre ...
随机推荐
- 【ACMER纷纷表示】女生应该找一个玩ACM的男生
1.强烈的事业心 将来,他也一定会有自己热爱的事业.而且,男人最性感的时刻之一,就是他专心致志做事的时候.所以,找一个机会在他全神贯注玩ACM的时候,从侧面好好观察他,你就会发现我说的话没错.2.永不 ...
- CentOS 6.4 搭建SVN服务器
SVN作为新一代代码版本管理工具,有很多优点,管理方便,逻辑明确,安全性高,代码一致性高.SVN数据存储有两种方式,BDB(事务安全表类型)和FSFS(一种不需要数据库的存储系统),为了避免在服务器连 ...
- Oracle 体系结构2 - 实例和数据库
Oracle最最基本的概念: 实例和数据库 实例就是oracle进程和一块共享内存, 数据库就是静态的文件,如datafile, log file, redo logfile, control fil ...
- 【Linux高频命令专题(6)】mkdir
简述 用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 命令格式 mkdir [选项] 目录... 命令参数 -m, --mode=模式 ...
- linux上应用程序的执行机制
linux上应用程序的执行机制 执行文件是如何在shell中被"执行"的.本文中尽可能少用一些源码,免得太过于无 聊,主要讲清这个过程,感兴趣的同学可以去查看相应的源码了解更多的信 ...
- C和指针贴图
ANSI C 算术转换 内存操作函数 打开流 关闭流 IO函数常用模式 字符输入函数 字符输出函数 撤销字符 未格式化的行IO 格式化的行IO-scanf家族 格式化IO-printf家族 print ...
- Error building Player: Win32Exception: ApplicationName=‘xxxxxxxxxxxxxxxxxx//sdk\tools\zipalign.exe' , CommandLine='4 的解决办法
更新了安卓SDK后,有时候Unity编译失失败,报错类似 Error building Player: Win32Exception: ApplicationName='D:/Program File ...
- ipconfig
当使用ipconfig时不带任何参数选项,那么它为每个已经配置了的接口显示IP地址.子网掩码和缺省网关值. 如果你安装了虚拟机和无线网卡的话,它们的相关信息也会出现在这里.
- 转:Servlet的url匹配以及url-pattern详解
Servlet是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜.估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天遇到一个问题,上网查了servlet的规范才发现,servlet中的u ...
- Spring IoC — 基于注解的配置
基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现. @Component:对类进行标注,Spring容器 ...