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檢查。