Thank you Pierron! I think i should make my situation clearer. I need your patient.
-----------------------------An Instance of JitCode before and after protection---------------------- Suppose the original Jitcode is looked as the following: #begin jitcode [Codegen] ****** [Codegen] ****** [Codegen] ret #end jitcode My scheme tries to protect only valid (aligned) RET instructions. (By the way, this scheme is only a part of my whole security scheme.) The JitCode would be like the following after enforcing the protection. #begin jitcode [Codegen] xorl $cookie, (%rsp) [Codegen] ***** [Codegen] ****** [Codegen] xorl $cookie, (%rsp) [Codegen] ret #end jitcode I use XOR instructions to encrypt and decrypt the return-address. In this way, the RET instructions cannot be used for ROP attacks. I intend to protect all RET instructions of JitCodes (exclude all stubs) , so baseline'd code and ion'ed code would be hardened in this fashion. ----------------------------------------end----------------------------------------------------- ----------------------------------------Challenges----------------------------------------------------- The key point is to ensure that the encrypting and decrypting operations are paired with the same cookie value. Otherwise, the program (i.e. the js shell) would be crashed because it will use a encrypted return-address. However, making them paired is a big challenge as the control flow sometimes exits the JitCode in the middle rather than at the end by executing the tailed RET instruction. An good instance occurs when osring from baseline'd code to ion'ed code; the control-flow transition is implemented by the function DoWarmUpCounterFallback. In this instance, the return-address (an address within the EnterBaseJit Stub) of baseline'ed code is encrypted with a cookie, suppose 0x11223344. However, this return-address will also be used by Ion'ed code for returning, besides encrypting and decrypting it with another cookie. Therefore, i have to make the return address clean by decrypting it with 0x11223344 before transition. I do this work at the end of function DoWarmUpCounterFallback. ---------------------------------------end--------------------------------------------- ----Maybe to prototype it, it would be easier to create some reserved memory which is used as a second stack space which only contains the cookies? ----You could store them as part of the JSContext*, and fetch the one corresponding to the top of the stack. It's a good tip. I think we can reserve memory to store a RB-tree to record the beginning and end of each JitCode; and add a new field in JitCode to store the cookie. With this tree, we can retrieve the correct JitCode instance according to a code address (e.g. an address interrupted for bailing-out), and then get the cookie for decryption. In this way, no need to modify the the JitFramLayout structures. This scheme is simple and also applicable for WebAssembly / Asm.js. My current implementation applies a trick. I use a single cookie which is the highest bit of address value. So, my cookie is 0x80000000 and 0x8000000000000000 in x86 and x64 platforms, receptively. In this way, by only examining the return-address, we can decide whether it is encrypted or not; and we can decrypt it simply by clear the highest bit. -----What are you issues with bailouts and exceptions? They are basically reading a register dump from the stack to build a MachineState (structure of pointers to each register spilled location if any) and then -----unwind the frame and in case of a bailout replace it by the one created by Baseline. I found it is hard for me to pair the encrypting and decrypting operations when bailing out mechanism is activated. The may reason is that, to be honest, i cannot exactly decide where the control-flow would go in all cases. As a result, i cannot exactly decide which return-address should be decrypted in the bailing-out process. I will give more details after i running the JIT-test cases. Thank you very much. 2017-03-22 23:44 GMT+08:00 Nicolas B. Pierron <nicolas.b.pier...@mozilla.com >: > On 03/22/2017 04:07 AM, Yuan Pinghai wrote: > >> In my current design, the cookie is stored in a new field (named >> retCookie_) of JitCode, and each JITCODE (representing an instance of >> JitCode) has its own cookie. In this way, when i need the original >> return-address, i can recover it by first getting the JITCODE and then >> fetching the cookie. Now, my problem is how can i get the correct JITCODE >> with an address (e.g. the interrupted address before bailing-out)? >> > > The CalleeToken of JitFrameLayout frames holds either a JSFunction or a > JSScript which contains a pointer to the Baseline and Ion structure > containing references to the JitCode. > > When a JitCode is invalidated (Ion), the JitCode pointer is written above > the return address. JitFrameIterator::ionScript() should do the proper > work to get the information you are looking for. > > Note that JitCode are used for all trampoline code which are created when > the JitRuntime is created. (see Trampoline-*.cpp files) and these should be > registered on the Runtime. > > Our stack frames are making assumption about the alignment of the stack, > thus if you add any fields in the CommonFrameLayout, or JitFrameLayout, > these might cause issue in all code able to produce code, in which case you > should look for MacroAssembler::call and MacroAssembler::callJit. > > WebAssembly / Asm.js are not using any of the Jit frames. Instead they > are using the same frame layout as the ABI of the system, with some > variations around the manipulation of SIMD registers. > > Could some body give me a tip? Any suggestions are welcome. I appreciate >> for the help! >> > > To be honest, our stack frames are not the easiest thing to manipulate. > > Maybe to prototype it, it would be easier to create some reserved memory > which is used as a second stack space which only contains the cookies? > > You could store them as part of the JSContext*, and fetch the one > corresponding to the top of the stack. > > > By the way, i am working on Spidermonkey 45. By honest, i don't think i >> have enough knowledge on fixing the bailing-out and exception handling >> mechanisms, i also need suggestions on them. >> > > What are you issues with bailouts and exceptions? They are basically > reading a register dump from the stack to build a MachineState (structure > of pointers to each register spilled location if any) and then unwind the > frame and in case of a bailout replace it by the one created by Baseline. > > What would matter would be to edit the return address, knowing the caller > & callee, which you should have in both cases with the JitFrameIterator. > > > -- > Nicolas B. Pierron > _______________________________________________ > dev-tech-js-engine-internals mailing list > dev-tech-js-engine-internals@lists.mozilla.org > https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals > _______________________________________________ dev-tech-js-engine-internals mailing list dev-tech-js-engine-internals@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals