Just-in-time Compiler in JavaScriptCore (WebKit)

Just-in-time Compiler in JavaScriptCore (WebKit)

Articles , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , 23 Comments

last video we explored how JavaScript core the JavaScript engine from WebKit stores objects and values in memory now in this video I want to learn a bit more about the JIT the just-in-time compiler this series on browse exploitation is supported by SSD secure disclosure check out the description for more information simply speaking the just-in-time compiler compiles JavaScript bytecode which is executed by the JavaScript virtual machine into native machine code like you would compile C code but there is a bit more fanciness when it comes to JIT in JavaScript core so how can we learn about it I got another tip from Linus to check out some official web kit resources like this article on the WebKit block JavaScript core CSI a crash site investigation story today I will describe some of these tools that WebKit engineers use by telling the story of how we diagnosed a real bug in their JSC virtual machine so this is a block intended for people that would like to contribute to WebKit and the author shares a lot of very valuable insight into how to debug a crash in order to find the root cause and this is exactly what we want to know as a security researcher as well for example it describes how to create an address sanitizer built of WebKit in order to catch possible heap overflows or use after free issues that for normal programs often don't crash right away but we are currently interested in the JIT stuff and further into the article we find the following JC comes with multiple tiers of execution engines you might have read about them here this is an article that introduces the FTL JIT there are four tiers tier one there ll in interpreter tio2 the baseline JIT compiler tier 3 the DFG jet and here for the FTL jet so tier one is the regular interpreter that's the basic JavaScript virtual machine we can have a quick look into the low-level interpreter cpp source file which contains the interpreter loop so it simply loops over the javascript bytecode and then execute each instruction so now when a function is called a lot it can become hot that is the term describing that it's executing a lot and then javascriptcore might decide to jet the function with the first tier the baseline jet and in the corresponding jet d'eau CPP file we can get again some additional information when the ll int determines it wants to do OSR entry into the baseline jet in a loop it will pass in the bytecode offset it was executing it when it kicked off our compilation we only need to compile code for anything reachable from that bytecode offset OS r on stack replacement is basically aware you can't switch on the fly to the compiled code it's still very compatible so to say with the bytecode as there hasn't been any optimization yet from the introducing the WebKit FTL JIT we can also read the first execution of any function always starts in the interpreter tier as soon as any statement in the function executes more than a hundred times or the function is called more than six time whichever comes first execution is diverted into code compiled by the baseline JIT this eliminates some of the interpreters overhead but lacks any serious compiler optimization once any statement executes more than a thousand times in baseline code or the waistline functions invoked more than sixty six times we divert execution again to the DFG jet DFG stands for data flow graph so that kind of already reveals a bit what that step is about the article also has a nice picture describing the DFG pipeline the DFG starts by converting byte code into the DFG cps form cps stands for continuation passing style which means your code doesn't use returns but instead continues and passes on to the next function if you have L done some no GS Express development I think you can imagine it like the next function so this form reveals dataflow relationships between variables and temporaries then profiling information is used to infer guesses about types and those guesses are used to insert a minimal set of type checks traditional compile optimization follow the compiler finishes by generating machine code directly from the data flow graph so here it starts to get interesting the JIT compiler guesses types and if the JIT believes types don't change the JIT can decide to remove certain checks which of course can speed up the code dramatically if it's a function that is called a lot but that is not all after the F gjett there is another jet the FTL faster than light when the steel was first introduced adduced the known compiler beckoned LLVM to apply much more typical compiler optimizations the FTL jet is designed to bring aggressive c-like optimizations to JavaScript at some point LLVM got replaced by b3 but the idea is the same and that JIT compiler might even make more assumptions on the code but let's look at this a bit more practically this is again where the article about the crash investigation is excellent it introduces several environment variables that can be used to control the behavior of the JIT in an able debugging output for example we could use JC use JIT to disable the JIT entirely or use JSC use FTL j't to only disable FTL of the last year or we can disable threads that do jet in parallel or we can report and print every time when any JIT does optimization so an l DB I set the environment variable to turn everything on and then restart JSC this already caused us some jet optimization debug prints looking at the function names that budgeted it looks like things like jar at ABS etc have already been optimized but now we want to get our own function so here's a life overflow function that takes a simple number as parameter then prepares a result variable and loops from I is equals to 0 to n and sums it up in a result simple next we have to make the function hot we can do this with a simple loop calling that function let's start with only four executions it shows some output but not what we want also executing it 10 times in a loop doesn't do anything but calling it a few more times we will get the baseline JIT here is a compiled assembly code equivalent of the JavaScript function let's try to trigger an even more aggressive chip let's increase the loop and boom DFG JIT and now let's go totally crazy adjust the loop FTL jet boom there's also so much more output but to be honest no clue what that all means but the important part is just that we have learned about various debugging methods and tricks to dig deeper now you know a bit more about the JIT compilers from last video you also know how javascript objects arrays and values are represented in memory now consider the following idea if the JIT compiler guesses and assumes types in the code and removes checks and for example just simply moves from a certain memory offset could that be abused just hypothetically let's say jittered code expects a javascript array with doubles and directly x on these values the JIT compiler then optimizes all the checks away but then you find a way to replace one entry of the array with an object now an object would be placed as a pointer into that area so if judgeth code has known checks and for example returns the first entry of this array it would return that pointer as a double right that would be pretty bad and that's actually one of the typical browser vulnerability patterns and we will see that in action soon but how does the JIT try to prevent things like this from happening well it turns out that the developers try to model every function that has an effect on the assumptions of the JIT compiler so if there is anything that could change the layout of that array for example when an object is placed into a double array then such a function should be marked dangerous let me read you a quick excerpt from this CDI article about inverting new assumptions a guide to treat comparisons here they write the way to state that an operation is potentially dangerous to prevent later optimizations is to call a function called clobber world which among other things will break all assumptions about the types of all arrays within the graph so the JavaScript engine tries to mark everything that could have potential side effects by calling clobber world side effects could be things like we just thought about like changing the type of a value and something else didn't expect that change so here's the function Kluber world implemented in the DFG JIT part this will call Club of structures which will set set structure clobber State two structures are clobbered so side effects that the JIT has to be very careful about obviously things where for example the structure of an object changes let's say the JIT optimizes accessing a property X on an object and suddenly you removed it it has to be marked that the structure changed so that jutted code can be discarded otherwise you get memory corruptions if you reuse that jutted function but that's enough for now next video we move on to Linus's exploit abusing such a case thanks again to SSD secure disclosure for supporting the Cirie's check out the website and learn more about the SSD vulnerability disclosure program at SST disclosure com you

