代碼堆棧管理的制作方法
【技術(shù)領(lǐng)域】
[0001] 本發(fā)明通常涉及計(jì)算機(jī)系統(tǒng),并且更具體地涉及執(zhí)行計(jì)算機(jī)程序期間的代碼堆棧 管理。
【背景技術(shù)】
[0002] 計(jì)算機(jī)系統(tǒng)典型地包括計(jì)算機(jī)程序和硬件(諸如半導(dǎo)體、晶體管、芯片、電路板、存 儲(chǔ)設(shè)備和處理器)的組合。存儲(chǔ)設(shè)備存儲(chǔ)數(shù)據(jù)和由處理器執(zhí)行的計(jì)算機(jī)程序。
[0003] 計(jì)算機(jī)程序通常分成彼此調(diào)用的片段。片段典型地稱為方法、函數(shù)、模塊、部分、 類、程序或者子例程。當(dāng)?shù)谝环椒?調(diào)用方)調(diào)用第二方法(被調(diào)用方)時(shí),調(diào)用方的方法停止 執(zhí)行以及被調(diào)用方的方法獲得處理器的控制并且開始執(zhí)行。當(dāng)被調(diào)用方的方法停止執(zhí)行 時(shí),它將處理器的控制返回至調(diào)用方的方法,調(diào)用方的方法在調(diào)用被調(diào)用方的方法的調(diào)用 指令之后的下一個(gè)指令處重新開始執(zhí)行。
[0004] 為了促進(jìn)該調(diào)用和返回技術(shù),計(jì)算機(jī)可以使用調(diào)用棧,也稱為運(yùn)行期棧、函數(shù)棧、 執(zhí)行棧、調(diào)用?;蛘吆?jiǎn)稱棧。調(diào)用棧包括每個(gè)主動(dòng)方法的條目(也稱為幀)。條目存儲(chǔ)關(guān)于執(zhí) 行其相應(yīng)方法的信息。信息可以包括方法的標(biāo)識(shí)符、方法的返回地址(在被調(diào)用方的方法返 回之后接著執(zhí)行的調(diào)用方的方法中的指令位置)、由方法讀取或者寫入的局部變量的值、傳 遞至方法的參數(shù)、用于算術(shù)運(yùn)算或者邏輯運(yùn)算的操作數(shù)的求值棧、指向方法當(dāng)前實(shí)例的指 針、封裝方法上下文和/或方法的特權(quán)或者授權(quán)級(jí)別中的任何一個(gè)、一些或者全部。
[0005] 調(diào)用棧使用后進(jìn)先出(LIF0)原則,意思是添加(推入)至調(diào)用棧頂部的最后(或者 最近)條目是從調(diào)用棧頂部移除(彈出)的第一(或者下一個(gè))條目。例如,響應(yīng)于第一方法調(diào) 用第二方法,新條目被創(chuàng)建以保存第一方法的上下文以及容納第二方法的局部變量并且被 推至調(diào)用棧頂部。如果第二方法調(diào)用第三方法,則保存第二方法上下文以及容納第二方法 局部變量的新條目被推至調(diào)用棧上。一旦當(dāng)前執(zhí)行的方法結(jié)束,則其調(diào)用方的方法的條目 從棧頂部彈出并且用于恢復(fù)調(diào)用方的方法的運(yùn)行環(huán)境。由于許多方法可以彼此調(diào)用并且調(diào) 用可以是嵌套或者甚至遞歸的,因此調(diào)用棧隨著程序執(zhí)行而增長和縮小。
[0006] 在計(jì)算機(jī)程序中,嵌套函數(shù)(還稱為嵌套程序或者嵌套子例程)是在詞法上封裝在 另一個(gè)函數(shù)(稱為當(dāng)前函數(shù))內(nèi)的函數(shù)。在許多方法中,嵌套函數(shù)用于結(jié)構(gòu)化編程。由于嵌 套,嵌套函數(shù)的范圍在嵌套函數(shù)的當(dāng)前函數(shù)內(nèi)。這意味著嵌套函數(shù)可以訪問當(dāng)前函數(shù)中從 當(dāng)前函數(shù)外部不可見的局部變量和其它局部函數(shù)以及局部常量和類型。盡管在實(shí)用程序中 通常僅使用少數(shù)級(jí)別,但是理論上嵌套可以到任何級(jí)別的深度。在一些環(huán)境中,嵌套函數(shù)的 代碼動(dòng)態(tài)地生成并且一直持續(xù)到從當(dāng)前函數(shù)和其子例程退出。這種動(dòng)態(tài)生成的代碼的示例 是蹦床函數(shù)和信號(hào)處理程序。操作系統(tǒng)可以將該動(dòng)態(tài)生成的代碼分配在調(diào)用棧上。
【發(fā)明內(nèi)容】
[0007] 實(shí)施例包括用于代碼棧管理的方法、系統(tǒng)和計(jì)算機(jī)程序產(chǎn)品。一個(gè)方面包括配置 為執(zhí)行軟件應(yīng)用的處理器。另一個(gè)方面包括代碼棧存儲(chǔ)器區(qū)域和數(shù)據(jù)棧存儲(chǔ)器區(qū)域,代碼 棧存儲(chǔ)器區(qū)域與數(shù)據(jù)棧存儲(chǔ)器區(qū)域分離。另一個(gè)方面包括將數(shù)據(jù)棧保持在數(shù)據(jù)棧存儲(chǔ)器區(qū) 域中,數(shù)據(jù)棧包括多個(gè)棧幀,該多個(gè)棧幀包括與軟件應(yīng)用的執(zhí)行相對(duì)應(yīng)的一個(gè)或者多個(gè)數(shù) 據(jù)變量。另一個(gè)方面包括將代碼棧保持在代碼棧存儲(chǔ)器區(qū)域中,代碼棧包括多個(gè)代碼棧條 目,該多個(gè)代碼棧條目包括與軟件應(yīng)用的執(zhí)行相對(duì)應(yīng)的可執(zhí)行計(jì)算機(jī)代碼。
【附圖說明】
[0008]在說明書結(jié)論處的權(quán)利要求中特別指出了被看作實(shí)施例的主題并且對(duì)其明確地 要求保護(hù)。通過與附圖結(jié)合理解的下列詳細(xì)說明,實(shí)施例的前述特性和其它特性以及優(yōu)點(diǎn) 是顯而易見的。
[0009]圖1描繪了根據(jù)實(shí)施例的用于代碼棧管理的計(jì)算機(jī)系統(tǒng);
[0010]圖2A-2C描繪了數(shù)據(jù)棧和代碼棧的實(shí)施例;
[0011] 圖3描繪了根據(jù)實(shí)施例包括使代碼棧與數(shù)據(jù)棧同步的代碼棧管理的過程流程;
[0012] 圖4-5描繪了根據(jù)各種實(shí)施例的代碼棧管理的過程流程;
[0013]圖6描繪了數(shù)據(jù)區(qū)域和代碼棧的實(shí)施例;以及
[0014] 圖7圖示了根據(jù)實(shí)施例的計(jì)算機(jī)程序產(chǎn)品。
【具體實(shí)施方式】
[0015] 提供了代碼棧管理的實(shí)施例,在下面對(duì)示例性實(shí)施例詳細(xì)地進(jìn)行討論。將動(dòng)態(tài)生 成的代碼分配到調(diào)用棧上可以使計(jì)算機(jī)系統(tǒng)容易受到安全性攻擊(諸如棧溢出情況)。為了 提高安全性,在計(jì)算機(jī)存儲(chǔ)器中保持包括數(shù)據(jù)棧和代碼棧的兩個(gè)單獨(dú)的并且不同的棧。數(shù) 據(jù)??梢晕挥诳蓪懭氲牟豢蓤?zhí)行存儲(chǔ)器區(qū)域中,而代碼??梢晕挥诳蓤?zhí)行存儲(chǔ)器區(qū)域中。 在一些實(shí)施例中,除了將新條目分配到代碼棧上期間以外,可以使代碼棧不可寫入,并且還 可以在將新條目分配到代碼棧上期間使代碼棧不可執(zhí)行。因此,通過不可執(zhí)行數(shù)據(jù)棧和單 獨(dú)代碼棧防止對(duì)應(yīng)用的安全性攻擊。分離的代碼棧和數(shù)據(jù)棧允許動(dòng)態(tài)生成的代碼在增強(qiáng)安 全性的同時(shí)為例如事件處理程序和詞法嵌套提供蹦床函數(shù)。
[0016] 可以將蹦床函數(shù)分配在代碼棧上。蹦床函數(shù)是在獲得嵌套函數(shù)地址的運(yùn)行時(shí)間創(chuàng) 建的一小段代碼。蹦床函數(shù)中的指令必須做兩件事情:將常數(shù)地址加載到靜態(tài)鏈寄存器中, 并且跳轉(zhuǎn)至嵌套函數(shù)的實(shí)地址。這可能需要兩個(gè)指令:立即移動(dòng)和跳轉(zhuǎn)。兩個(gè)地址可以存在 于蹦床函數(shù)中作為字長立即操作數(shù)??赡苄枰獙⒚總€(gè)地址以兩個(gè)部分加載到寄存器中;每 個(gè)地址段形成單獨(dú)的立即操作數(shù)。
[0017] 生成以初始化蹦床函數(shù)的代碼必須將靜態(tài)鏈值和函數(shù)地址存儲(chǔ)到指令的立即操 作數(shù)中。靜態(tài)鏈和函數(shù)入口地址可以存儲(chǔ)在位于代碼棧外部的單獨(dú)數(shù)據(jù)區(qū)域中。數(shù)據(jù)區(qū)域 還可以可選地容納代碼棧管理信息,諸如用于對(duì)代碼棧條目(諸如代碼棧幀分配大小和關(guān) 聯(lián)數(shù)據(jù)棧幀)進(jìn)行分配和解除分配。在一些實(shí)施例中,蹦床函數(shù)在分配之后是不可變的,并 且配置為與指向通過寫入單獨(dú)數(shù)據(jù)區(qū)域存在的嵌套函數(shù)的指針結(jié)合使用。數(shù)據(jù)區(qū)域不容納 可寫代碼,從而避免代碼注入到可寫的可執(zhí)行蹦床函數(shù)中的風(fēng)險(xiǎn)。
[0018] 圖1圖示了用于代碼棧管理的計(jì)算機(jī)系統(tǒng)100的實(shí)施例。計(jì)算機(jī)系統(tǒng)100包括執(zhí)行 軟件應(yīng)用104的處理器101,軟件應(yīng)用104包括存儲(chǔ)在計(jì)算機(jī)系統(tǒng)100的存儲(chǔ)器105中的可執(zhí) 行計(jì)算機(jī)代碼。在執(zhí)行應(yīng)用104期間,處理器101管理數(shù)據(jù)棧102和代碼棧103。數(shù)據(jù)棧102位 于存儲(chǔ)器105中的數(shù)據(jù)棧存儲(chǔ)器區(qū)域106內(nèi),該數(shù)據(jù)棧存儲(chǔ)器區(qū)域106包括可寫的不可執(zhí)行 存儲(chǔ)器區(qū)域。代碼棧103位于存儲(chǔ)器105中的代碼棧存儲(chǔ)器區(qū)域107內(nèi)。代碼棧存儲(chǔ)器區(qū)域 107包括可執(zhí)行存儲(chǔ)器區(qū)域。數(shù)據(jù)棧存儲(chǔ)器區(qū)域106與代碼棧存儲(chǔ)器區(qū)域107分離并且不同, 并且不與代碼棧存儲(chǔ)器區(qū)域107重疊。在一些實(shí)施例中,除了將條目分配到代碼棧103上期 間以外,代碼棧存儲(chǔ)器區(qū)域107可以是不可寫的。在另外的實(shí)施例中,在將條目分配到代碼 棧103上期間,可以在將條目分配到代碼棧103上期間使代碼棧存儲(chǔ)器區(qū)域107暫時(shí)不可執(zhí) 行。在一些實(shí)施例中,代碼棧存儲(chǔ)器區(qū)域107可以是可由計(jì)算機(jī)系統(tǒng)100的可信組件(諸如內(nèi) 核或者另一個(gè)系統(tǒng)組件,其可以包括,但不限于可信程序庫、受管理的運(yùn)行期環(huán)境或者管理 程序系統(tǒng))專門寫入的。
[0019] 在一些實(shí)施例中,可以通過用動(dòng)態(tài)生成的蹦床函數(shù)預(yù)填充存儲(chǔ)器頁面以進(jìn)行嵌套 函數(shù)的條目在代碼棧103上的分配。在另一個(gè)實(shí)施例中,可以通過使代碼棧存儲(chǔ)器區(qū)域107 暫時(shí)可寫將與蹦床函數(shù)相對(duì)應(yīng)的一個(gè)或者多個(gè)條目分配到代碼棧103上。在將與預(yù)填充的 蹦床函數(shù)相對(duì)應(yīng)的代碼棧條目分配在代碼棧103上之后,將代碼棧存儲(chǔ)器區(qū)域107設(shè)定為可 執(zhí)行的并且不可寫的。在代碼棧存儲(chǔ)器區(qū)域107在將與蹦床函數(shù)相對(duì)應(yīng)的條目分配在代碼 棧103上期間不可執(zhí)行的實(shí)施例中,可以提供恢復(fù)代碼以供應(yīng)用104中并行執(zhí)行的任何其它 線程使用。代碼棧103中與蹦床函數(shù)相對(duì)應(yīng)的條目的數(shù)據(jù)(諸如靜態(tài)鏈數(shù)據(jù)和函數(shù)地址數(shù) 據(jù))可以存儲(chǔ)在存儲(chǔ)器105中的單獨(dú)數(shù)據(jù)區(qū)域中(諸如數(shù)據(jù)區(qū)域113);這在下面關(guān)于表格1A-B和圖6進(jìn)行了更詳細(xì)的討論。
[0020] 在一些實(shí)施例中,立即將具有限制許可(諸如不能讀取、不能寫入和不能執(zhí)行許可 的組合)的一個(gè)或者多個(gè)存儲(chǔ)頁面設(shè)置在存儲(chǔ)器105中的代碼棧存儲(chǔ)器區(qū)域107前和/或后 以通過例如位于代碼棧存儲(chǔ)器區(qū)域107區(qū)域附近的緩沖區(qū)的溢出或者下溢防止任何意外的 引用、溢出或者下溢到達(dá)代碼棧存儲(chǔ)器區(qū)域107。還可以可選地將一個(gè)或者多個(gè)保護(hù)頁面設(shè) 置在代碼棧存儲(chǔ)器區(qū)域107中的代碼棧103上面和下面以用于進(jìn)一步保護(hù)代碼棧103。
[0021 ]每個(gè)代碼棧條目可以具有數(shù)據(jù)棧102中的相應(yīng)棧幀,并且與分配代碼棧條目的棧 幀相對(duì)應(yīng)。棧幀可以由處理器101自動(dòng)地分配和解除分配,并且可以保持任何適當(dāng)?shù)淖兞俊?代碼棧存儲(chǔ)器區(qū)域107可以相對(duì)遠(yuǎn)離數(shù)據(jù)棧存儲(chǔ)器區(qū)域106地設(shè)置在計(jì)算機(jī)系統(tǒng)100的存儲(chǔ) 器映射中以避免對(duì)代碼棧存儲(chǔ)器區(qū)域107的意外或者惡意寫入。
[0022]在表格1A中示出了蹦床函數(shù)代碼的示例。在一些實(shí)施例中,諸如表格1A所示的蹦 床函數(shù)代碼可以插入在代碼棧103中的多個(gè)條目中,以及代碼棧103中的這些條目中的每一 個(gè)可以具有為代碼棧103中的每個(gè)蹦床函數(shù)指定唯一相應(yīng)函數(shù)地址和靜態(tài)鏈的對(duì)應(yīng)相應(yīng)數(shù) 據(jù)區(qū)域(諸如數(shù)據(jù)區(qū)域113)。
[0023] 表格1A:示例蹦床函數(shù)代碼
[0026] 參照表格1A的代碼,在由標(biāo)簽"trampoline_initial"指示的位置處用適合于將容 納所調(diào)用函數(shù)的返回值的鏈路寄存器讀到寄存器r0中的指令"mflr rO"開始執(zhí)行。指令 "bl.+4"適合于典型地在生成下一個(gè)指令的值時(shí)用作返回地址,并且將控制轉(zhuǎn)移至如指示 當(dāng)前地址加4個(gè)字節(jié)的記數(shù)法".+4"指示的下一個(gè)指令。指令"mflr rll"將該地址從鏈路寄 存器加載到寄存器rll中以稍后用作尋址引用。指令"mtlr rO"將先前加載到rO中的返回地 址恢復(fù)到鏈路寄存器lr中。指令"Id rl2,8192(rl 1)"使用寄存器rl 1