SEAndroid安全機制對Binder IPC的保護分析_第1頁
SEAndroid安全機制對Binder IPC的保護分析_第2頁
SEAndroid安全機制對Binder IPC的保護分析_第3頁
SEAndroid安全機制對Binder IPC的保護分析_第4頁
SEAndroid安全機制對Binder IPC的保護分析_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

SEAndroid安全機制對BinderIPC的保護分析在SEAndroid安全機制中,除了文件和屬性,還有BinderIPC需要保護。BinderIPC是Android系統(tǒng)的靈魂,使用得相當廣泛又頻繁。例如,應用程序都是BinderIPC請求訪問系統(tǒng)服務和資源。因此,SEAndroid安全機制必須要為BinderIPC保駕護航,阻止一個進程非法訪問其它進程的服務和資源。本文就詳細分析SEAndroid安全機制對BinderIPC提供的支持。關(guān)于BinderIPC的知識,可以參考這個系列的文章。SEAndroid安全機制對BinderIPC的保護實現(xiàn)在Binder驅(qū)動中,如圖1所示:從圖1可以看到,當ServiceManager將自己注冊為ContextManager時,Binder驅(qū)動會檢查它是否具有設(shè)置ContextManager的SEAndroid安全權(quán)限。ServiceManager將自己注冊為ContextManager的過程,可以參考前面一文。此外,當Client通過Binder驅(qū)動請求與Server發(fā)送通信時,Binder驅(qū)動會檢查Client是否具有與Server通信的SEAndroid安全權(quán)限。如果Client與Server的通信數(shù)據(jù)帶有Binder對象或者文件描述符,那么Binder驅(qū)動還會進一步檢查源進程是否具有向目標進程傳輸Binder對象或者文件描述符的SEAndroid權(quán)限。Client與Server的通信過程可以參考前面一文。以上提到的與BinderIPC相關(guān)的SEAndroid安全權(quán)限定義在內(nèi)核的SELinux模塊的數(shù)組secclass_map中,如下所示:[cpp]viewplaincopystructsecurity_class_mappingsecclass_map[]={......{"binder",{"impersonate","call","set_context_mgr","transfer",NULL}},......};這個數(shù)組定義在文件kernel/goldfish/security/selinux/include/classmap.h中。數(shù)組secclass_map列出的BinderIPC相關(guān)的SEAndroid權(quán)限有四種,分別是impersonate、call、set_context_mgr和transfer。其中,call、set_context_mgr和transfer就對應我們前面說的Client與Server通信、設(shè)置ContextManager和傳輸Binder對象權(quán)限。數(shù)組secclass_map沒有列出傳輸文件描述符的權(quán)限,是因為傳輸文件描述符權(quán)限實質(zhì)上是屬于文件讀寫相關(guān)的權(quán)限,也就是檢查目標進程是否具有訪問在通信數(shù)據(jù)附帶的文件描述符所描述的文件的權(quán)限,這屬于文件類別的SEAndroid安全權(quán)限。同時,數(shù)組secclass_map多出了一個impersonate權(quán)限。當進程1代表進程2與進程3執(zhí)行BinderIPC時,Binder驅(qū)動需要檢查進程1是否具有模擬進程2的impersonate權(quán)限。目前,不會發(fā)生一個進程代表另外一個進程與目標進程執(zhí)行BinderIPC的情況,因此,impersonate權(quán)限實際上是沒有使用到的。在SEAndroid安全策略中,定義有一個名稱為unconfineddomain的domain,它具有上述的call、set_context_mgr和transfer權(quán)限,如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片allowunconfineddomaindomain:binder{calltransferset_context_mgr};上述安全策略定義在文件external/sepolicy/unconfined.te中。在Android系統(tǒng)中,所有類型的應用程序進程的domain都具有unconfineddomain屬性,如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片##Appssignedwiththeplatformkey.#typeplatform_app,domain;......unconfined_domain(platform_app)#Appssignedwiththemediakey.typemedia_app,domain;......unconfined_domain(media_app)#Appssignedwiththesharedkey.typeshared_app,domain;......unconfined_domain(shared_app)#Appssignedwiththereleasekey(testkeyinAOSP).typerelease_app,domain;......unconfined_domain(release_app)#ServiceswithisolatedProcess=trueintheirmanifest.#Inorderforisolated_appstointeractwithappsthathavelevelFromUid=true#setitmustbeanmlstrustedsubject.typeisolated_app,domain,mlstrustedsubject;......unconfined_domain(isolated_app)##Untrustedapps.#typeuntrusted_app,domain;......unconfined_domain(untrusted_app)上述安全策略定義在文件external/sepolicy/app.te中。例如,用戶安裝的第三方應用程序運行在的進程的domain為untrusted_app,它通過宏unconfined_domain將unconfineddomain設(shè)置為自己的屬性。宏unconfined_domain的定義如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片######################################unconfined_domain(domain)#Allowthespecifieddomaintodoanything.#define(`unconfined_domain',`typeattribute$1mlstrustedsubject;typeattribute$1unconfineddomain;')這個宏定義在文件external/sepolicy/te_macros中。這意味著所有應用程序進程都可以與其它進程進行BinderIPC,并且傳遞Binder對象。關(guān)于Android應用程序進程的domain設(shè)置過程,可以參考前面一文。此外,Android系統(tǒng)的ServiceManager進程的domain也具有unconfined_domain屬性,如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片#servicemanager-theBindercontextmanagertypeservicemanager,domain;......unconfined_domain(servicemanager)上述安全策略定義在文件external/sepolicy/servicemanager.te中。這說明ServiceManager進程具有向Binder驅(qū)動設(shè)置ContextManager的權(quán)限。了解了BinderIPC相關(guān)的SEAndroid安全權(quán)限以及安全策略之后,接下來我們就分別分析Binder驅(qū)動應用它們的過程。1.設(shè)置ContextManager過程中的SEAndroid安全檢查從前面一文可以知道,當ServiceManager將自己設(shè)置為Binder驅(qū)動的ContextManager的時候,Binder驅(qū)動里面的函數(shù)binder_ioctl就會被調(diào)用,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticstructbinder_node*binder_context_mgr_node;......staticlongbinder_ioctl(structfile*filp,unsignedintcmd,unsignedlongarg){intret;structbinder_proc*proc=filp->private_data;......switch(cmd){......caseBINDER_SET_CONTEXT_MGR:if(binder_context_mgr_node!=NULL){......ret=-EBUSY;gotoerr;}ret=security_binder_set_context_mgr(proc->tsk);if(ret<0)gotoerr;......binder_context_mgr_node=binder_new_node(proc,NULL,NULL);......break;......default:ret=-EINVAL;gotoerr;}ret=0;err:......returnret;}這個函數(shù)定義在文件kernel/goldfish/drivers/staging/android/binder.c中。binder_context_mgr_node是一個類型為binder_node的全局變量,用來描述注冊在Binder驅(qū)動里面的ContextManager。當binder_context_mgr_node的值不等于NULL的時候,就表示已經(jīng)有進程注冊過ContextManager了,因此,就不再允許重復注冊。否則的話,就會調(diào)用函數(shù)binder_new_node創(chuàng)建一個binder_node對象,并且保存在全局變量binder_context_mgr_node中。不過,在調(diào)用函數(shù)binder_new_node為當前進程創(chuàng)建一個binder_node對象之前,需要調(diào)用函數(shù)security_binder_set_context_mgr檢查當前進程是否具有注冊ContextManager的SEAndroid安全權(quán)限。當前進程是通過本地變量proc來描述的,它指向的是一個類型為binder_proc的對象。在結(jié)構(gòu)體binder_proc中,有一個類型為task_struct的成員變量task,它指向的就是內(nèi)核中用來描述進程的一個控制塊。在前面一文中提到,進程的安全上下文是保存在內(nèi)核中用來描述該進程的一個task_struct結(jié)構(gòu)體中的,因此,當知道一個進程的task_struct結(jié)構(gòu)體之后,我們就可以獲得它的安全上下文。接下來,我們就繼續(xù)分析函數(shù)security_binder_set_context_mgr的實現(xiàn),如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticstructsecurity_operations*security_ops;......intsecurity_binder_set_context_mgr(structtask_struct*mgr){returnsecurity_ops->binder_set_context_mgr(mgr);}這個函數(shù)定義在文件kernel/goldfish/security/security.c中。security_ops是一個類型為security_operations的全局變量,它的成員變量binder_set_context_mgr是一個函數(shù)指針,指向的函數(shù)為selinux_binder_set_context_mgr,它的定義如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticintselinux_binder_set_context_mgr(structtask_struct*mgr){u32mysid=current_sid();u32mgrsid=task_sid(mgr);returnavc_has_perm(mysid,mgrsid,SECCLASS_BINDER,BINDER__SET_CONTEXT_MGR,NULL);}這個函數(shù)定義在文件kernel/goldfish/security/selinux/hooks.c中。函數(shù)selinux_binder_set_context_mgr首先獲得用來描述當前進程的安全上下文的sid,即mysid,接著再獲得用來描述要注冊ContextManager的進程mgr的安全上下文的sid,即mgrsid,最后都調(diào)用由SELinux模塊提供的函數(shù)avc_has_perm來檢查進程mgr是否具有類型為SECCLASS_BINDER的安全權(quán)限BINDER__SET_CONTEXT_MGR。當前進程即為注冊ContextManager的進程,也就是說前面獲得的mysid和mgrsid是一樣的。進程的安全上下文本來是用字符串來描述的,但是在內(nèi)核中,不會直接使用這些字符串形式的安全上下文。我們知道,SELinux是在內(nèi)核的安全模塊LSM的基礎(chǔ)上實現(xiàn)的,但是LSM不只是為SELinux服務的。也就是說,我們也可以在內(nèi)核中創(chuàng)建一個類似SELinux的模塊,來實現(xiàn)另外一個安全機制。在這個另外實現(xiàn)的安全機制里面,或許不再使用字符串來描述進程的安全上下文。為了能夠提供一種統(tǒng)一方式來計算、應用這些安全策略,LSM模塊要求在它的基礎(chǔ)上實現(xiàn)的安全機制在內(nèi)部使用一個不透明的32位無符號數(shù)來代表一個安全上下文。這樣,LSM模塊就可以提供一個統(tǒng)一的avc_has_perm函數(shù)計算一個主體是否相應的權(quán)限來訪問一個客體。簡單來說,一個SID代表的就是一個安全上下文,不同的SID代表的是不同的安全上下文,根據(jù)安全上下文計算出其對應的SID是由SELinux實現(xiàn)的,但是對于LSM來說是不透明的。LSM提供的函數(shù)avc_has_perm首先是在內(nèi)部維護的一個AccessVectorCache中檢查指定的主體mysid是否具有對客體mgrsid類型為SECCLASS_BINDER的安全權(quán)限BINDER__SET_CONTEXT_MGR。如果LSM之前處理過相同參數(shù)的權(quán)限檢查,那么就能從AccessVectorCache直接得到結(jié)果。否則的話,就需要到從用戶空間加載進來的安全策略中去計算結(jié)果。計算得到的結(jié)果除了返回給調(diào)用者之外,還會緩存在AccessVectorCache中,這樣就可以提高下一次同一樣的安全檢查的效率。函數(shù)avc_has_perm的實現(xiàn)原理就如上所述,它的詳細實現(xiàn)我們就不進一步分析了,有興趣的讀者可以自行分析。不過從函數(shù)binder_ioctl到函數(shù)selinux_binder_set_context_mgr的調(diào)用過程,我們就可以知道,函數(shù)selinux_binder_set_context_mgr實際上就是由SELinux模塊通過LSM模塊安插在Binder驅(qū)動中的一個Hook,而通過這個Hook就可以驗證對應的進程是否具有設(shè)置ContextManager的SEAndroid安全權(quán)限。從前面的分析可以知道,ServiceManager進程的domain具有unconfined_domain屬性,而所有具有unconfined_domain屬性的domain都具有設(shè)置ContextManager的SEAndroid安全權(quán)限,因此,當ServiceManager進程將自己注冊為ContextManager的時候,是能成功注冊的。2.Client調(diào)用Server的SEAndroid安全權(quán)限檢查從前面一文可以知道,Client發(fā)送給Server的請求需要經(jīng)過Binder驅(qū)動的函數(shù)binder_transaction處理,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticvoidbinder_transaction(structbinder_proc*proc,structbinder_thread*thread,structbinder_transaction_data*tr,intreply){......if(reply){......}else{if(tr->target.handle){structbinder_ref*ref;ref=binder_get_ref(proc,tr->target.handle);......target_node=ref->node;}else{target_node=binder_context_mgr_node;......}.......target_proc=target_node->proc;......if(security_binder_transaction(proc->tsk,target_proc->tsk)<0){......gotoerr_invalid_target_handle;}......}....../*ContinuetoProcessBinderTransaction*/......err_invalid_target_handle:......./*ErrorReturn*/.......}這個函數(shù)定義在文件kernel/goldfish/drivers/staging/android/binder.c中。參數(shù)reply用來區(qū)別函數(shù)binder_transaction是用來處理Client發(fā)送給Server的請求還是Server對Client發(fā)送的請求的回應。如果參數(shù)reply的值等于false,那么就表示函數(shù)binder_transaction是用來處理Client發(fā)送給Server的請求。在這種情況下,函數(shù)binder_transaction就需要檢查Client是否有權(quán)限給Server發(fā)送請求。另一方面,如果參數(shù)reply的值等于true,那么就表示函數(shù)binder_transaction是用來處理Server對Client發(fā)送的請求的回應。在這種情況下,很明顯就不需要進行權(quán)限檢查。接下來我們就主要分析Client發(fā)送給Server的請求的情況。參數(shù)proc描述的是Client進程,而Server進程由參數(shù)tr指向的一個binder_transaction_data結(jié)構(gòu)體描述。該binder_transaction_data結(jié)構(gòu)體是從Client進程的用戶空間傳遞進來的,它的成員變量target.handle是一個Binder句柄,實際上就是一個整數(shù)。如果這個Binder句柄不等于0,那么它所引用的Binder實體對象對應的就是運行在Server進程中的一個Binder服務。通過調(diào)用函數(shù)binder_get_ref可以獲得一個Binder句柄所對應的Binder引用對象,而通過一個Binder引用對象的成員變量node可以獲得它所引用的Binder實體對象。獲得了要通信的Binder實體對象之后,通過它的成員變量proc就可以獲得該Binder實體對象對應的Binder服務所運行在的Server進程。另一方面,如果上述Binder句柄的值等于0,那么就說明Client進程要發(fā)送請求給ServiceManager。ServiceManager是一個特殊的Binder服務,它會將自己注冊為BinderIPC的ContextManager,并且在Binder驅(qū)動中使用一個專門的全局變量binder_context_mgr_node來描述它所對應的Binder實體對象。因此,在這種情況下,很容易就可以通過全局變量binder_context_mgr_node的成員變量proc找到要通信的Server進程。這樣,我們就知道了Client進程和Server進程分別由參數(shù)proc描述和本地變量arget_proc指向的binder_proc結(jié)構(gòu)體描述。結(jié)構(gòu)體binder_proc的成員變量tsk指向的是內(nèi)核中用來描述進程的結(jié)構(gòu)體task_struct。根據(jù)我們在前面一小節(jié)的分析,結(jié)構(gòu)體task_struct包含了進程的安全上下文信息,因此,這時候就可以調(diào)用函數(shù)security_binder_transaction檢查Client進程是否有權(quán)限向Server進程發(fā)送請求了,也就是Client是否有權(quán)限調(diào)用Server的功能。如果有權(quán)限的話,接下來就會將Client傳遞進來的參數(shù)發(fā)送給Server,否則的話,就直接出錯返回。函數(shù)security_binder_transaction的實現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticstructsecurity_operations*security_ops;......intsecurity_binder_transaction(structtask_struct*from,structtask_struct*to){returnsecurity_ops->binder_transaction(from,to);}這個函數(shù)定義在文件kernel/goldfish/security/security.c中。前面提到,security_ops是一個類型為security_operations的全局變量,它的成員變量binder_transaction是一個函數(shù)指針,指向的函數(shù)為selinux_binder_transaction,它的定義如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticintselinux_binder_transaction(structtask_struct*from,structtask_struct*to){u32mysid=current_sid();u32fromsid=task_sid(from);u32tosid=task_sid(to);intrc;if(mysid!=fromsid){rc=avc_has_perm(mysid,fromsid,SECCLASS_BINDER,BINDER__IMPERSONATE,NULL);if(rc)returnrc;}returnavc_has_perm(fromsid,tosid,SECCLASS_BINDER,BINDER__CALL,NULL);}這個函數(shù)定義在文件kernel/goldfish/security/selinux/hooks.c中。這里有3個sid,分別是mysid、fromsid和tosid。其中,mysid描述的是當前進程的安全上下文,fromsid描述的是Client進程的安全上下文,tosid描述的是Server進程的安全上下文。在目前的Binder驅(qū)動的實現(xiàn)中,當前正在調(diào)用函數(shù)selinux_binder_transaction進程即為Client進程。因此,mysid和fromsid的值總是相等的。但是,selinux模塊在設(shè)計函數(shù)selinux_binder_transaction的時候,也考慮到了一個可能出現(xiàn)的特殊情景,那就是當前進程即不是真正的進程,而是代表參數(shù)from描述的Client進程向參數(shù)to描述的Server進程發(fā)送Binder通信請求。在這種情況下,如果當前進程和Client進程具有不同的安全上下文,即mysid和fromsid的值不相等,那么就要求當前進程具有模擬Client進程的權(quán)限,也就是具有類別為SECCLASS_BINDER的BINDER__IMPERSONATE權(quán)限。由于在目前的Binder驅(qū)動的實現(xiàn)中,不會出現(xiàn)一個進程代表另外一個進程向第三個進程發(fā)起B(yǎng)inderIPC請求的情況,因此,我們在用戶空間的SEAndroid安全策略中,是看不到有關(guān)BINDER__IMPERSONATE的規(guī)則的。最后,函數(shù)selinux_binder_transaction調(diào)用LSM模塊提供的通用函數(shù)avc_has_perm檢查Client進程對Server進程是否具有類別為SECCLASS_BINDER的BINDER__CALL的權(quán)限,也就是檢查Client進程是否有權(quán)限向Server進程發(fā)送BinderIPC請求,并且將結(jié)果返回給調(diào)用者。從前面的分析可以知道,在Android系統(tǒng)中,所有類型的應用程序進程的domain都具有unconfined_domain屬性,也就是說它們之間是可以互相進行BinderIPC的。而且,Android系統(tǒng)的服務進程,例如ServiceManager進程、Zygote進程和SystemServer進程等,它們的domain也是具有unconfined_domain屬性的,因此,應用程序進程和它們也能夠互相進行BinderIPC的。當然,這只是默認的情況,如果有需要,我們是可以在SEAndroid安全策略中定義一個規(guī)則,禁止某一個應用程序進程向某一個服務進程發(fā)送BinderIPC請求的,這樣就可以起到保護系統(tǒng)服務或者資源的目的。3.傳遞Binder對象的SEAndroid安全權(quán)限檢查Client與Server在執(zhí)行BinderIPC的過程中,可能會將Binder對象傳遞給對方,使得對方可以獲得這些Binder對象的代理接口,進而使用這些Binder對象提供的服務。想象這樣的一個情景。一個進程從另一個進程獲得了一個有權(quán)限使用的Binder對象,接著將這個Binder對象通過BinderIPC傳遞給第三個進程,但是第三個進程沒有使權(quán)限使用這個Binder對象。這時候就需要從源頭上杜絕第三個進程獲得它沒有權(quán)限使用的Binder對象。確保一個進程不會通過BinderIPC獲得它沒有權(quán)限使用的Binder對象也是由Binder驅(qū)動在函數(shù)binder_transaction中進行的,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticvoidbinder_transaction(structbinder_proc*proc,structbinder_thread*thread,structbinder_transaction_data*tr,intreply){structbinder_transaction*t;......structbinder_proc*target_proc;......t=kzalloc(sizeof(*t),GFP_KERNEL);......t->buffer=binder_alloc_buf(target_proc,tr->data_size,tr->offsets_size,!reply&&(t->flags&TF_ONE_WAY));......if(copy_from_user(t->buffer->data,tr->data.ptr.buffer,tr->data_size)){......gotoerr_copy_data_failed;}if(copy_from_user(offp,tr->data.ptr.offsets,tr->offsets_size)){......gotoerr_copy_data_failed;}......off_end=(void*)offp+tr->offsets_size;for(;offp<off_end;offp++){structflat_binder_object*fp;......fp=(structflat_binder_object*)(t->buffer->data+*offp);switch(fp->pe){caseBINDER_TYPE_BINDER:caseBINDER_TYPE_WEAK_BINDER:{......structbinder_node*node=binder_get_node(proc,fp->binder);......if(security_binder_transfer_binder(proc->tsk,target_proc->tsk)){......gotoerr_binder_get_ref_for_node_failed;}......}break;caseBINDER_TYPE_HANDLE:caseBINDER_TYPE_WEAK_HANDLE:{structbinder_ref*ref=binder_get_ref(proc,fp->handle);......if(security_binder_transfer_binder(proc->tsk,target_proc->tsk)){......gotoerr_binder_get_ref_failed;}......}break;......}......}......err_binder_get_ref_for_node_failed:err_binder_get_ref_failed:......}這個函數(shù)定義在文件kernel/goldfish/drivers/staging/android/binder.c中。參數(shù)tr指向的是一個從用戶空間傳遞進來的binder_transaction_data結(jié)構(gòu)體,里面包含了源進程proc發(fā)送給目標進程target_proc的通信數(shù)據(jù)。在這些通信數(shù)據(jù)里面,可能包含有Binder對象。函數(shù)binder_transaction通過創(chuàng)建一個類型為binder_transaction的結(jié)構(gòu)體t來描述當前這一次的Binder通信,并且通過函數(shù)binder_alloc_buf給這個結(jié)構(gòu)體在內(nèi)核空間分配了一塊緩沖區(qū),用來保存從用戶空間傳遞進來的通信數(shù)據(jù)。用戶空間傳統(tǒng)進來的數(shù)據(jù)包含有兩部分內(nèi)容。第一部分是通信數(shù)據(jù)內(nèi)容,第二部分是一個偏移數(shù)組,用來描述第一部分哪些位置包含有Binder對象。因此,函數(shù)binder_transaction需要通過兩個copy_from_user函數(shù)調(diào)用將它們拷貝到剛才分配得到的內(nèi)核緩沖區(qū)中。將Binder通信數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間后,函數(shù)binder_transaction就通過上述的偏移數(shù)組對包含在通信數(shù)據(jù)里面的Binder對象進行處理,其中就包括SEAndroid安全檢查。首先,每一個包含在通信數(shù)據(jù)里面的Binder對象都是用一個flat_binder_object結(jié)構(gòu)體來描述。結(jié)構(gòu)體flat_binder_object有一個成員變量type,當它的值等于BINDER_TYPE_BINDER、BINDER_TYPE_WEAK_BINDER、BINDER_TYPE_HANDLE和BINDER_TYPE_WEAK_HANDLE的時候,都表示它描述的是一個Binder對象。其中,前兩者表示結(jié)構(gòu)體flat_binder_object描述的是一個Binder實體對象,而后兩者表示結(jié)構(gòu)體flat_binder_object描述的是一個Binder引用對象。在Binder驅(qū)動中,Binder實體對象使用結(jié)構(gòu)體binder_node來描述,而Binder引用對象使用結(jié)構(gòu)體binder_ref來描述。無論是哪一種情況,都需要通過調(diào)用函數(shù)security_binder_transfer_binder來檢查源進程proc是否具有向目標進程target_proc傳遞Binder對象的權(quán)限。函數(shù)security_binder_transfer_binder的實現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片intsecurity_binder_transfer_binder(structtask_struct*from,structtask_struct*to){returnsecurity_ops->binder_transfer_binder(from,to);}這個函數(shù)定義在文件kernel/goldfish/security/security.c中。前面提到,security_ops是一個類型為security_operations的全局變量,它的成員變量binder_transfer_binder是一個函數(shù)指針,指向的函數(shù)為selinux_binder_transfer_binder,它的定義如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticintselinux_binder_transfer_binder(structtask_struct*from,structtask_struct*to){u32fromsid=task_sid(from);u32tosid=task_sid(to);returnavc_has_perm(fromsid,tosid,SECCLASS_BINDER,BINDER__TRANSFER,NULL);}這個函數(shù)定義在文件kernel/goldfish/security/selinux/hooks.c中。參數(shù)from和to描述的分別是源進程和目標進程,通過函數(shù)task_sid可以獲得用來描述它們的安全上下文的sid。有了源進程和目標進程的安全上下文之后,就可以調(diào)用LSM模塊提供的函數(shù)avc_has_perm來檢查源進程是否具有向目標進程傳遞Binder對象的SEAndroid安全權(quán)限了,也就是類型為SECCLASS_BINDER的BINDER__TRANSFER權(quán)限。從前面的分析可以知道,在Android系統(tǒng)中,所有類型的應用程序進程,以及系統(tǒng)服務進程,例如ServiceManager進程、Zygote進程和SystemServer進程,它們的domain都具有unconfined_domain屬性,也就是說,在默認情況下,它們之間是可以在BinderIPC中,互相傳遞Binder對象。當然,我們也可以在SEAndroid安全策略中定義相應的規(guī)則,來阻止一個進程向另外一個進程傳遞Binder對象。4.傳遞文件描述符的SEAndroid安全權(quán)限檢查Client與Server在執(zhí)行BinderIPC的過程中,除了可以相互傳遞Binder對象之外,還可以傳遞文件描述符。也就是說,一個進程可以打開一個有權(quán)限訪問的文件,得到一個文件描述符,然后再通過BinderIPC將這個文件描述符傳遞給另外一個進程,使得另外的這個進程也可以訪問這個文件。由于文件是屬于系統(tǒng)的敏感資源,因此,我們需要禁止一個進程將一個文件描述符傳遞給一個沒有權(quán)限訪問的進程。與傳遞Binder對象的安全檢查一樣,傳遞文件描述符的安全檢查也是在Binder驅(qū)動的函數(shù)binder_transaction進行的,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片staticvoidbinder_transaction(structbinder_proc*proc,structbinder_thread*thread,structbinder_transaction_data*tr,intreply){structbinder_transaction*t;......structbinder_proc*target_proc;......t=kzalloc(sizeof(*t),GFP_KERNEL);......t->buffer=binder_alloc_buf(target_proc,tr->data_size,tr->offsets_size,!reply&&(t->flags&TF_ONE_WAY));......if(copy_from_user(t->buffer->data,tr->data.ptr.buffer,tr->data_size)){......gotoerr_copy_data_failed;}if(copy_from_user(offp,tr->data.ptr.offsets,tr->offsets_size)){......gotoerr_copy_data_failed;}......off_end=(void*)offp+tr->offsets_size;for(;offp<off_end;offp++){structflat_binder_object*fp;......fp=(structflat_binder_object*)(t->buffer->data+*offp);switch(fp->type){......caseBINDER_TYPE_FD:{......structfile*file;......file=fget(fp->handle);......if(security_binder_transfer_file(proc->tsk,target_proc->tsk,file)<0){......gotoerr_get_unused_fd_failed;}......}break;......}......}......err_get_unused_fd_failed:......}這個函數(shù)定義在文件kernel/goldfish/drivers/staging/android/binder.c中。與Binder對象一樣,包含在BinderIPC通信數(shù)據(jù)里面的文件描述符也是使用一個類型為flat_binder_object的結(jié)構(gòu)體來描述的,不過這時候flat_binder_object結(jié)構(gòu)體的成員變量type的值為BINDER_TYPE_FD。此外,這時候flat_binder_object結(jié)構(gòu)體的成員變量handle描述的就是要傳遞的文件描述符。有了這個文件描述符之后,就可以調(diào)用函數(shù)fget獲得一個file結(jié)構(gòu)體,該file結(jié)構(gòu)體就描述要傳遞的文件的所有信息,包含它的安全上下文信息。因此,接下來就可以調(diào)用函數(shù)security_binder_transfer_file來檢查源進程proc是否具有向目標進程target_proc傳遞指定的文件file了。函數(shù)security_binder_transfer_file的實現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片intsecurity_binder_transfer_file(structtask_struct*from,structtask_struct*to,structfile*file){returnsecurity_ops->binder_transfer_file(from,to,file);}這個函數(shù)定義在文件kernel/goldfish/security/security.c中。前面提到,security_ops是一個類型為security_operations的全局變量,它的成員變量binder_transfer_file是一個函數(shù)指針,指向的函數(shù)為selinux_binder_transfer_file,它的定義如下所示:[cpp]viewplaincopy在CODE上查看

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論