深入解析Mac OS X & iOS 操作系統(tǒng) 學(xué)習(xí)筆記(十五)

BSD 高級(jí)功能

內(nèi)存管理

虛擬內(nèi)存管理是在Mach 層進(jìn)程的,Mach 控制了分頁器,并且向用戶態(tài)導(dǎo)出了各種vm_和mach_vm_消息接口。而用戶態(tài)的開發(fā)者大部分都只知道標(biāo)準(zhǔn)的POSIX 調(diào)用,因此需要對(duì)這些Mach 調(diào)用進(jìn)行封裝。BSD也使用了屬于自己的內(nèi)存管理函數(shù)。

POSIX 內(nèi)存和頁面管理系統(tǒng)調(diào)用

POSIX 為開發(fā)人員提供了多種API,用于虛擬內(nèi)存頁面的管理和嚴(yán)格控制。函數(shù)所在的頭文件為<sys/mman.h>這些函數(shù)是對(duì)Mach VM 原語的包裝,因?yàn)镸ach VM 原語才真正負(fù)責(zé)處理Mach 虛擬內(nèi)存。這些函數(shù)執(zhí)行基本的參數(shù)肩擦,然后通過current_map( ) 獲得當(dāng)前的Mach 內(nèi)存映射,最后再調(diào)用底層的Mach 函數(shù)。

BSD 內(nèi)部的內(nèi)存函數(shù)

BSD 層要求有自己的內(nèi)存管理函數(shù),這些函數(shù)自然是架構(gòu)在Mach 之上。這些函數(shù)在XNU 的BSD 應(yīng)用廣泛,但是沒有暴露給用戶態(tài)。

  • BSD的MALLOC 和 zone :BSD 的malloc 系列函數(shù)<bsd/sys/malloc.h> 頭文件中。函數(shù)名為_MALLOC、_FREE、_REALLOC、_MALLOC_ZONE、_FREE_ZONE
  • mcache 和 slab 分配器:這是BSD 提供的基于緩存的非常高校的內(nèi)存分配方法,默認(rèn)是實(shí)現(xiàn)是使用任何后端 slab 分配器。使用mcache 機(jī)制的主要優(yōu)點(diǎn)是速度:內(nèi)存分配和維護(hù)是在每一個(gè) CPU 自有的緩存中進(jìn)行的,因此可以映射到CPU的物理緩存,從而極大地提升訪問速度
內(nèi)存壓力

Mach VM 層支持 VM 壓力(pressure)的概念,這個(gè)概念表示的意思是系統(tǒng)的可以RAM量低到危險(xiǎn)的程度了。VM壓力的處理放在BSD 層進(jìn)程,BSD層還提供了一個(gè)系統(tǒng)調(diào)用 vm_pressure_monitor( ),這個(gè)調(diào)用直接封裝了Mach對(duì)應(yīng)的調(diào)用。當(dāng)系統(tǒng)發(fā)送內(nèi)存壓力通知,iOS 中的 Objective-C 應(yīng)用就會(huì)響應(yīng)。Objective-C的垃圾回收機(jī)制使用了libauto,libauto調(diào)用libdispatch 創(chuàng)建一個(gè)VM 壓力分發(fā)源,還會(huì)調(diào)用應(yīng)用程序提供的didReceiveMemoryWarning回調(diào)函數(shù)。

Jestam/Memorystatus(iOS)

進(jìn)程并不是總能找到可以拋棄的內(nèi)存時(shí),這時(shí)需要采用Jestam機(jī)制。這是OS X 和 iOS 實(shí)現(xiàn)的一個(gè)低內(nèi)存清晰的處理機(jī)制。也稱為Memorystatus,這個(gè)機(jī)制有點(diǎn)類似于Linux的“Out-of-Memory”殺手,最初的目的就是殺掉消耗太多內(nèi)存的進(jìn)程。Memorystatus維護(hù)了兩個(gè)列表:

  • 快照列表:保存系統(tǒng)中所有進(jìn)程的狀態(tài)以及消耗的內(nèi)存頁面數(shù)
  • 優(yōu)先級(jí)列表:保存要?dú)⒌舻膫溥x進(jìn)程
進(jìn)程休眠(iOS)

在iOS 5中,Jstsam/Memorystatus 和默認(rèn)的freezer 結(jié)合在一起,實(shí)現(xiàn)了對(duì)進(jìn)程的冷凍而不是殺死。通過這種方式可以提供更好的用戶體驗(yàn),因?yàn)閿?shù)據(jù)不會(huì)丟失,而且當(dāng)內(nèi)存情況好轉(zhuǎn)時(shí)進(jìn)程可以安全恢復(fù)。進(jìn)程休眠操作是有jstsam_hibernate_top_proc 完成的,這個(gè)函數(shù)冷凍底層的任務(wù)(通過task_freeze)。冷凍操作需要遍歷任務(wù)的vm_map,然后將vm_map 傳遞給默認(rèn)的 freezer。用戶態(tài)也可以通過pid_suspend( ) 和 pid_resume( )控制進(jìn)程的休眠。iOS 還定義了 pid_hibernate,這個(gè)函數(shù)目前會(huì)忽略傳入的參數(shù),僅僅喚醒kernel_hibernation_thread(即通過kern_hibnernation_wakeup發(fā)送信號(hào))。

