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 ...
随机推荐
- 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- 【树形DP/搜索】BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会
1827: [Usaco2010 Mar]gather 奶牛大集会 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 793 Solved: 354[Sub ...
- QualityCenter10+Oracle10.2.1.0.1+Win2003SP2企业版安装步骤
HpQualityCenter10+Oracle10.2.1.0.1+Win2003SP2企业版安装步骤: 1.点击setup.exe,等待,知道出现以下界面,然后按“下一步” 2.出现如下界面,接受 ...
- NGUI UIGrid 动态刷新布局 && BUG FIX
/// <summary> /// "1" => 对应的一个UISpirte,"1234" => 对应四个预设 /// </sum ...
- POJ1144 Network 无向图的割顶
现在打算重新学习图论的一些基础算法,包括像桥,割顶,双连通分量,强连通分量这些基础算法我都打算重敲一次,因为这些量都是可以用tarjan的算法求得的,这次的割顶算是对tarjan的那一类算法的理解的再 ...
- [转]剖析ASP.Net MVC Application
http://www.cnblogs.com/errorif/archive/2009/02/13/1389927.html 为了完全了解Asp.net MVC是怎样工作的,我将从零开始创建一个MVC ...
- JSP include标签和include指令
test1.jsp <% int a = 5; out.println(a); %> test2.jsp <jsp:include page="/test1.jsp&quo ...
- ubuntu 13.10 64bit装BeyondCompare
1. Beyond Compare官网下载amd-64位的,安装失败,依赖于ia32-libs,但是这个文件已经不在源里了: 2. 官网下载tar.gz源码包,解压安装失败: 3. 直接装32位的,可 ...
- 40. Combination Sum II
题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...
- Android 线程通讯类Handler
handler是线程通讯工具类.用于传递消息.它有两个队列: 1.消息队列 2.线程队列 消息队列使用sendMessage和HandleMessage的组合来发送和处理消息. 线程队列类似一段代码, ...