[置顶] Android的IPC访问控制设计与实现

3.3.1 IPC钩子函数设计与实现

IPC Binder是Android最重要的进程间通信机制,因此,必须在此实施强制访问控制。

1. 修改secuirty.h

打开终端shell,输入指令“cd /android4.0/kernel/goldfish/include/linux/vim security.h”,找到结构security_operations,加入函数指针变量,如下所示:

/*

* This is the main security structure.

*/

struct security_operations {

   charname[SECURITY_NAME_MAX + 1];

#ifdef HAVE_SMACK

   /*

    * to add a binder hook

    * */

   int(*binder_transaction) (struct task_struct *from, struct task_struct *to);

#endif

随后在security_operations定义结尾后,加入函数声明,如下:

#ifdef HAVE_SMACK

int security_binder_transaction(structtask_struct *from, struct task_struct *to);

#endif

在LSM钩子函数实现处加入security_binder_transaction的定义,如下:

#ifdef HAVE_SMACK

static inline intsecurity_binder_transaction(struct task_struct *from, struct task_struct *to) {

   return 0;

}

#endif

2. 修改security.c

打开终端shell,输入指令“cd /android4.0/kernel/goldfish/security/vim security.c”,加入函数,如下所示:

#ifdefHAVE_SMACK

intsecurity_binder_transaction(struct task_struct *from, struct task_struct *to) {

    returnsecurity_ops->binder_transaction(from, to);

}

#endif

3. 修改smack_lsm.c

打开终端shell,输入指令“cd /android4.0/kernel/goldfish/security/smack/vim smack_lsm.c”,加入函数“smack_binder_transaction”,如下所示:

#ifdefHAVE_SMACK

/*

 * smack_binder_transaction - to check bindertransaction between two tasks

 * */

static intsmack_binder_transaction(struct task_struct *from, struct task_struct *to) {

    int rc1, rc2;

    /*

     * ask the two task must have writepermission to each other

     * */

    rc1 = smk_access(task_security(from),task_security(to), MAY_WRITE);

    rc2 = smk_access(task_security(to),task_security(from), MAY_WRITE);

    return rc1 == 0 && rc2 == 0 ? 0:1;

}

#endif

此钩子函数用来判断源进程from和目标进程to之间有没有互相写权限。最后在结构体security_operations smack_ops新增成员变量如下:

structsecurity_operations smack_ops = {

   .name =                      "smack",

#ifdefHAVE_SMACK

   .binder_transaction = smack_binder_transaction,

#endif

4. 重新编译模拟器内核

编译Android内核方法已经在第二章有所阐述,这里不再叙述。

3.3.2  

每个进程分为用户空间和内核空间两部分,不同进程的用户空间是无法共享的,进程内核空间通过Android Binder来实现IPC。Binder驱动代码位于“/android4.0/kernel/goldfish/driver/staging/android/bind.c”文件中,其中binder_transaction函数使用binder_transaction_data结构体的数据来执行Binder寻址、复制Binder IPC数据、生成及检索Binder节点等操作。打开终端shell,输入指令“cd /host/android4.0/kernel/goldfish/drivers/staging/android/vim binder.c”,找到该函数的定义,如下

static voidbinder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply);

在源进程和目标进程确定后,加入代码,如下:

       if(security_binder_transaction(proc->tsk,target_proc->tsk)) {

           return_error = BR_FAILED_REPLY;

           goto err_invalid_target_handle;

       }

其中,target_proc->tsk指向目标进程的task_struct,proc->tsk指向源进程的task_struct,加入security_task_movememory用来判断当前进程对源进程有没有写权限,security_binder_transaction用来判断源进程对目标进程有没有写权限,这两个函数均为LSM钩子函数,由于内核已经装载了smack模块,因此它们是指向了smack内核的smack_task_movememory和smack_binder_transaction。加入上述代码的目的是为了防止进程不经授权滥用IPC Binder进行通信,正如下图所示:


如上图所示,服务客户端通过Binder调用Service Server的foo函数,服务客户端将Binder IPC数据通过BinderDriver传递给Service Server,Binder Driver是源进程和目标进程通信的媒介,IPC检查机制就是在Binder Driver中检查源进程和目标进程之间有没有互相“写”的权限。在进程的安全标签不是“_”的前提下,使用Smack可以实现对进程的控制。例如上层应用如果要想实现发短信的功能,与上层应用所对应的Linux进程是在BinderDriver中与radio进程进行互相通信,如果smack规则否定了上层应用对radio“写”权限,那么上层应用不能实现发短信的功能。再如,上层应用要想实现访问通讯录的目的,上层应用也是在Binder Driver中与通讯录进程进行通信,如果smack规则容许上层应用对通讯录进程有“写”的权限,那么上层应用才可以访问通讯录。恶意软件可能绕过Android框架层的权限检查机制,但它们绕不过内核的IPC检查。


原文地址:https://www.cnblogs.com/pangblog/p/3265265.html