內(nèi)核地址空間布局隨機(jī)化(ASLR)

這項(xiàng)技術(shù)是在 Mountain Lion 引入的。現(xiàn)在已經(jīng)成為操作系統(tǒng)想要阻止黑客和惡意軟件視圖注入代碼攻擊的必備技術(shù)。防御代碼注入的主要方法是數(shù)據(jù)執(zhí)行阻止(Data Execution Prevention,DEP,在Intel 中也稱為W^X或XD,在ARM中也稱為XN),DEP能使得黑客注入代碼的企圖更加困難。

工作隊(duì)列

工作隊(duì)列(work queue)是OS X 中開發(fā)的一項(xiàng)機(jī)制,作用是為用戶通訊提供多線程并且支持?jǐn)U展到多處理器支持。工作隊(duì)列也是蘋果Grand Central Dispatch(GCD)的基礎(chǔ)機(jī)制。工作隊(duì)列是通過兩個(gè)系統(tǒng)調(diào)用提供的:

  • workq_open( ):創(chuàng)建一個(gè)工作隊(duì)列,LibC 中的 pthread_workqueue_create_np 函數(shù)封裝了這個(gè)系統(tǒng)調(diào)用,而這個(gè)庫函數(shù)進(jìn)一步被GCD 和 libdispatch 中的 dispatch_get_global_queue 函數(shù)封裝了
  • workq_kernturn( ):負(fù)責(zé)創(chuàng)建工作隊(duì)列以外的其他所有的事情,通過以下3個(gè)定義選項(xiàng)對(duì)工作隊(duì)列進(jìn)行控制:
  • WQOPS_QUEUE_ADD:對(duì)應(yīng)的是要執(zhí)行(用GCD 的話說就是分發(fā)(dispatch))的代碼塊(block)或函數(shù)。libdiapatch 實(shí)際上對(duì)每一個(gè)隊(duì)列都創(chuàng)建了兩份副本,額外的那一份副本用于overcommit(過量使用),不過這些額外的副本沒有直接暴露給調(diào)用者。通過這種方式,應(yīng)用程序的主隊(duì)列實(shí)際上只不過是默認(rèn)隊(duì)列的引用,并且設(shè)置了overcommit。overcommit位表示這個(gè)隊(duì)列可以創(chuàng)建新的線程,通常情況下不建議使用這個(gè)策略,因?yàn)榫€程多于CPU數(shù)會(huì)降低程序的運(yùn)行速度,GCD將通過dispatch_get_global_queue 調(diào)用可以接受的一個(gè)標(biāo)志(DISPATCH_QUEUE_OVERCOMMIT)來支持overcommit,但是蘋果的文檔掩蓋了這個(gè)事實(shí),宣傳這個(gè)標(biāo)志必須為0
  • WQOPS_THREAD_SETCONC:控制工作隊(duì)列的并發(fā)性,pthread_workqueue_requestconcurrencu_np( ) 調(diào)用封裝了這個(gè)選項(xiàng)
  • WQOPS_THREAD_RETURN:將線程從工作隊(duì)列分開并終止線程。pthread 的 workqueue_exit( ) 調(diào)用通過一個(gè)內(nèi)部調(diào)用_thread_workq_return 封裝了這個(gè)選項(xiàng)
    工作隊(duì)列設(shè)置(由項(xiàng)的添加而出發(fā))的邏輯在XNU 中非常獨(dú)特。主要工作由 wq_runitem 完成的,wq_rnitem 調(diào)用 setup_wqthread 手工創(chuàng)建了工作隊(duì)列線程的狀態(tài),設(shè)置了每一個(gè)寄存器的值。然后喚醒線程,線程以新的身份運(yùn)行

換個(gè)角度看BSD層

sysctl

BSD 和很多其他UNIX 系統(tǒng)一樣,也提供了一個(gè)統(tǒng)一的接口用于獲取和設(shè)置內(nèi)核變量,這個(gè)接口稱為sysctl(8)。而和Linux 這樣的系統(tǒng)不同之處在于,sysctl 是訪問這些變量的唯一方法,因?yàn)槿鄙?proc這樣用戶可以見的文件系統(tǒng)。

kqueue