23 thoughts on “Just-in-time Compiler in JavaScriptCore (WebKit)

  • nikoshalk

    Thank you for the video! Clearing the air all around javascript and how it works under the hood is really interesting

  • ZelenoJabko

    Hans, I love you. You have a gift of explaining everything so well everyone understands!

  • john

    Is there a way to decompile (c++ written) dll/exe? Or atleast know what are they doing/changing?

  • Byamarro2

    It would be nice to see video like this but about V8, since Safari is rather niche.

  • dasten123

    the thing with clobberWorld() was very confusing 🙁 I did not understand what you said at all. Who is calling that? When? So this is a marker for not optimizing certain functions, which is hardcoded for, for example String.valueOf ? huh? Why is that function harmful to optimize? What about user defined functions, are they always optimized? … sorry I think I don't belong here 😐

  • AramesK Channel™

    Could you make a video commenting this video?
    It's about vulnerability of the new WPA3 system

  • TobyAsE120

    I've never seen JS as a real and serious language. Something to use in browsers to spice up the webpage I'm working on. The "real" and interesting compiler-stuff is reserved for "real" languages like C or even python. I never thought about how JS gets executed and that all of this optimization-stuff is used – after all it's just used to spice up webpages.
    Thank you for getting me closer to this topic, my view of JS is changing and I am excited for the rest of the series.

  • Prozacgod

    Oh, nice! A SecuriTeam reference, ages ago I broke apart a JS zero day, and asked a bunch of technical questions about it and Gadi invited me to blog there, I posted… At most an introduction :p. (Couldnt run with the big dogs I guess) But we're still somewhat acquainted, and it was his invite that kept me curious and interested in software vulnerabilities. I think he since moved on from SecuriTeam and doing bigger better things.

  • Hadi Azami

    I wish this video was out before I did a talk on JIT at school

  • Nullbyte

    Really interesting. Thank you very much! Can't wait for the next video!

  • Twittergram

    If water was made of sponge

  • plushoom

    very interesting

  • billigerfusel

    Yeet compiler

  • Varad Mahashabde

    Could there be attacks on the butterfly of a function, changing it to one that of a completely innocent string

  • Hamed Pour

    l love you man! Keep up the excellent work

  • EvilSapphireR

    This turned out to be pretty theoretical. I need to brush up on how JIT compiling in general works to wrap my head fully around this.

  • Vorname Nachname

    I call my group "HDD" which is "Humane Disassembly Disclosure". So i guess you as "SSD" make me go out of business… sarcasm off

  • pitboy1o1 pitboy1o1

    me likey

  • John Stevonson

    Hello LiveOverflow!
    I really tried to be first this time. Sorry for being a bit late.

  • Timo Herngreen

    This video is just in time for my break.

  • Loki, Son of Odin

  • Hackers Blog


  • Omar Mohamed

    1 view
    YouTube is drunk again

Leave a Reply

Your email address will not be published. Required fields are marked *