BSD 中引入 kqueue 的目的是為了替代伸縮性不好的poll(2)/select(2)模型。這個(gè)接口著重強(qiáng)調(diào)的方面是擴(kuò)展性,允許未來添加任意數(shù)目的事件源,而不需要對(duì)編程接口進(jìn)行修改。XNU 導(dǎo)出了兩個(gè)和kqueue相關(guān)的系統(tǒng)調(diào)用:

  • kqueue(#362):負(fù)責(zé)創(chuàng)建kqueue,創(chuàng)建的keque實(shí)際上是一個(gè)文件描述符
  • kevent/kevent64(#363和#369):用于設(shè)置事件過濾器以及從kqueue 中讀取事件
審計(jì)(OS X)

從內(nèi)核角度看,審計(jì)只不過是在系統(tǒng)調(diào)用的邏輯中穿插了一些宏的過程:

  • AUDIT_SYSCALLL_ENTRY:調(diào)用sysent 表中的一條UNIX 系統(tǒng)調(diào)用之前調(diào)用這個(gè)宏。這個(gè)宏接受3個(gè)參數(shù):系統(tǒng)調(diào)用代碼(編號(hào))、BSD進(jìn)程以及負(fù)責(zé)這個(gè)調(diào)用的線程對(duì)象
  • AUDIT_ARG:在系統(tǒng)調(diào)用的實(shí)現(xiàn)內(nèi)部調(diào)用。這個(gè)宏接受一個(gè)表示操作的參數(shù),以及其他可變參數(shù),其他參數(shù)具體取決于對(duì)應(yīng)的系統(tǒng)調(diào)用
  • AUDIT_SYSCALL_EXIT:在系統(tǒng)調(diào)用的實(shí)現(xiàn)之后立即被調(diào)用。參數(shù)和ENTER的參數(shù)值,還接受一個(gè)系統(tǒng)調(diào)用的返回值
強(qiáng)制訪問控制(MAC)

強(qiáng)制訪問控制(Mandatory Access Control,MAC),這是蘋果從TrustedBSD 引入的一項(xiàng)強(qiáng)大的安全特性。用戶態(tài)的視角非常有局限性,只有內(nèi)核才能可靠地實(shí)施這種安全性。

MAC策略

從用戶態(tài)看,MAC策略只不過是一個(gè)不透明的對(duì)象。然而在內(nèi)核態(tài)中,策略是一個(gè)mac_policy_conf數(shù)據(jù)結(jié)構(gòu)。策略模塊在加載時(shí)通過mac_policy_register注冊(cè)這個(gè)數(shù)據(jù)機(jī)構(gòu),在退出時(shí)應(yīng)該通過mac_policy_unregister解除注冊(cè)這個(gè)結(jié)構(gòu)。
mac_polic_conf 數(shù)據(jù)結(jié)構(gòu)中的關(guān)鍵字段是 mpc_ops,這是一個(gè)指向mac_policy_ops 數(shù)據(jù)結(jié)構(gòu)的指針。mac_policy_ops 數(shù)據(jù)結(jié)構(gòu)是一個(gè)包含了300多個(gè)函數(shù)指針的巨大結(jié)構(gòu)體,每一個(gè)策略模塊都應(yīng)該實(shí)現(xiàn)其中的函數(shù)或留空(NULL)。這些函數(shù)指針基本上覆蓋了系統(tǒng)中的每一個(gè)操作,函數(shù)名遵循mpo_object_operation_call的命名約定,其中:

  • object:表示對(duì)象類型:file(實(shí)際上是文件描述符)、port、socket、sysvsem、proc 和 vnode(文件本身)
  • operation:可以是“l(fā)abel”和“check”。“l(fā)abel”操作表示標(biāo)簽相關(guān)的操作。“check”操作表示認(rèn)證一個(gè)系統(tǒng)調(diào)用或陷阱
  • call:對(duì)于check,通常表示訪問檢查涉及的系統(tǒng)調(diào)用(或Mach陷阱)名稱;對(duì)于label,則表示標(biāo)簽聲明周期的一個(gè)階段,通常包括init、associate 和 destory,有時(shí)候還要其他特定的動(dòng)詞

當(dāng)XNU 調(diào)用MAC層驗(yàn)證一個(gè)操作時(shí),MAC層調(diào)用策略模塊,然后策略模塊負(fù)責(zé)進(jìn)行驗(yàn)證。所有的MAC檢查基本上都符合一個(gè)模板。例如,考慮一個(gè)非常有用的mac_vnode_check_signature操作,這個(gè)操作負(fù)責(zé)實(shí)施代碼簽名。

蘋果的策略模塊

OS X 中 MAC 的主要作用是沙盒機(jī)制,在iOS中通過MAC實(shí)現(xiàn)嚴(yán)格的代碼簽名和entitlement機(jī)制,使得蘋果可以保護(hù)自己珍貴的硬件不被可怕的第三方代碼破壞。

sandbox.kext

sandbox 內(nèi)核擴(kuò)展有時(shí)候會(huì)請(qǐng)求/usr/libexec/sandboxd的服務(wù)。這個(gè)守護(hù)程序是有l(wèi)aunchd(1)啟動(dòng)的,使用的主機(jī)特殊端口#14(通過HOST_SEATABELT_PORT定義)。sandbox.kext 實(shí)現(xiàn)了一個(gè)小型的類SCHEME方言,用于定義認(rèn)證和操作許可。這個(gè)文本格式在用戶態(tài)動(dòng)態(tài)編譯,然后提交給內(nèi)核用作之后的驗(yàn)證。驗(yàn)證則是另一個(gè)內(nèi)核擴(kuò)展AppleMatch.text的職責(zé),AppleMatch.kext 負(fù)責(zé)規(guī)則和正則表達(dá)式匹配

AppleMobileFileIntegrity.text

iOS 的安全機(jī)制比 OS X 的安全機(jī)制要嚴(yán)格得多。 OS X 中的代碼簽名是可選的,而iOS 會(huì)通過 kill -9 殺掉任何代碼簽名不正確的進(jìn)行。iOS 中的“壞警察”的職責(zé)是由AppleMobileFileIntegrity.kext(AMFI)扮演的。AMFI在用戶態(tài)有一個(gè)守護(hù)程序:/usr/libexec/amfid。這個(gè)守護(hù)程序是有l(wèi)aunchd 啟動(dòng)的,也注冊(cè)了一個(gè)主機(jī)特殊端口#18(HOSR_AMFID_PORT)。這個(gè)守護(hù)程序接收來自AMFI的消息,并且負(fù)責(zé)AMFI完成一些最好在用戶態(tài)完成的任務(wù)。
對(duì)initializeAppleMobileFileIntegrity函數(shù)調(diào)用了mac_policy_register,就像所有的策略模塊一樣。這個(gè)模塊大部分回調(diào)函數(shù)都是NULL,有用的函數(shù)包括:

  • mpo_vnode_chek_exec:這個(gè)AMFI的回調(diào)函數(shù)返回1(表示允許vnode執(zhí)行),但是不會(huì)在設(shè)置代碼簽名的標(biāo)志位(CS_HARD和CS_KILL)之前返回1。這可以確保所有的進(jìn)程都必須進(jìn)行代碼簽名的檢查,而且之后如果需要代碼檢查的話也能殺掉進(jìn)程
  • mpo_vnode_check_signature:這是AMFI的主邏輯,這個(gè)函數(shù)使用了amfid以其內(nèi)核內(nèi)的簽名緩存來驗(yàn)證文件的代碼簽名
  • mpo_proc_check_get_task:這個(gè)函數(shù)保護(hù)task_for_pid 調(diào)用,作用是獲得任務(wù)的端口(從而能完全控制任務(wù))。這個(gè)函數(shù)檢查兩個(gè)entitlement(get-taks-allow 和task-for-pid-allow),還有一個(gè)調(diào)用用于檢查是否啟用了不受限制的調(diào)試(通過amfid),如果上訴任何返回真,那么這個(gè)函數(shù)也返回真
  • mpo_proc_check_run_cs_invalid:檢查是否設(shè)置了entitlement:get-task-allow、run-invalid-allow以及run-unsigned-code,或者是否啟用了不受限制的調(diào)試。如果檢查返回真,那么cs_allow-invalid清除CS_KILL、CS_HARD和CS_VALID位,并且返回真,允許執(zhí)行未簽名的代碼

AMFI能(通過PE_parse_boot_argn)識(shí)別一些引導(dǎo)參數(shù),并且根據(jù)參數(shù)禁用一些檢查。如下表:

AMFI引導(dǎo)參數(shù) 用途
PE_i_can_has_debugger 這個(gè)XNU中使用的全局引導(dǎo)參數(shù),表示允許附著調(diào)試器。禁用大多檢查
cs_debug 禁用代碼簽名
cs_enfoecement_disable 禁用代碼簽名;仍然會(huì)做檢查,但是僅此而已
amfi_allow_any_signature 允許任何代碼簽名,不僅是蘋果的簽名
amfi_unrestrict_task_for_pif 不論進(jìn)程是否有g(shù)et-task-allow和task_for_pid-allow entitlement,都允許task_for_pid
amfi_get_out_of_my_way 整個(gè)禁用AMFI。明顯是蘋果的開發(fā)者原卷了AMFI事事都要插手
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,694評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,690評(píng)論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,019評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,188評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,718評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,438評(píng)論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,667評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,845評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,384評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,635評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容