1 00:00:00,070 --> 00:00:02,430 The following content is provided under a Creative 2 00:00:02,430 --> 00:00:03,820 Commons license. 3 00:00:03,820 --> 00:00:06,060 Your support will help MIT OpenCourseWare 4 00:00:06,060 --> 00:00:10,150 continue to offer high quality educational resources for free. 5 00:00:10,150 --> 00:00:12,700 To make a donation or to view additional materials 6 00:00:12,700 --> 00:00:16,600 from hundreds of MIT courses, visit MIT OpenCourseWare 7 00:00:16,600 --> 00:00:17,260 at ocw.mit.edu. 8 00:00:26,730 --> 00:00:29,110 PROFESSOR: All right, let's get started. 9 00:00:29,110 --> 00:00:32,490 So today we're going to talk about the system called 10 00:00:32,490 --> 00:00:36,340 Native Client, which is actually a real world 11 00:00:36,340 --> 00:00:39,779 system used by Google. 12 00:00:39,779 --> 00:00:42,070 One example, they actually use it in the Chrome browser 13 00:00:42,070 --> 00:00:45,290 to allow web applications to run arbitrary native code. 14 00:00:45,290 --> 00:00:47,070 It's actually a pretty cool system, 15 00:00:47,070 --> 00:00:49,560 and it's also an illustration. 16 00:00:49,560 --> 00:00:52,900 Another isolation or sort of sandboxing or privilege 17 00:00:52,900 --> 00:00:55,320 separation technique, that's called software fault 18 00:00:55,320 --> 00:00:58,850 isolation, doesn't rely on operating systems 19 00:00:58,850 --> 00:01:01,130 to sandbox a process or virtual machines. 20 00:01:01,130 --> 00:01:03,330 But instead, it has a very different approach 21 00:01:03,330 --> 00:01:05,830 to looking at the particular instructions in a binary, 22 00:01:05,830 --> 00:01:09,390 to figure out whether it's going to be safe to run or not. 23 00:01:09,390 --> 00:01:11,900 So before we I guess start looking 24 00:01:11,900 --> 00:01:15,000 at the technical details of the system, let's figure out, 25 00:01:15,000 --> 00:01:18,960 why do these guys actually want to run native code? 26 00:01:18,960 --> 00:01:21,580 So the particular context they are 27 00:01:21,580 --> 00:01:23,980 interested in applying their solution to 28 00:01:23,980 --> 00:01:26,420 is a web browser, where you can already 29 00:01:26,420 --> 00:01:29,750 run JavaScript code and maybe Flash, and maybe 30 00:01:29,750 --> 00:01:31,510 a couple of other things. 31 00:01:31,510 --> 00:01:34,070 Why are these guys so excited about running raw x86? 32 00:01:34,070 --> 00:01:36,758 It seems like a step backwards. 33 00:01:36,758 --> 00:01:38,590 AUDIENCE: Really fast computation. 34 00:01:38,590 --> 00:01:41,006 PROFESSOR: Yeah, that's one huge advantage of native code. 35 00:01:41,006 --> 00:01:43,560 Even though it might be unsafe from some perspectives, 36 00:01:43,560 --> 00:01:45,210 it's really high performance. 37 00:01:45,210 --> 00:01:47,245 And whatever you can do in JavaScript, 38 00:01:47,245 --> 00:01:49,870 presumably you could just write the same thing and assemble it, 39 00:01:49,870 --> 00:01:53,900 and it'll go at least as fast-- probably much faster. 40 00:01:53,900 --> 00:01:54,650 Any other reasons? 41 00:01:54,650 --> 00:01:55,395 Yeah? 42 00:01:55,395 --> 00:01:56,562 AUDIENCE: Run existing code? 43 00:01:56,562 --> 00:01:57,228 PROFESSOR: Yeah. 44 00:01:57,228 --> 00:01:58,610 So another big thing is maybe not 45 00:01:58,610 --> 00:02:00,110 everything is written in JavaScript. 46 00:02:00,110 --> 00:02:03,090 So if you have an existing application-- 47 00:02:03,090 --> 00:02:06,664 I guess 'legacy' in industry terminology-- 48 00:02:06,664 --> 00:02:08,580 if you have some existing code that you really 49 00:02:08,580 --> 00:02:10,774 want to run in the web, then this 50 00:02:10,774 --> 00:02:11,940 seems like a great solution. 51 00:02:11,940 --> 00:02:14,530 Because you could just take an existing library, 52 00:02:14,530 --> 00:02:17,485 like some complicated graphics processing engine that's 53 00:02:17,485 --> 00:02:20,050 both performance sensitive and lots of complicated stuff 54 00:02:20,050 --> 00:02:21,550 you don't want to re-implement, then 55 00:02:21,550 --> 00:02:23,677 this seems like a good solution. 56 00:02:23,677 --> 00:02:26,260 Anything else-- if you're just like programming a new web app, 57 00:02:26,260 --> 00:02:29,460 should you use Native Client if you 58 00:02:29,460 --> 00:02:33,910 don't care about legacy or performance so much? 59 00:02:33,910 --> 00:02:35,240 Any other reasons? 60 00:02:37,592 --> 00:02:38,550 I guess another-- yeah? 61 00:02:38,550 --> 00:02:39,990 AUDIENCE: You don't have to use JavaScript. 62 00:02:39,990 --> 00:02:42,227 PROFESSOR: Yeah, that's an awesome reason, right? 63 00:02:42,227 --> 00:02:43,810 If you don't like JavaScript, then you 64 00:02:43,810 --> 00:02:44,590 don't have to use it, right? 65 00:02:44,590 --> 00:02:47,140 You can actually use, well, C, if you are so inclined. 66 00:02:47,140 --> 00:02:49,680 You could run Python code, you could write Haskell, 67 00:02:49,680 --> 00:02:51,910 whatever you think is useful. 68 00:02:51,910 --> 00:02:54,400 You could actually support other languages all of a sudden. 69 00:02:58,240 --> 00:03:03,490 So this is a reasonably compelling list of-- motivation 70 00:03:03,490 --> 00:03:06,700 for them to run native code in the browser, 71 00:03:06,700 --> 00:03:09,389 and it turns out to be reasonably tricky to get right. 72 00:03:09,389 --> 00:03:11,430 And we'll look at the technical details, I guess, 73 00:03:11,430 --> 00:03:13,100 of how it works in a second. 74 00:03:13,100 --> 00:03:15,730 But just to show you guys what this paper is talking about, 75 00:03:15,730 --> 00:03:18,760 I just want to show a very simple tutorial demo 76 00:03:18,760 --> 00:03:22,410 almost that I got out of their Native Client website. 77 00:03:22,410 --> 00:03:25,850 It's fairly simple as it turns out to just take a C++ or a C 78 00:03:25,850 --> 00:03:28,130 program and run in the browser. 79 00:03:28,130 --> 00:03:29,970 So just to show you what this looks like, 80 00:03:29,970 --> 00:03:32,640 here's basically a demo I mostly sort of took 81 00:03:32,640 --> 00:03:34,600 from one of their examples. 82 00:03:34,600 --> 00:03:39,110 So you can look at a web page like this index HTML file. 83 00:03:39,110 --> 00:03:42,360 And inside of it, you have a bunch of JavaScript code. 84 00:03:42,360 --> 00:03:44,620 And the reason this JavaScript code exists 85 00:03:44,620 --> 00:03:47,710 is to sort of interact with the Native Client piece. 86 00:03:47,710 --> 00:03:50,810 So the way you can sort of think of this running in the browser 87 00:03:50,810 --> 00:03:53,904 is that you have the browser-- well, we'll 88 00:03:53,904 --> 00:03:55,570 talk much more about web security later, 89 00:03:55,570 --> 00:03:59,320 but roughly you have some sort of a page, web page that 90 00:03:59,320 --> 00:04:01,540 contains some JavaScript code. 91 00:04:01,540 --> 00:04:05,310 And this runs with the pages privileges. 92 00:04:05,310 --> 00:04:08,160 And this can do various things to the web page 93 00:04:08,160 --> 00:04:11,140 itself, maybe talk to the network in some circumstances. 94 00:04:11,140 --> 00:04:13,080 But what Native Client allows you to do 95 00:04:13,080 --> 00:04:17,060 is to have this Native Client module running 96 00:04:17,060 --> 00:04:19,471 sort of to the side in the browser as well. 97 00:04:19,471 --> 00:04:20,970 And the JavaScript code can actually 98 00:04:20,970 --> 00:04:25,600 interact with the Native Client module and get responses back. 99 00:04:25,600 --> 00:04:27,440 And what you see here in this web page 100 00:04:27,440 --> 00:04:29,140 is the little bit of JavaScript code 101 00:04:29,140 --> 00:04:30,980 that's necessary in Native Client 102 00:04:30,980 --> 00:04:34,060 to interract with the particular NaCl module 103 00:04:34,060 --> 00:04:35,920 that we're going to be running. 104 00:04:35,920 --> 00:04:38,300 And you can send messages to this module. 105 00:04:38,300 --> 00:04:40,540 The way you do it is you take this module object 106 00:04:40,540 --> 00:04:42,440 in JavaScript, and you call it postMessage. 107 00:04:42,440 --> 00:04:44,530 And you could actually supply a message 108 00:04:44,530 --> 00:04:47,560 to send to the Native Client module. 109 00:04:47,560 --> 00:04:49,430 And when the Native Client module responds, 110 00:04:49,430 --> 00:04:52,751 it'll run this handle message function in JavaScript. 111 00:04:52,751 --> 00:04:54,250 And in this particular case, it just 112 00:04:54,250 --> 00:04:59,080 pops up and alerts dialog box in my browser. 113 00:04:59,080 --> 00:05:01,270 So it's a fairly simple interface from the web page 114 00:05:01,270 --> 00:05:02,589 side, from the JavaScript side. 115 00:05:02,589 --> 00:05:04,630 And the only thing you additional you have to do, 116 00:05:04,630 --> 00:05:07,560 is you actually have to declare this Native Client 117 00:05:07,560 --> 00:05:09,210 module this way. 118 00:05:09,210 --> 00:05:12,489 So you just say embed module with a particular ID. 119 00:05:12,489 --> 00:05:14,030 And the sort of most interesting part 120 00:05:14,030 --> 00:05:16,290 is this source equals Hello. 121 00:05:16,290 --> 00:05:19,230 some NMF barch attribute. 122 00:05:19,230 --> 00:05:21,710 And this one just says, well here's the roughly executable 123 00:05:21,710 --> 00:05:24,220 file that you need to load and start running 124 00:05:24,220 --> 00:05:27,230 in the native side of things. 125 00:05:27,230 --> 00:05:30,880 And this native code actually looks like any other C++ code 126 00:05:30,880 --> 00:05:32,230 you might write roughly. 127 00:05:32,230 --> 00:05:34,290 So here's the program. 128 00:05:34,290 --> 00:05:37,620 The interesting part is roughly this handle message function. 129 00:05:37,620 --> 00:05:42,380 So this is a C++ class, and whenever the JavaScript code 130 00:05:42,380 --> 00:05:44,510 sends some message to the native code, 131 00:05:44,510 --> 00:05:46,230 it'll actually run this function. 132 00:05:46,230 --> 00:05:48,800 And it'll check if the message that's being sent is hello. 133 00:05:48,800 --> 00:05:51,310 And if so, construct a reply string of some sort 134 00:05:51,310 --> 00:05:52,809 and send it back. 135 00:05:52,809 --> 00:05:53,850 It's fairly simple stuff. 136 00:05:53,850 --> 00:05:56,420 But just to be concrete, let's try 137 00:05:56,420 --> 00:05:58,300 to run it and see what happens. 138 00:05:58,300 --> 00:06:02,360 So we can actually build it, and run a little web 139 00:06:02,360 --> 00:06:08,850 server that is going serve up this page and Native Client 140 00:06:08,850 --> 00:06:09,950 module. 141 00:06:09,950 --> 00:06:12,850 So here I can go to this URL and here we go. 142 00:06:12,850 --> 00:06:14,640 Right, it's actually loaded in the module. 143 00:06:14,640 --> 00:06:16,681 The module seems to have gotten our hello message 144 00:06:16,681 --> 00:06:17,436 from JavaScript. 145 00:06:17,436 --> 00:06:19,720 It replied back with the string back to JavaScript. 146 00:06:19,720 --> 00:06:22,600 And the JavaScript code popped up a dialog box 147 00:06:22,600 --> 00:06:24,390 containing that response. 148 00:06:24,390 --> 00:06:26,710 So it actually does kind of work. 149 00:06:26,710 --> 00:06:29,680 We can try to see if we could crash Native Client-- hopefully 150 00:06:29,680 --> 00:06:34,690 not, but we can take this code and we have this buffer. 151 00:06:34,690 --> 00:06:37,890 We could write a bunch of As to it-- 152 00:06:37,890 --> 00:06:42,020 I don't know, quite a lot-- and see what happens. 153 00:06:42,020 --> 00:06:43,970 So hopefully this shouldn't crash my browser, 154 00:06:43,970 --> 00:06:47,760 because Native Client is trying to provide isolation. 155 00:06:47,760 --> 00:06:50,740 But let's see what happens. 156 00:06:50,740 --> 00:06:53,930 So we can rebuild it, rerun the web server. 157 00:06:53,930 --> 00:06:57,037 And here if you run it, nothing happens. 158 00:06:57,037 --> 00:06:58,620 We don't get the message back anymore, 159 00:06:58,620 --> 00:07:00,224 so clearly the message didn't get 160 00:07:00,224 --> 00:07:01,890 sent back from the Native Client module, 161 00:07:01,890 --> 00:07:03,150 because I don't see any popup. 162 00:07:03,150 --> 00:07:05,980 We can look at the JavaScript console here, 163 00:07:05,980 --> 00:07:08,920 and we can see that the Native Client module tells us 164 00:07:08,920 --> 00:07:10,270 NaCl module crash. 165 00:07:10,270 --> 00:07:14,250 So somehow it caught this buffer flow scribbling 166 00:07:14,250 --> 00:07:16,940 over some memory, or maybe it jumped to some bad address 167 00:07:16,940 --> 00:07:18,780 containing all As. 168 00:07:18,780 --> 00:07:21,110 But any case, the Native Client module 169 00:07:21,110 --> 00:07:23,850 is actually able to contain this without this arbitrary 170 00:07:23,850 --> 00:07:26,170 sort of memory corruption in the module affecting 171 00:07:26,170 --> 00:07:28,620 the rest of the browser. 172 00:07:28,620 --> 00:07:32,150 So this is roughly just a quick demo of what the system is, 173 00:07:32,150 --> 00:07:38,209 and how you use it as an end user or web developer. 174 00:07:38,209 --> 00:07:39,500 So let's look now at some more. 175 00:07:39,500 --> 00:07:42,380 So that's all in terms of demos I have to show you. 176 00:07:42,380 --> 00:07:45,770 So let's look more now at how a Native Client is going to work, 177 00:07:45,770 --> 00:07:49,400 or perhaps even why we need this particular design as opposed 178 00:07:49,400 --> 00:07:51,050 to some of the alternatives. 179 00:07:54,120 --> 00:07:59,384 So if your goal, I guess is to sandbox native code, 180 00:07:59,384 --> 00:08:01,300 there's a number of alternatives you can make. 181 00:08:01,300 --> 00:08:02,716 People actually had these problems 182 00:08:02,716 --> 00:08:04,640 before, performance existing legacy code 183 00:08:04,640 --> 00:08:07,780 and other languages before Native Client came around. 184 00:08:07,780 --> 00:08:10,960 And people just solved them in different ways 185 00:08:10,960 --> 00:08:14,540 that maybe weren't as satisfying from a security standpoint 186 00:08:14,540 --> 00:08:17,570 or usability standpoint as Native Client. 187 00:08:17,570 --> 00:08:19,649 But it is doable. 188 00:08:19,649 --> 00:08:20,190 So let's see. 189 00:08:20,190 --> 00:08:21,606 So what could you do if you really 190 00:08:21,606 --> 00:08:25,020 want to run native code in a browser? 191 00:08:28,730 --> 00:08:33,974 So one option that people did was to trust the developer. 192 00:08:37,440 --> 00:08:39,500 And maybe a variant of this approach 193 00:08:39,500 --> 00:08:43,870 is to ask the user whether they want to run some piece of code 194 00:08:43,870 --> 00:08:46,420 in their browser or not. 195 00:08:46,420 --> 00:08:47,920 So does everybody understand roughly 196 00:08:47,920 --> 00:08:48,920 what the plan is, right? 197 00:08:48,920 --> 00:08:51,660 Like instead of having that whole Native Client compilation 198 00:08:51,660 --> 00:08:52,710 strategy, I could have just built 199 00:08:52,710 --> 00:08:54,700 a simple C program, served it up on the browser, 200 00:08:54,700 --> 00:08:56,030 and maybe the browser asked, do you 201 00:08:56,030 --> 00:08:57,238 want to run this site or not? 202 00:08:57,238 --> 00:08:59,270 If I click yes, then it accidentally 203 00:08:59,270 --> 00:09:02,550 scribbled over the browser's memory and crashes the browser. 204 00:09:02,550 --> 00:09:04,860 So it's possible, right? 205 00:09:04,860 --> 00:09:06,360 It certainly solves all these goals, 206 00:09:06,360 --> 00:09:07,980 but what's wrong with it? 207 00:09:07,980 --> 00:09:11,180 Well, I guess there's the insecurity part, which 208 00:09:11,180 --> 00:09:12,560 is unfortunate. 209 00:09:12,560 --> 00:09:15,340 One way to potentially get around this-- and some systems 210 00:09:15,340 --> 00:09:15,840 did. 211 00:09:15,840 --> 00:09:17,720 Like Microsoft had the system called 212 00:09:17,720 --> 00:09:22,190 ActiveX, that basically implemented this plan. 213 00:09:22,190 --> 00:09:26,410 You could serve binaries to IE, the browser on your machine. 214 00:09:26,410 --> 00:09:28,400 And as long as it came with a certificate 215 00:09:28,400 --> 00:09:30,860 from particular developer signed by let's say 216 00:09:30,860 --> 00:09:33,345 Microsoft or someone else, then it 217 00:09:33,345 --> 00:09:35,329 would actually run this code. 218 00:09:35,329 --> 00:09:37,620 What do you guys think about this plan, is this useful? 219 00:09:37,620 --> 00:09:38,496 Yeah? 220 00:09:38,496 --> 00:09:39,412 AUDIENCE: [INAUDIBLE]. 221 00:09:44,750 --> 00:09:46,000 PROFESSOR: That's right, yeah. 222 00:09:46,000 --> 00:09:49,160 So right, you really have to put quite a bit of trust 223 00:09:49,160 --> 00:09:50,990 into whoever it is that's signing this, 224 00:09:50,990 --> 00:09:53,280 that they will only sign binaries that 225 00:09:53,280 --> 00:09:55,954 will not to do something bad. 226 00:09:55,954 --> 00:09:57,870 But it's kind of vague what this bad thing is. 227 00:09:57,870 --> 00:09:59,619 And presumably they're just writing C code 228 00:09:59,619 --> 00:10:04,250 and signing it blindly without doing a huge amount of work. 229 00:10:04,250 --> 00:10:07,480 In which case, you might well be susceptible to some problems 230 00:10:07,480 --> 00:10:09,210 down the line. 231 00:10:09,210 --> 00:10:10,762 What if we ask the user? 232 00:10:10,762 --> 00:10:11,734 Yeah? 233 00:10:11,734 --> 00:10:12,650 AUDIENCE: [INAUDIBLE]. 234 00:10:16,239 --> 00:10:17,530 PROFESSOR: Oh yeah, yeah, yeah. 235 00:10:17,530 --> 00:10:19,970 Like the user's goal is to run this thing. 236 00:10:19,970 --> 00:10:24,180 And even if the user wants to be cautious, it's actually not 237 00:10:24,180 --> 00:10:25,700 clear how should the user decide? 238 00:10:25,700 --> 00:10:27,410 Suppose I really want to understand, 239 00:10:27,410 --> 00:10:29,192 should I allow this program to run? 240 00:10:29,192 --> 00:10:30,650 All it tells me is well, maybe it's 241 00:10:30,650 --> 00:10:32,358 created from Google.com or Microsoft.com, 242 00:10:32,358 --> 00:10:34,590 and its file name as foo.exe. 243 00:10:34,590 --> 00:10:37,587 I don't know, like what's in there? 244 00:10:37,587 --> 00:10:39,170 Even if I dissemble the code, it might 245 00:10:39,170 --> 00:10:40,794 be very hard to tell whether it's going 246 00:10:40,794 --> 00:10:42,310 to do something bad or not. 247 00:10:42,310 --> 00:10:44,270 So it's actually really hard to decide. 248 00:10:44,270 --> 00:10:45,980 So one way to think of Native Client 249 00:10:45,980 --> 00:10:48,722 is it's a mechanism by which users can actually 250 00:10:48,722 --> 00:10:50,680 get some confidence whether they should say yes 251 00:10:50,680 --> 00:10:51,888 or not to running this thing. 252 00:10:51,888 --> 00:10:54,045 So in practice, I guess like Paul Young, who 253 00:10:54,045 --> 00:10:55,670 was giving his guest lecture last week, 254 00:10:55,670 --> 00:10:57,400 and he suggested that you should enable this click 255 00:10:57,400 --> 00:10:58,566 to play extension in Chrome. 256 00:10:58,566 --> 00:11:00,550 So every extension, including Native Client, 257 00:11:00,550 --> 00:11:03,209 you should rush click on this thing before it starts running. 258 00:11:03,209 --> 00:11:04,750 So in some ways, that's ask the user. 259 00:11:04,750 --> 00:11:06,080 But then the user actually has some sense, 260 00:11:06,080 --> 00:11:08,130 that well, if I click it, I'm still hopefully 261 00:11:08,130 --> 00:11:10,630 safe in the sense that Native Client will protect me. 262 00:11:10,630 --> 00:11:13,210 So the two aren't necessarily exclusive, 263 00:11:13,210 --> 00:11:15,640 but you really want some technical guarantee 264 00:11:15,640 --> 00:11:19,300 from Native Client that ensures that even if you say yes, 265 00:11:19,300 --> 00:11:21,290 there are something meaningful that 266 00:11:21,290 --> 00:11:24,210 isn't enforcing your security. 267 00:11:24,210 --> 00:11:26,440 So does this make sense? 268 00:11:26,440 --> 00:11:27,410 OK. 269 00:11:27,410 --> 00:11:31,340 So the other I guess approach that people have taken, 270 00:11:31,340 --> 00:11:37,443 is to use an OS or hardware sandboxing, or isolation. 271 00:11:41,730 --> 00:11:45,470 So this is things we looked at in the last couple of lectures. 272 00:11:45,470 --> 00:11:49,800 So maybe you would use Unix, isolation mechanisms. 273 00:11:49,800 --> 00:11:51,790 Maybe if you had something more sophisticated, 274 00:11:51,790 --> 00:11:53,289 if you're running a free [INAUDIBLE] 275 00:11:53,289 --> 00:11:54,790 maybe you would use Capsicum. 276 00:11:54,790 --> 00:11:58,060 It seems very well suited to sandboxing some piece of code. 277 00:11:58,060 --> 00:12:00,450 Because you can give it very few capabilities, and then 278 00:12:00,450 --> 00:12:02,070 it seems great. 279 00:12:02,070 --> 00:12:04,380 And Linux has a similar mechanism called Seccomp 280 00:12:04,380 --> 00:12:07,420 that we briefly touched on in the last lecture, that could 281 00:12:07,420 --> 00:12:09,844 allow you to do similar things. 282 00:12:09,844 --> 00:12:11,425 So it seems like there is already 283 00:12:11,425 --> 00:12:15,410 a mechanism for writing code in isolation on your machine. 284 00:12:15,410 --> 00:12:18,810 Why are these guys opposed to using this existing solution? 285 00:12:18,810 --> 00:12:22,130 Then they are like reinventing the wheel for some reason. 286 00:12:22,130 --> 00:12:24,110 So what's going on? 287 00:12:24,110 --> 00:12:25,110 Yeah? 288 00:12:25,110 --> 00:12:27,110 Oh yeah? 289 00:12:27,110 --> 00:12:29,925 AUDIENCE: Maybe they want to minimize the [INAUDIBLE]? 290 00:12:29,925 --> 00:12:31,800 PROFESSOR: Yeah, so in some sense, maybe they 291 00:12:31,800 --> 00:12:34,429 don't want to trust the operating system. 292 00:12:34,429 --> 00:12:36,220 So maybe they're here, and they're actually 293 00:12:36,220 --> 00:12:39,430 worried about OS bugs. 294 00:12:39,430 --> 00:12:42,410 It might be that the previous dekernel, the Linux kernel, 295 00:12:42,410 --> 00:12:46,000 has quite a lot of C code written that they don't want 296 00:12:46,000 --> 00:12:47,680 to audit for correctness, or maybe 297 00:12:47,680 --> 00:12:49,263 can't even audit for correctness, even 298 00:12:49,263 --> 00:12:50,360 if they wanted to. 299 00:12:50,360 --> 00:12:54,549 And in one of these Capsicum or Seccomp based isolation plan, 300 00:12:54,549 --> 00:12:56,840 you probably do trust quite a bit of code in the kernel 301 00:12:56,840 --> 00:13:00,176 to be correct, for the sandbox to actually hold and enforce 302 00:13:00,176 --> 00:13:00,910 isolation. 303 00:13:00,910 --> 00:13:02,370 Yeah? 304 00:13:02,370 --> 00:13:06,105 AUDIENCE: As you get a lot more ways to use browsers and stuff, 305 00:13:06,105 --> 00:13:08,620 like you'd have to deal with having some sort of thing 306 00:13:08,620 --> 00:13:10,612 you're doing with it on like iOS and Android, 307 00:13:10,612 --> 00:13:12,420 and all these other things, accessing-- 308 00:13:12,420 --> 00:13:13,220 PROFESSOR: Yeah, so it's actually 309 00:13:13,220 --> 00:13:14,595 another interesting consideration 310 00:13:14,595 --> 00:13:17,200 is that normally my OSes have bugs. 311 00:13:17,200 --> 00:13:19,450 But actually the OSs are incompatible 312 00:13:19,450 --> 00:13:22,520 with each other in some ways, meaning that each OS 313 00:13:22,520 --> 00:13:23,986 has it's own-- like right here. 314 00:13:23,986 --> 00:13:26,235 Well, there's Unix, there's Capsicum, there's Seccomp, 315 00:13:26,235 --> 00:13:27,290 but this is just a Unix variances. 316 00:13:27,290 --> 00:13:29,920 There's Mac OS seatbelt, there's Windows something else, 317 00:13:29,920 --> 00:13:31,970 and the list just keeps going on and on. 318 00:13:31,970 --> 00:13:34,920 So as a result, every platform you 319 00:13:34,920 --> 00:13:37,750 will have to use a different isolation mechanism. 320 00:13:37,750 --> 00:13:39,480 And the thing that actually bothers them 321 00:13:39,480 --> 00:13:42,146 is not so much that they'll have to write different code for Mac 322 00:13:42,146 --> 00:13:43,390 and Windows and Linux. 323 00:13:43,390 --> 00:13:46,510 But more of that, this impacts how you write the thing 324 00:13:46,510 --> 00:13:48,747 inside of the sandbox. 325 00:13:48,747 --> 00:13:50,330 Because in Native Client, you actually 326 00:13:50,330 --> 00:13:53,140 write a piece of code that runs the same way, 327 00:13:53,140 --> 00:13:56,580 or it's the same piece of code the runs on Apple or Windows 328 00:13:56,580 --> 00:13:58,420 or Linux systems. 329 00:13:58,420 --> 00:14:00,655 And if you use these isolation mechanisms, 330 00:14:00,655 --> 00:14:02,790 they actually impose different restrictions 331 00:14:02,790 --> 00:14:04,440 on the program being sandboxed. 332 00:14:04,440 --> 00:14:06,840 So you'll have to write one program that's 333 00:14:06,840 --> 00:14:08,560 going to run inside of a Linux sandbox, 334 00:14:08,560 --> 00:14:11,296 another program inside of a Windows sandbox, and so on. 335 00:14:11,296 --> 00:14:13,400 So this is actually not acceptable to them. 336 00:14:13,400 --> 00:14:17,202 They don't want to deal with these kinds of problems. 337 00:14:17,202 --> 00:14:20,620 So are there other considerations? 338 00:14:20,620 --> 00:14:21,692 Yeah? 339 00:14:21,692 --> 00:14:23,400 AUDIENCE: Presumably performance as well. 340 00:14:23,400 --> 00:14:26,890 Because if you say Capsicum, you need 341 00:14:26,890 --> 00:14:29,510 to fork up a set of [INAUDIBLE], or whatever 342 00:14:29,510 --> 00:14:31,370 is running inside the sandbox. 343 00:14:31,370 --> 00:14:34,135 With here, they can actually run it in the same [INAUDIBLE]. 344 00:14:34,135 --> 00:14:34,830 PROFESSOR: That's true, yeah. 345 00:14:34,830 --> 00:14:36,440 So potentially the approach they take, 346 00:14:36,440 --> 00:14:37,880 the software fault isolation plan 347 00:14:37,880 --> 00:14:39,840 is actually highly performant, and could 348 00:14:39,840 --> 00:14:43,517 outperform these sandboxes at the OS level. 349 00:14:43,517 --> 00:14:44,975 It turns out that in Native Client, 350 00:14:44,975 --> 00:14:49,390 they actually use both their sandbox and the OS sandbox, 351 00:14:49,390 --> 00:14:52,110 just for extra precaution for safety. 352 00:14:52,110 --> 00:14:54,122 So they don't actually win on performance 353 00:14:54,122 --> 00:14:56,080 in their implementation, but they could, right. 354 00:14:56,080 --> 00:14:56,627 Yeah? 355 00:14:56,627 --> 00:14:58,710 AUDIENCE: There is some like control aspect to it. 356 00:14:58,710 --> 00:15:00,834 Because it can control what happens in the browser, 357 00:15:00,834 --> 00:15:04,132 but if they sent one out to the client's machine into their OS, 358 00:15:04,132 --> 00:15:05,590 they sort of don't necessarily know 359 00:15:05,590 --> 00:15:07,990 what might be happening to it? 360 00:15:07,990 --> 00:15:09,930 PROFESSOR: So I guess maybe one way 361 00:15:09,930 --> 00:15:12,630 to think of that is that yeah, the OS might have bugs, 362 00:15:12,630 --> 00:15:15,710 or my OS might not do as good of a job at sandboxing it. 363 00:15:15,710 --> 00:15:18,310 Or maybe the interface is a little different, 364 00:15:18,310 --> 00:15:20,743 so you don't know what the OS is going to expose. 365 00:15:20,743 --> 00:15:22,617 AUDIENCE: So it doesn't like prevent the code 366 00:15:22,617 --> 00:15:24,655 from doing some bad things. 367 00:15:24,655 --> 00:15:26,447 Like there are a lot of cases of bad things 368 00:15:26,447 --> 00:15:27,988 that the code can just do, like maybe 369 00:15:27,988 --> 00:15:29,910 you want to statically analyze the distance, 370 00:15:29,910 --> 00:15:32,034 but they both sit in a loop and then not allow that 371 00:15:32,034 --> 00:15:32,949 as a valid program. 372 00:15:32,949 --> 00:15:34,240 PROFESSOR: So you could, right? 373 00:15:34,240 --> 00:15:36,280 So their approach is quite powerful in the sense 374 00:15:36,280 --> 00:15:39,090 that you could try to look for various kinds of problems 375 00:15:39,090 --> 00:15:41,740 in the code like maybe infinite loops, et cetera. 376 00:15:41,740 --> 00:15:44,480 It's hard to decide, kind of like the holding problem, 377 00:15:44,480 --> 00:15:46,740 whether it's going to have infinite loops or not. 378 00:15:46,740 --> 00:15:50,390 But in principle, you might be able to catch some problems. 379 00:15:50,390 --> 00:15:53,812 I think one actually interesting example that I almost 380 00:15:53,812 --> 00:15:55,270 didn't realize this sort of existed 381 00:15:55,270 --> 00:15:56,936 before reading this paper, is these guys 382 00:15:56,936 --> 00:16:00,255 are worried about hardware bugs as well, that not only are they 383 00:16:00,255 --> 00:16:01,880 worried that the operating system might 384 00:16:01,880 --> 00:16:04,870 have vulnerabilities that the motions code will exploit. 385 00:16:04,870 --> 00:16:07,300 But also that the processor itself 386 00:16:07,300 --> 00:16:10,000 has some instructions that will hang it, 387 00:16:10,000 --> 00:16:12,250 or it'll reboot your machine. 388 00:16:12,250 --> 00:16:15,850 And in principle, your hardware shouldn't have such bug, 389 00:16:15,850 --> 00:16:19,440 because the operating system relies on the hardware 390 00:16:19,440 --> 00:16:23,290 to trap into the kernel if there's anything bad executing 391 00:16:23,290 --> 00:16:26,650 user mode, so that the operating system can take care of it. 392 00:16:26,650 --> 00:16:29,280 But experimentally, it turns out that processors 393 00:16:29,280 --> 00:16:31,129 are so complicated that they do have bugs, 394 00:16:31,129 --> 00:16:32,670 and these guys actually say, well, we 395 00:16:32,670 --> 00:16:34,705 actually found some evidence that this happens. 396 00:16:34,705 --> 00:16:37,760 If you have some complicated instruction that the CPU wasn't 397 00:16:37,760 --> 00:16:40,965 expecting, the CPU will actually halt instead 398 00:16:40,965 --> 00:16:42,950 of trapping to the kernel. 399 00:16:42,950 --> 00:16:43,960 This seems bad. 400 00:16:43,960 --> 00:16:46,290 But I guess it's not a disastrous, if I'm sort of only 401 00:16:46,290 --> 00:16:48,560 running reasonable things on my laptop. 402 00:16:48,560 --> 00:16:51,430 But it is bad if you visit some web page and your computer 403 00:16:51,430 --> 00:16:52,300 hangs. 404 00:16:52,300 --> 00:16:54,130 So they want basically a stronger level 405 00:16:54,130 --> 00:16:57,810 of protection for these Native Client modules than what 406 00:16:57,810 --> 00:17:01,410 you would get out of sort of an OS level isolation, 407 00:17:01,410 --> 00:17:04,147 even from a hardware [INAUDIBLE] bug standpoint. 408 00:17:04,147 --> 00:17:05,480 So they're actually pretty cool. 409 00:17:05,480 --> 00:17:09,450 They're like really paranoid about security, 410 00:17:09,450 --> 00:17:12,612 including hardware problems. 411 00:17:12,612 --> 00:17:15,140 All right, so any questions about all these alternatives, 412 00:17:15,140 --> 00:17:17,400 how that works, or why these guys are not 413 00:17:17,400 --> 00:17:19,454 excited about that? 414 00:17:19,454 --> 00:17:21,496 Makes sense? 415 00:17:21,496 --> 00:17:22,700 All right. 416 00:17:22,700 --> 00:17:25,990 So I guess let's try to look at now, 417 00:17:25,990 --> 00:17:30,566 how Native Client does actually decide to sandbox processes. 418 00:17:30,566 --> 00:17:34,760 Let me pull up these boards. 419 00:17:34,760 --> 00:17:37,340 So Native Client takes this different approach 420 00:17:37,340 --> 00:17:41,070 that's in general called software fault isolation. 421 00:17:49,040 --> 00:17:52,630 And the plan is actually not rely on the operating 422 00:17:52,630 --> 00:17:55,500 system or hardware to check things at runtime, 423 00:17:55,500 --> 00:18:00,000 but instead to somehow look at the instructions ahead of time, 424 00:18:00,000 --> 00:18:03,950 and decide that there are always going to be safe to execute. 425 00:18:03,950 --> 00:18:06,350 So actually look at the binary, and you 426 00:18:06,350 --> 00:18:08,610 check all the possible instructions 427 00:18:08,610 --> 00:18:11,480 to see whether they're going to be safe instructions 428 00:18:11,480 --> 00:18:12,660 or unsafe instructions. 429 00:18:12,660 --> 00:18:15,960 And once you've decided that it's all going to be safe, 430 00:18:15,960 --> 00:18:18,050 you can just jump in and start executing. 431 00:18:18,050 --> 00:18:20,970 Because you know it's all composed of safe things, 432 00:18:20,970 --> 00:18:22,850 so it cannot go wrong. 433 00:18:22,850 --> 00:18:25,800 So we'll talk about exactly what this means. 434 00:18:25,800 --> 00:18:28,130 But roughly what they're going to do is, 435 00:18:28,130 --> 00:18:31,000 they're going to look at pretty much every instruction 436 00:18:31,000 --> 00:18:34,050 in the binary code that is served up to the browser. 437 00:18:34,050 --> 00:18:37,290 And they're going to decide that particular instructions are 438 00:18:37,290 --> 00:18:41,872 going to be safe or unsafe. 439 00:18:41,872 --> 00:18:43,455 What do they do for safe instructions? 440 00:18:43,455 --> 00:18:46,010 Well, they're just going to allow them. 441 00:18:46,010 --> 00:18:48,315 What's an example of a safe instruction? 442 00:18:48,315 --> 00:18:51,260 What are they thinking of that don't need any extra checks 443 00:18:51,260 --> 00:18:53,432 or protections, et cetera? 444 00:18:53,432 --> 00:18:54,424 AUDIENCE: [INAUDIBLE]. 445 00:18:54,424 --> 00:18:57,900 PROFESSOR: Yeah, so like any kind of ALU operation. 446 00:18:57,900 --> 00:18:59,730 Basically you have math, presumably 447 00:18:59,730 --> 00:19:03,840 moves between registers and so on. 448 00:19:03,840 --> 00:19:06,490 So this doesn't actually affect the security of the system, 449 00:19:06,490 --> 00:19:07,410 as far as they're concerned. 450 00:19:07,410 --> 00:19:08,600 Because all they really care about 451 00:19:08,600 --> 00:19:11,045 is things like memory safety, where what code you execute, 452 00:19:11,045 --> 00:19:12,321 and so on. 453 00:19:12,321 --> 00:19:14,445 So as long as you are just computing on some stuff, 454 00:19:14,445 --> 00:19:16,120 and registers, they don't really care. 455 00:19:16,120 --> 00:19:19,660 It's not going to affect the rest of the browser. 456 00:19:19,660 --> 00:19:21,350 So what about unsafe operations? 457 00:19:21,350 --> 00:19:22,960 I guess these are things that they 458 00:19:22,960 --> 00:19:24,330 might care much more about. 459 00:19:24,330 --> 00:19:29,740 So this anything that maybe does a memory access, or maybe 460 00:19:29,740 --> 00:19:34,400 some privileged instruction, maybe invoking a system 461 00:19:34,400 --> 00:19:37,670 call on this machine. 462 00:19:37,670 --> 00:19:41,450 Maybe trying to jump out of the sandbox, who knows what? 463 00:19:41,450 --> 00:19:43,450 So for these kinds of instructions, 464 00:19:43,450 --> 00:19:46,180 they are going to do one of two things. 465 00:19:46,180 --> 00:19:50,090 If the instruction actually is necessary for the application 466 00:19:50,090 --> 00:19:52,922 to do it's job, like accessing memory seems important, 467 00:19:52,922 --> 00:19:55,430 then they're going to somehow make sure 468 00:19:55,430 --> 00:19:59,650 that they can execute this unsafe instruction safely. 469 00:19:59,650 --> 00:20:02,300 Or if you're jumping around for example in the program's 470 00:20:02,300 --> 00:20:04,425 address space, [INAUDIBLE] what they're going to do 471 00:20:04,425 --> 00:20:07,048 is somehow instrument the instruction. 472 00:20:07,048 --> 00:20:09,050 And what instrumenting the instruction means 473 00:20:09,050 --> 00:20:12,006 is that you used to have one unsafe instruction that 474 00:20:12,006 --> 00:20:14,630 sometimes does good things, that the application might actually 475 00:20:14,630 --> 00:20:15,960 want to do legitimately. 476 00:20:15,960 --> 00:20:18,620 And sometimes the instruction can do bad things. 477 00:20:18,620 --> 00:20:20,722 So what instrumenting it means is 478 00:20:20,722 --> 00:20:22,680 that you add some extra instructions before it, 479 00:20:22,680 --> 00:20:26,240 that it'll check or enforce, but only good things 480 00:20:26,240 --> 00:20:28,383 are going to happen with that instruction. 481 00:20:28,383 --> 00:20:30,850 So for example, if you are accessing a memory location, 482 00:20:30,850 --> 00:20:32,267 which you could do-- it turns out, 483 00:20:32,267 --> 00:20:34,016 they don't do it for performance reasons-- 484 00:20:34,016 --> 00:20:36,030 but one way to instrument a memory access would 485 00:20:36,030 --> 00:20:38,040 be to put some checks, like an if 486 00:20:38,040 --> 00:20:40,050 statement before the instructions, saying, well, 487 00:20:40,050 --> 00:20:42,660 is this address you're accessing in range of what's 488 00:20:42,660 --> 00:20:43,660 allowed for this module? 489 00:20:43,660 --> 00:20:46,554 And if so, do that-- otherwise, exit. 490 00:20:46,554 --> 00:20:48,220 So that would instrument an instruction. 491 00:20:48,220 --> 00:20:50,370 And that would turn an unsafe instruction 492 00:20:50,370 --> 00:20:52,110 into one that's always safe to execute, 493 00:20:52,110 --> 00:20:55,020 because there's always that check in front of it. 494 00:20:55,020 --> 00:20:56,020 So does that make sense? 495 00:20:56,020 --> 00:20:58,940 This is their sort of big idea for running 496 00:20:58,940 --> 00:21:02,830 this enforcing safety without support from that operating 497 00:21:02,830 --> 00:21:05,050 system at some level. 498 00:21:05,050 --> 00:21:06,880 And I guess for other unsafe instructions, 499 00:21:06,880 --> 00:21:08,330 they don't instrument all of them. 500 00:21:08,330 --> 00:21:09,990 Some of them they actually prohibit, 501 00:21:09,990 --> 00:21:12,425 if they believe that this is an instruction that's 502 00:21:12,425 --> 00:21:14,830 not really necessary during normal operation, 503 00:21:14,830 --> 00:21:16,875 and if an application tried to run it, 504 00:21:16,875 --> 00:21:18,780 we should just kill the application 505 00:21:18,780 --> 00:21:22,450 or not allow it to run in the first place. 506 00:21:22,450 --> 00:21:23,150 Makes sense? 507 00:21:23,150 --> 00:21:26,840 Those are their sort of big plan for software fault isolation. 508 00:21:26,840 --> 00:21:30,480 And once you've checked the application's binary, 509 00:21:30,480 --> 00:21:32,214 and it all passes, and everything 510 00:21:32,214 --> 00:21:33,630 seems to be properly instrumented, 511 00:21:33,630 --> 00:21:36,690 then you can just run the program and off it goes. 512 00:21:36,690 --> 00:21:39,115 And by definition almost, it will not 513 00:21:39,115 --> 00:21:41,630 do bad things, if we do all these checks 514 00:21:41,630 --> 00:21:44,310 and instrumentation [INAUDIBLE]. 515 00:21:44,310 --> 00:21:47,010 And I guess there's one more part to the software fault 516 00:21:47,010 --> 00:21:50,090 isolation story, which is that once you've 517 00:21:50,090 --> 00:21:51,650 make sure that everything is safe, 518 00:21:51,650 --> 00:21:53,470 then it can't actually do anything terribly 519 00:21:53,470 --> 00:21:55,570 interesting, other than compute stuff in it's 520 00:21:55,570 --> 00:21:56,502 own little memory. 521 00:21:56,502 --> 00:21:58,876 So it can't access the network, it can't access the disk, 522 00:21:58,876 --> 00:22:01,640 it can't access your browser, display, keyboard, almost 523 00:22:01,640 --> 00:22:02,580 anything. 524 00:22:02,580 --> 00:22:04,770 So pretty much every software fault isolation story, 525 00:22:04,770 --> 00:22:07,630 there's actually also some trusted service runtime. 526 00:22:12,580 --> 00:22:15,370 And this trusted runtime is going 527 00:22:15,370 --> 00:22:18,869 to not be subject to these checks on it's instructions. 528 00:22:18,869 --> 00:22:20,410 So the trusted runtime could actually 529 00:22:20,410 --> 00:22:22,034 do all these potentially unsafe things. 530 00:22:22,034 --> 00:22:23,980 But this trusted runtime is written by Google. 531 00:22:23,980 --> 00:22:25,940 So hopefully they get a [INAUDIBLE]. 532 00:22:25,940 --> 00:22:27,990 And it's going to implement all the functions 533 00:22:27,990 --> 00:22:31,530 that Google's Native Client team believes 534 00:22:31,530 --> 00:22:33,690 are OK throughout for these modules. 535 00:22:33,690 --> 00:22:36,420 So these are going to be things like maybe allocated 536 00:22:36,420 --> 00:22:42,020 memory, maybe creating a thread, maybe 537 00:22:42,020 --> 00:22:43,910 communicating with the browser as we 538 00:22:43,910 --> 00:22:49,900 saw-- so some sort of a message passing system, et cetera. 539 00:22:49,900 --> 00:22:54,310 And the way it's going to be exposed to this isolated module 540 00:22:54,310 --> 00:23:00,730 is through certain presumably special jumps or operations 541 00:23:00,730 --> 00:23:04,980 that the module is going to perform to transition 542 00:23:04,980 --> 00:23:07,180 control into this trusted runtime, 543 00:23:07,180 --> 00:23:11,195 but hopefully in a very predictable way to-- question? 544 00:23:11,195 --> 00:23:12,736 AUDIENCE: I'm just curious about, you 545 00:23:12,736 --> 00:23:16,432 have to design this application, knowing that it's going 546 00:23:16,432 --> 00:23:18,566 to be sent to the NaCl module? 547 00:23:18,566 --> 00:23:21,458 Or does it like change the code to [INAUDIBLE] 548 00:23:21,458 --> 00:23:23,386 making the [INAUDIBLE] sort of stuff bad? 549 00:23:23,386 --> 00:23:27,540 PROFESSOR: So I think if you are building an application, 550 00:23:27,540 --> 00:23:29,550 you do have to be sort of aware that it's 551 00:23:29,550 --> 00:23:32,580 going to be running inside of Native Client. 552 00:23:32,580 --> 00:23:36,610 So some function calls like malloc or pthread_create, 553 00:23:36,610 --> 00:23:39,005 I think they just transparently are placed with calls 554 00:23:39,005 --> 00:23:40,670 to their trusted runtime. 555 00:23:40,670 --> 00:23:42,760 But if you do anything like opening a file 556 00:23:42,760 --> 00:23:45,830 by path name, or anything else that sort of you 557 00:23:45,830 --> 00:23:47,790 would expect to do on a Unix machine, 558 00:23:47,790 --> 00:23:50,640 that you would probably have to replace with something else. 559 00:23:50,640 --> 00:23:52,800 And you'd probably want to structure your thing 560 00:23:52,800 --> 00:23:55,341 to interact at least a little bit with your JavaScript or web 561 00:23:55,341 --> 00:23:56,150 page in some way. 562 00:23:56,150 --> 00:23:59,160 And that you would have to do by explicitly doing some message 563 00:23:59,160 --> 00:24:02,420 passing or RPCs into the JavaScript part. 564 00:24:02,420 --> 00:24:04,890 So that you would have to probably change. 565 00:24:04,890 --> 00:24:08,620 So there are some-- it's not like you can run an arbitrary 566 00:24:08,620 --> 00:24:11,660 Unix program in there, and you'll just sort of get a shell 567 00:24:11,660 --> 00:24:13,599 and you can run commands all of a sudden. 568 00:24:13,599 --> 00:24:15,140 Probably if you tried hard, maybe you 569 00:24:15,140 --> 00:24:17,170 could create such an environment. 570 00:24:17,170 --> 00:24:19,110 But by default, you probably have 571 00:24:19,110 --> 00:24:22,886 to make it operate inside of this web page, and then 572 00:24:22,886 --> 00:24:23,386 [INAUDIBLE]. 573 00:24:23,386 --> 00:24:25,866 Does that make sense? 574 00:24:25,866 --> 00:24:28,346 All right. 575 00:24:28,346 --> 00:24:29,350 OK. 576 00:24:29,350 --> 00:24:32,885 So that's the overall plan software fault isolation. 577 00:24:32,885 --> 00:24:34,260 So I guess let's look at actually 578 00:24:34,260 --> 00:24:38,440 what safety means in their case for Native Client. 579 00:24:38,440 --> 00:24:40,710 So we talked loosely about this notion 580 00:24:40,710 --> 00:24:43,290 of safe instructions, unsafe instructions-- what do 581 00:24:43,290 --> 00:24:45,070 they actually care about here? 582 00:24:45,070 --> 00:24:47,700 So as far as I can tell for Native Client, 583 00:24:47,700 --> 00:24:51,440 safety basically means two things. 584 00:24:51,440 --> 00:24:57,040 One is that there's no disallowed instructions 585 00:24:57,040 --> 00:24:58,050 that it can execute. 586 00:25:00,750 --> 00:25:02,610 And these disallowed instructions 587 00:25:02,610 --> 00:25:07,430 are things like maybe system calls or triggering 588 00:25:07,430 --> 00:25:10,280 an interop, which is another mechanism on x86 to jump 589 00:25:10,280 --> 00:25:12,310 into the kernel and invoke a system call, 590 00:25:12,310 --> 00:25:15,520 and probably other privileged instructions that 591 00:25:15,520 --> 00:25:17,520 would allow you to escape out of the sandbox. 592 00:25:17,520 --> 00:25:18,970 We'll look a little bit more later 593 00:25:18,970 --> 00:25:20,428 at what instructions could actually 594 00:25:20,428 --> 00:25:23,420 let you jump out of a sandbox. 595 00:25:23,420 --> 00:25:26,320 And in addition to this no disallowed instructions rule, 596 00:25:26,320 --> 00:25:33,900 they also want to make sure that all code and data accesses are 597 00:25:33,900 --> 00:25:36,670 in bounds for the module. 598 00:25:39,602 --> 00:25:41,310 So what this means, is that they actually 599 00:25:41,310 --> 00:25:44,230 dedicate a particular part of the program's address 600 00:25:44,230 --> 00:25:47,150 space-- specifically it goes from zero up 601 00:25:47,150 --> 00:25:51,250 to 256 megs in the process. 602 00:25:51,250 --> 00:25:54,570 And everything that this untrusted module does 603 00:25:54,570 --> 00:25:57,950 has to refer to locations within this chunk of memory 604 00:25:57,950 --> 00:26:00,812 in the program. 605 00:26:00,812 --> 00:26:02,270 All right, so just to double check. 606 00:26:02,270 --> 00:26:05,910 So why do they want to disallow these instructions? 607 00:26:05,910 --> 00:26:09,785 So what if they fail to disallow the instructions? 608 00:26:09,785 --> 00:26:10,285 Yeah? 609 00:26:10,285 --> 00:26:12,575 AUDIENCE: The module can manipulate the system. 610 00:26:12,575 --> 00:26:14,700 PROFESSOR: Right, so that's fairly straightforward, 611 00:26:14,700 --> 00:26:15,283 exactly, yeah. 612 00:26:15,283 --> 00:26:17,040 So it can just directly reboot the machine 613 00:26:17,040 --> 00:26:19,625 or open your home directory and enumerate all the files, 614 00:26:19,625 --> 00:26:20,740 and do all these things. 615 00:26:20,740 --> 00:26:22,720 So that seems like a good thing to do. 616 00:26:22,720 --> 00:26:25,190 Why do they care about this plan, 617 00:26:25,190 --> 00:26:28,140 like isolating the coded data to only access 618 00:26:28,140 --> 00:26:30,174 these low addresses? 619 00:26:30,174 --> 00:26:31,840 What goes wrong if they fail to do that? 620 00:26:36,280 --> 00:26:36,960 Yeah? 621 00:26:36,960 --> 00:26:39,376 AUDIENCE: Then they can sort of accessing and interrupting 622 00:26:39,376 --> 00:26:42,004 [INAUDIBLE] module on the computer. 623 00:26:42,004 --> 00:26:42,670 PROFESSOR: Yeah. 624 00:26:42,670 --> 00:26:45,275 AUDIENCE: We don't care if they ruin their own program 625 00:26:45,275 --> 00:26:46,010 and it crashes. 626 00:26:46,010 --> 00:26:48,301 That's fine, as long as it's not going to crash the key 627 00:26:48,301 --> 00:26:49,900 to [INAUDIBLE]. 628 00:26:49,900 --> 00:26:52,100 PROFESSOR: Yeah, so in some sense, that's true. 629 00:26:52,100 --> 00:26:54,080 But in their case, they actually run the thing 630 00:26:54,080 --> 00:26:55,250 in a separate process. 631 00:26:55,250 --> 00:26:59,080 So in theory, this would only crash that extra process. 632 00:26:59,080 --> 00:27:01,330 I think that I guess what they're really worried about 633 00:27:01,330 --> 00:27:04,290 is that this is a necessary condition 634 00:27:04,290 --> 00:27:07,260 to ensure this no disallowed instructions in some way, 635 00:27:07,260 --> 00:27:09,540 because there's other stuff, like this trusted 636 00:27:09,540 --> 00:27:11,470 runtime in your process. 637 00:27:11,470 --> 00:27:13,440 So if what you really care about is not 638 00:27:13,440 --> 00:27:15,030 corrupting the rest of your computer, 639 00:27:15,030 --> 00:27:18,150 then if the untrusted module can arbitrarily 640 00:27:18,150 --> 00:27:20,100 jump into the trusted service runtime 641 00:27:20,100 --> 00:27:22,460 and do anything that the trusted service runtime can do, 642 00:27:22,460 --> 00:27:24,582 then they could sort of violate this property. 643 00:27:24,582 --> 00:27:27,040 So in some ways, this is really like a supporting mechanism 644 00:27:27,040 --> 00:27:30,000 for enforcing that. 645 00:27:30,000 --> 00:27:33,670 In principle, this could also be used for lighter weight 646 00:27:33,670 --> 00:27:37,200 isolation if you could run this Native Client module 647 00:27:37,200 --> 00:27:39,320 inside of the browser process itself, and not 648 00:27:39,320 --> 00:27:40,812 start an extra process. 649 00:27:40,812 --> 00:27:42,520 But it turns out for performance reasons, 650 00:27:42,520 --> 00:27:44,150 they really have to tie down the module 651 00:27:44,150 --> 00:27:46,360 to this particular range of memory, 652 00:27:46,360 --> 00:27:48,310 or it has to start at zero anyway. 653 00:27:48,310 --> 00:27:49,810 So this means that you can only have 654 00:27:49,810 --> 00:27:52,812 one really Native Client untrusted module per process. 655 00:27:52,812 --> 00:27:55,020 So you probably are going to start a separate process 656 00:27:55,020 --> 00:27:56,956 anyway. 657 00:27:56,956 --> 00:27:58,408 Makes sense? 658 00:27:58,408 --> 00:27:59,376 Any questions? 659 00:27:59,376 --> 00:28:00,780 Yeah? 660 00:28:00,780 --> 00:28:02,280 AUDIENCE: Is there actually a reason 661 00:28:02,280 --> 00:28:04,230 why it has to start at zero? 662 00:28:04,230 --> 00:28:07,620 PROFESSOR: Yeah, so it turns out it's more efficient in terms 663 00:28:07,620 --> 00:28:11,480 of performance to enforce jump targets, 664 00:28:11,480 --> 00:28:14,922 if you know that the legitimate address is a contiguous set 665 00:28:14,922 --> 00:28:17,505 of addresses starting at zero, because you can then do it with 666 00:28:17,505 --> 00:28:21,080 a single AND mask, where all the high bits are one, 667 00:28:21,080 --> 00:28:27,140 and only a couple of low bits are zero-- well, 668 00:28:27,140 --> 00:28:29,542 if you're willing-- well-- 669 00:28:29,542 --> 00:28:32,000 AUDIENCE: I thought the AND mask was to ensure [INAUDIBLE]. 670 00:28:32,000 --> 00:28:34,166 PROFESSOR: Right, so the AND mask ensures alignment, 671 00:28:34,166 --> 00:28:35,240 you're right. 672 00:28:35,240 --> 00:28:38,443 So why do they start at zero? 673 00:28:38,443 --> 00:28:43,210 I think it probably helps them to-- well, 674 00:28:43,210 --> 00:28:45,715 I guess they rely on the segmentation hardware. 675 00:28:45,715 --> 00:28:47,090 So in principle, maybe they could 676 00:28:47,090 --> 00:28:49,369 use the segmentation hardware to shift the region up, 677 00:28:49,369 --> 00:28:50,410 in terms of linear space. 678 00:28:50,410 --> 00:28:52,076 Or maybe it's just with the application, 679 00:28:52,076 --> 00:28:53,480 sort of sees this range. 680 00:28:53,480 --> 00:28:54,810 And you can actually place it at different offsets 681 00:28:54,810 --> 00:28:56,260 in your virtual address space. 682 00:28:56,260 --> 00:28:59,260 It could be-- yeah, so maybe you could actually 683 00:28:59,260 --> 00:29:01,010 play tricks with the segmentation hardware 684 00:29:01,010 --> 00:29:03,511 to run multiple models in a single address space. 685 00:29:03,511 --> 00:29:06,052 AUDIENCE: But is it because they want to catch a null pointer 686 00:29:06,052 --> 00:29:06,552 reception? 687 00:29:06,552 --> 00:29:09,176 PROFESSOR: Yeah, so they want to catch all points of reception. 688 00:29:09,176 --> 00:29:10,570 But you could sort of do that. 689 00:29:10,570 --> 00:29:11,610 Because the null pointer-- I guess 690 00:29:11,610 --> 00:29:13,359 we'll talk about segmentation in a second, 691 00:29:13,359 --> 00:29:17,260 but the null pointer actually is relative to the segment 692 00:29:17,260 --> 00:29:18,662 in which you are accessing. 693 00:29:18,662 --> 00:29:20,120 So if you shift the segment around, 694 00:29:20,120 --> 00:29:22,574 then you can map an unused zero page 695 00:29:22,574 --> 00:29:25,030 at the beginning of everyone's segment. 696 00:29:25,030 --> 00:29:30,090 So yeah, it might be that you could do multiple modules. 697 00:29:30,090 --> 00:29:33,930 I think for-- well, because one reason they probably 698 00:29:33,930 --> 00:29:35,810 want to do this is that when they 699 00:29:35,810 --> 00:29:38,110 port their stuff to 64 bits, they have 700 00:29:38,110 --> 00:29:39,300 a slightly different design. 701 00:29:39,300 --> 00:29:40,966 This paper doesn't really talk about it. 702 00:29:40,966 --> 00:29:44,360 And I think about 64-bit design, the hardware itself 703 00:29:44,360 --> 00:29:46,230 got rid of some of the segmentation hardware 704 00:29:46,230 --> 00:29:49,110 they were relying on for efficiency reasons, 705 00:29:49,110 --> 00:29:51,890 and they have to do a much more software oriented approach, 706 00:29:51,890 --> 00:29:54,880 in which case having a little bit doesn't help them. 707 00:29:54,880 --> 00:29:57,580 But in this 32-bit version, I think, yeah, maybe that's true. 708 00:29:57,580 --> 00:30:02,189 That's not a deep reason why it has to start at zero. 709 00:30:02,189 --> 00:30:02,855 Other questions? 710 00:30:05,500 --> 00:30:06,550 All right. 711 00:30:06,550 --> 00:30:10,549 So I guess we sort of roughly understand what the plan is, 712 00:30:10,549 --> 00:30:12,465 or what we want to enforce in terms of safety. 713 00:30:12,465 --> 00:30:14,690 So how do we do this? 714 00:30:14,690 --> 00:30:16,920 So let's look at some of at least naive approach, 715 00:30:16,920 --> 00:30:19,540 and see how could we screw it up, 716 00:30:19,540 --> 00:30:22,580 I guess, and then we'll try to fix it afterwards. 717 00:30:22,580 --> 00:30:25,734 So I guess the naive plan that sort 718 00:30:25,734 --> 00:30:29,900 of looks like what they do, is to just look 719 00:30:29,900 --> 00:30:33,450 for disallowed instructions by just scanning the executable 720 00:30:33,450 --> 00:30:34,815 from the start going forward. 721 00:30:37,612 --> 00:30:39,790 So how do you detect that instructions? 722 00:30:39,790 --> 00:30:43,380 Well, you could just take the program code, 723 00:30:43,380 --> 00:30:46,320 and you sort of lay it out in a giant string that 724 00:30:46,320 --> 00:30:50,780 goes from zero up to maybe all the way to 56 megabytes, 725 00:30:50,780 --> 00:30:53,850 depending on how big your code is, and you start looking. 726 00:30:53,850 --> 00:30:56,259 OK, well, maybe there's a nop instruction here. 727 00:30:56,259 --> 00:30:58,425 Maybe there's some sort of an add instruction there. 728 00:30:58,425 --> 00:31:02,580 Maybe there's a not-- I don't know, some sort of a jump, 729 00:31:02,580 --> 00:31:03,350 et cetera. 730 00:31:03,350 --> 00:31:05,840 And you just keep looking. 731 00:31:05,840 --> 00:31:07,450 And if you find a bad instruction, 732 00:31:07,450 --> 00:31:09,580 you say, ah, that's a bad module. 733 00:31:09,580 --> 00:31:10,610 And then you discard it. 734 00:31:10,610 --> 00:31:13,193 And if you don't see any system call [INAUDIBLE] instructions, 735 00:31:13,193 --> 00:31:15,550 then you're going to allow this module to run, 736 00:31:15,550 --> 00:31:20,200 module or whatever it is we'll do for the in bounds checks. 737 00:31:20,200 --> 00:31:23,301 So is this going to work? 738 00:31:23,301 --> 00:31:24,800 So why not? 739 00:31:24,800 --> 00:31:26,320 What are they worried about? 740 00:31:26,320 --> 00:31:27,470 Why is so complicated? 741 00:31:27,470 --> 00:31:29,430 AUDIENCE: [INAUDIBLE] the instructions? 742 00:31:29,430 --> 00:31:31,160 PROFESSOR: Yeah, so the weird thing 743 00:31:31,160 --> 00:31:34,480 is that x86, which is the sort of platform they are targeting 744 00:31:34,480 --> 00:31:36,305 has a variable length instructions. 745 00:31:39,448 --> 00:31:42,700 So this means that the particular size 746 00:31:42,700 --> 00:31:45,677 of an instruction depends on the first few bytes 747 00:31:45,677 --> 00:31:46,510 of that instruction. 748 00:31:46,510 --> 00:31:48,090 So you have to actually look at the first byte 749 00:31:48,090 --> 00:31:49,305 and say, OK, well, the instruction 750 00:31:49,305 --> 00:31:50,545 is going to be this much more. 751 00:31:50,545 --> 00:31:52,810 And then maybe you sort of have to look at a couple more bytes, 752 00:31:52,810 --> 00:31:54,660 and then decide, OK, well, that's exactly how long it's 753 00:31:54,660 --> 00:31:55,440 going to be. 754 00:31:55,440 --> 00:31:56,981 But you don't know how ahead of time. 755 00:31:56,981 --> 00:32:01,000 So some architectures like Spark, ARM, [INAUDIBLE], 756 00:32:01,000 --> 00:32:03,700 have more fixed length instructions. 757 00:32:03,700 --> 00:32:05,731 Well, ARM, for example-- ARM is like weird, 758 00:32:05,731 --> 00:32:07,230 but it has two instructions lengths. 759 00:32:07,230 --> 00:32:10,200 Either everything is two bytes or everything is four bytes. 760 00:32:10,200 --> 00:32:13,485 But x86, the instructions could be like one byte or 10 byte 761 00:32:13,485 --> 00:32:16,097 or five bytes, anything in between, as well. 762 00:32:16,097 --> 00:32:17,180 I forget actually how big. 763 00:32:17,180 --> 00:32:18,763 You can get a pretty long instruction. 764 00:32:18,763 --> 00:32:21,150 I think you can get like a 15 byte instruction with x86 765 00:32:21,150 --> 00:32:23,044 if you try hard. 766 00:32:23,044 --> 00:32:26,260 It's complicated instructions, though. 767 00:32:26,260 --> 00:32:28,900 But as a result, the problem that could show up 768 00:32:28,900 --> 00:32:31,270 is that maybe you're scanning linearly 769 00:32:31,270 --> 00:32:33,240 and everything seems to be fine. 770 00:32:33,240 --> 00:32:35,560 But maybe at runtime, you'll actually 771 00:32:35,560 --> 00:32:38,420 jump into the middle of some instruction. 772 00:32:38,420 --> 00:32:40,220 Maybe it was a multi-byte instruction, 773 00:32:40,220 --> 00:32:42,340 if you interpret it starting from the second byte, 774 00:32:42,340 --> 00:32:44,890 it looks like a completely different thing. 775 00:32:44,890 --> 00:32:47,190 So that's just one example of sort of playing around 776 00:32:47,190 --> 00:32:48,290 with an assembler. 777 00:32:48,290 --> 00:32:56,210 And if you have an instruction like this, 25 CD 80, 00, 00. 778 00:32:56,210 --> 00:32:58,872 And if you interpret it as this five byte instruction, 779 00:32:58,872 --> 00:33:00,330 meaning that you look at this byte. 780 00:33:00,330 --> 00:33:02,210 And oh yeah, this is going to be a five byte instruction. 781 00:33:02,210 --> 00:33:04,130 So you have to look five bytes forward. 782 00:33:04,130 --> 00:33:07,680 And then this turns out to be a fairly benign instruction 783 00:33:07,680 --> 00:33:10,980 that's an and of the EAX register, 784 00:33:10,980 --> 00:33:16,380 with some particular constant that happens to be I think 00, 785 00:33:16,380 --> 00:33:20,580 00, 80, CD. anyway. 786 00:33:20,580 --> 00:33:22,220 So this is one of the safe instructions 787 00:33:22,220 --> 00:33:25,330 that Native Client should just allow under the first rule 788 00:33:25,330 --> 00:33:28,020 in checking these binary instructions. 789 00:33:28,020 --> 00:33:29,780 But if it turns out at runtime the CPU 790 00:33:29,780 --> 00:33:33,150 decides this is where it has to start executing the code, 791 00:33:33,150 --> 00:33:35,920 then this instruction is actually 792 00:33:35,920 --> 00:33:39,040 a four byte instruction, and its actually an int instruction 793 00:33:39,040 --> 00:33:41,950 that makes the OX80 interrupt, which 794 00:33:41,950 --> 00:33:45,570 is one way to make system calls in Linux. 795 00:33:45,570 --> 00:33:49,720 So if you miss this fact, then eventually you're 796 00:33:49,720 --> 00:33:53,600 going to allow untrusted module to jump into the kernel 797 00:33:53,600 --> 00:33:56,988 and make system calls, which is what you wanted to prevent. 798 00:33:56,988 --> 00:33:59,790 Make sense? 799 00:33:59,790 --> 00:34:01,255 So how can we prevent it? 800 00:34:01,255 --> 00:34:02,796 Like one possibility is like maybe we 801 00:34:02,796 --> 00:34:05,980 should try to look at every byte offset. 802 00:34:05,980 --> 00:34:09,125 Because at least x86 can only start interpreting instruction 803 00:34:09,125 --> 00:34:11,643 on a byte boundary instead of a bit boundary. 804 00:34:11,643 --> 00:34:14,130 So you like look at every single possible byte off, 805 00:34:14,130 --> 00:34:17,420 and you see what instruction starts there. 806 00:34:17,420 --> 00:34:19,445 Is this a reasonable plan to report? 807 00:34:19,445 --> 00:34:19,944 Yeah? 808 00:34:19,944 --> 00:34:21,500 AUDIENCE: I mean, what if someone actually 809 00:34:21,500 --> 00:34:24,107 is doing an and, and they're never going to jump into that. 810 00:34:24,107 --> 00:34:25,480 And now you're just allowing their program. 811 00:34:25,480 --> 00:34:27,000 PROFESSOR: Right, so basically it's 812 00:34:27,000 --> 00:34:30,310 prone to eventually false positives. 813 00:34:30,310 --> 00:34:32,770 Now if you really wanted to, you could probably 814 00:34:32,770 --> 00:34:36,889 contort yourself and change the code a little-- 815 00:34:36,889 --> 00:34:38,330 and somehow avoid this. 816 00:34:38,330 --> 00:34:41,080 If you knew exactly what the checker was looking for, 817 00:34:41,080 --> 00:34:43,620 you could potentially change these instructions. 818 00:34:43,620 --> 00:34:45,969 Maybe like end it with one thing first, and then 819 00:34:45,969 --> 00:34:48,010 end it with another mask later. 820 00:34:48,010 --> 00:34:51,520 But just avoid these suspicious byte patterns. 821 00:34:51,520 --> 00:34:54,430 But that just seems pretty awkward to do. 822 00:34:54,430 --> 00:34:56,949 Now it is actually possible that the architecture does 823 00:34:56,949 --> 00:34:59,030 involve changing the compiler. 824 00:34:59,030 --> 00:35:01,400 So in principle, they do have some component 825 00:35:01,400 --> 00:35:05,150 that actually has to compile the code correctly. 826 00:35:05,150 --> 00:35:07,020 You can't just take of the shelf GCC 827 00:35:07,020 --> 00:35:08,880 and compile a code for Native Client. 828 00:35:08,880 --> 00:35:10,100 So in principle it's doable. 829 00:35:10,100 --> 00:35:12,500 But I think they're just thinking it's too much hassle, 830 00:35:12,500 --> 00:35:15,065 and it's not going to be reliable or high performance, 831 00:35:15,065 --> 00:35:16,506 et cetera. 832 00:35:16,506 --> 00:35:18,420 Make sense? 833 00:35:18,420 --> 00:35:20,770 And plus there's a couple of x86 instructions 834 00:35:20,770 --> 00:35:24,780 that are prohibited or should be unsafe and prohibited. 835 00:35:24,780 --> 00:35:27,110 But they're like one byte long, so that 836 00:35:27,110 --> 00:35:32,820 is going to be pretty damaging to look for or filter out. 837 00:35:32,820 --> 00:35:33,320 OK. 838 00:35:33,320 --> 00:35:36,110 So if they can't just assemble and sort of straight up 839 00:35:36,110 --> 00:35:39,540 and hope for the best, then they need some other plan 840 00:35:39,540 --> 00:35:43,830 for doing this disassembly in a reliable fashion. 841 00:35:43,830 --> 00:35:46,070 So what is that client or Native Client 842 00:35:46,070 --> 00:35:50,431 to ensure they don't get tripped up by this variable length 843 00:35:50,431 --> 00:35:50,930 encoding? 844 00:35:53,550 --> 00:35:58,839 So I guess one way to think about it is, well, 845 00:35:58,839 --> 00:36:01,130 so how are we going to solve this reliable disassembly? 846 00:36:06,310 --> 00:36:10,260 So in some sense, if we really do scan forward 847 00:36:10,260 --> 00:36:13,150 from the left to the right, and we look for all the possible up 848 00:36:13,150 --> 00:36:16,910 codes, if that's the way the code executes, 849 00:36:16,910 --> 00:36:18,080 then we're in good shape. 850 00:36:18,080 --> 00:36:20,000 So even if there are some weird instruction 851 00:36:20,000 --> 00:36:22,580 and has some offset, then the CPU 852 00:36:22,580 --> 00:36:24,290 isn't actually going to jump there. 853 00:36:24,290 --> 00:36:26,072 It actually executes the same way 854 00:36:26,072 --> 00:36:27,530 that we're scanning the instruction 855 00:36:27,530 --> 00:36:29,740 screen from left to right. 856 00:36:29,740 --> 00:36:34,020 So the problem with getting the disassembly to be reliable 857 00:36:34,020 --> 00:36:38,320 really comes from the fact that there's jumps. 858 00:36:38,320 --> 00:36:40,920 Because if we execute linearly from left to right, then 859 00:36:40,920 --> 00:36:42,390 the CPU will follow the same rules 860 00:36:42,390 --> 00:36:45,000 that our checker is following, and see the same instruction 861 00:36:45,000 --> 00:36:45,840 screen. 862 00:36:45,840 --> 00:36:48,230 So the problem really comes down to what 863 00:36:48,230 --> 00:36:51,490 happens if there's a jump somewhere in the application. 864 00:36:51,490 --> 00:36:53,500 Could a jump to some position in the code 865 00:36:53,500 --> 00:36:57,654 that we didn't observe in our left to right scan? 866 00:36:57,654 --> 00:36:59,570 So this is what they are sort of going another 867 00:36:59,570 --> 00:37:01,380 in the reliable disassembly. 868 00:37:01,380 --> 00:37:06,780 And the basic plan is to just check where all the jumps go. 869 00:37:06,780 --> 00:37:10,020 It's actually fairly straightforward at some level. 870 00:37:10,020 --> 00:37:12,880 They have a bunch of rules we'll look at in a second, 871 00:37:12,880 --> 00:37:17,680 but roughly the plan is if you see a jump instruction, 872 00:37:17,680 --> 00:37:19,910 then it actually has to be-- well, 873 00:37:19,910 --> 00:37:24,395 you have to check that the target was seen before. 874 00:37:28,360 --> 00:37:30,850 So you basically do the left to right scan 875 00:37:30,850 --> 00:37:33,970 that we sort of described in our naive approach here. 876 00:37:33,970 --> 00:37:36,910 But then if you see any kind of a jump instruction, 877 00:37:36,910 --> 00:37:39,545 then you see what is the address to which the jump instruction 878 00:37:39,545 --> 00:37:42,000 is pointing to, and you make sure that it's 879 00:37:42,000 --> 00:37:44,750 an address that you saw in your left to right disassembly. 880 00:37:44,750 --> 00:37:47,240 So if there's a jump instruction for example 881 00:37:47,240 --> 00:37:49,780 that goes to that CD byte, then we're 882 00:37:49,780 --> 00:37:53,340 going to flag that jump as invalid because we never 883 00:37:53,340 --> 00:37:55,250 saw an instruction starting in the CD byte. 884 00:37:55,250 --> 00:37:57,030 We saw a different instruction. 885 00:37:57,030 --> 00:37:59,320 But if all the instruction, if all the jumps 886 00:37:59,320 --> 00:38:01,540 go to the start of instructions we saw, 887 00:38:01,540 --> 00:38:03,622 then we're in good shape. 888 00:38:03,622 --> 00:38:06,320 Does that make sense? 889 00:38:06,320 --> 00:38:08,910 So the one problem is that you can't 890 00:38:08,910 --> 00:38:11,690 check the targets of every jump in the program, 891 00:38:11,690 --> 00:38:13,460 because there might be indirect jumps. 892 00:38:13,460 --> 00:38:15,520 For example in x86, you could actually 893 00:38:15,520 --> 00:38:20,105 have something like jump to the value of that EAX register. 894 00:38:20,105 --> 00:38:22,510 This is great for implementing function pointers. 895 00:38:22,510 --> 00:38:24,670 The function pointer somewhere in memory, 896 00:38:24,670 --> 00:38:26,080 then you hold to function pointer 897 00:38:26,080 --> 00:38:27,870 into some register at one time. 898 00:38:27,870 --> 00:38:29,930 And then you jump to whatever address 899 00:38:29,930 --> 00:38:34,240 was in the [INAUDIBLE] relocation register. 900 00:38:34,240 --> 00:38:36,894 So how do these guys deal with these indirect jumps? 901 00:38:36,894 --> 00:38:38,560 So I have no idea if this actually going 902 00:38:38,560 --> 00:38:42,674 to jump to the CD byte or the 25 byte. 903 00:38:42,674 --> 00:38:43,340 What do they do? 904 00:38:43,340 --> 00:38:43,820 Yeah? 905 00:38:43,820 --> 00:38:45,310 AUDIENCE: The instrument [INAUDIBLE]. 906 00:38:45,310 --> 00:38:45,976 PROFESSOR: Yeah. 907 00:38:45,976 --> 00:38:48,690 So this is their basically main trick here, is instrumentation. 908 00:38:48,690 --> 00:38:52,180 So whenever they see a jump like this, 909 00:38:52,180 --> 00:38:55,120 well actually what the compiler is going to generate 910 00:38:55,120 --> 00:38:56,960 is a proof that this jump is actually 911 00:38:56,960 --> 00:38:58,740 going to do the right thing. 912 00:38:58,740 --> 00:39:01,950 And the way they actually do this is-- they 913 00:39:01,950 --> 00:39:04,610 don't actually know-- it's actually kind of hard 914 00:39:04,610 --> 00:39:07,540 to put in a proof here that it's one of the addresses 915 00:39:07,540 --> 00:39:09,910 that you saw during the left right disassembly. 916 00:39:09,910 --> 00:39:11,670 So instead what they do is they want 917 00:39:11,670 --> 00:39:15,770 to make sure that all the jumps go to multiples of 32 bytes. 918 00:39:15,770 --> 00:39:17,470 And the way they do this is actually 919 00:39:17,470 --> 00:39:22,240 change all the jump instructions into something 920 00:39:22,240 --> 00:39:23,640 that they pseudo instructions. 921 00:39:23,640 --> 00:39:27,458 So they're still that jump to the EAX register. 922 00:39:31,290 --> 00:39:35,220 But they prefix it with an AND instruction 923 00:39:35,220 --> 00:39:40,690 that is going to clear the low five 924 00:39:40,690 --> 00:39:50,610 bits, E 0 with an EAX register. 925 00:39:50,610 --> 00:39:53,820 So that AND instruction clears the low five bits, 926 00:39:53,820 --> 00:39:56,120 which means that it forces this value 927 00:39:56,120 --> 00:39:59,690 to be a multiple of 32, two to the five. 928 00:39:59,690 --> 00:40:01,570 And then you jump to it. 929 00:40:01,570 --> 00:40:04,960 So if you look at it during verification time, 930 00:40:04,960 --> 00:40:06,800 then you can sort of convince yourself 931 00:40:06,800 --> 00:40:12,170 that this instruction pair will only 932 00:40:12,170 --> 00:40:15,180 jump to a multiple 32 bytes. 933 00:40:15,180 --> 00:40:17,420 And then in order to make sure that this is not 934 00:40:17,420 --> 00:40:19,777 going to jump to some weird instruction, 935 00:40:19,777 --> 00:40:21,610 you're going to enforce an extra rule, which 936 00:40:21,610 --> 00:40:25,195 is that during your disassembly, when you're scanning 937 00:40:25,195 --> 00:40:27,700 your instructions from left to right, 938 00:40:27,700 --> 00:40:30,640 you're going to ensure that every multiple of 32 bytes 939 00:40:30,640 --> 00:40:34,096 is a start of a valid instruction. 940 00:40:34,096 --> 00:40:35,720 So in addition to this instrumentation, 941 00:40:35,720 --> 00:40:44,867 you're also are going to check that every multiple of 32 942 00:40:44,867 --> 00:40:45,825 is a valid instruction. 943 00:40:51,070 --> 00:40:54,635 What I mean by valid instruction here is an instruction 944 00:40:54,635 --> 00:40:57,889 that you see when you disassemble from left to right. 945 00:40:57,889 --> 00:40:58,388 Yeah? 946 00:40:58,388 --> 00:40:59,730 AUDIENCE: Why 32? 947 00:40:59,730 --> 00:41:00,850 PROFESSOR: Well, yeah, so why did they choose 32? 948 00:41:00,850 --> 00:41:02,225 That seems like some magic number 949 00:41:02,225 --> 00:41:03,910 that they pulled out of a hat. 950 00:41:03,910 --> 00:41:07,680 Should you choose 1,000 or five? 951 00:41:07,680 --> 00:41:08,660 Any comment? 952 00:41:08,660 --> 00:41:11,130 OK, should we choose five? 953 00:41:11,130 --> 00:41:12,766 So why is five bad? 954 00:41:12,766 --> 00:41:14,482 AUDIENCE: The power of two. 955 00:41:14,482 --> 00:41:16,440 PROFESSOR: Yes, OK, so we're on a power of two. 956 00:41:16,440 --> 00:41:17,310 OK, so good point. 957 00:41:17,310 --> 00:41:19,827 Because otherwise ensuring something is a multiple of 5 958 00:41:19,827 --> 00:41:21,910 is going to require a couple of instructions here, 959 00:41:21,910 --> 00:41:24,080 which is going to lead overhead. 960 00:41:24,080 --> 00:41:25,420 How about eight? 961 00:41:25,420 --> 00:41:26,550 Is eight good enough, yeah? 962 00:41:26,550 --> 00:41:28,090 AUDIENCE: You can have instructions longer than eight. 963 00:41:28,090 --> 00:41:30,089 PROFESSOR: Yeah, OK, so it has to be at least as 964 00:41:30,089 --> 00:41:32,399 long as the longest x86 instruction you want to allow. 965 00:41:32,399 --> 00:41:33,940 So if there's a ten byte instruction, 966 00:41:33,940 --> 00:41:35,350 everything has to be a multiple of eight, well, 967 00:41:35,350 --> 00:41:37,474 you're kind of screwed with a ten byte instruction. 968 00:41:37,474 --> 00:41:39,025 There's nowhere to put it. 969 00:41:39,025 --> 00:41:40,400 So it has to be at least as long. 970 00:41:40,400 --> 00:41:42,570 32 is pretty good, like the biggest I could find 971 00:41:42,570 --> 00:41:43,990 was 15 bytes. 972 00:41:43,990 --> 00:41:45,596 So it's probably good enough. 973 00:41:45,596 --> 00:41:46,096 Yeah? 974 00:41:46,096 --> 00:41:50,080 AUDIENCE: Can [INAUDIBLE] be longer than [INAUDIBLE] code, 975 00:41:50,080 --> 00:41:52,570 they'd have to have a alt instruction 976 00:41:52,570 --> 00:41:54,064 at the beginning of the [INAUDIBLE] 977 00:41:54,064 --> 00:41:56,105 so you can't just jumpt directly into [INAUDIBLE] 978 00:41:56,105 --> 00:41:58,048 and they also need a jump instruction that 979 00:41:58,048 --> 00:41:59,330 jumps to another [INAUDIBLE]. 980 00:41:59,330 --> 00:42:00,580 PROFESSOR: That's right, yeah. 981 00:42:00,580 --> 00:42:02,390 So you have to be able to fit for the entry 982 00:42:02,390 --> 00:42:04,970 and exit from the process service runtime, 983 00:42:04,970 --> 00:42:07,580 you need to be able to fit some nontrivial amount of code 984 00:42:07,580 --> 00:42:09,799 in a single 32 byte slot. 985 00:42:09,799 --> 00:42:11,340 We'll see how this works in a second. 986 00:42:11,340 --> 00:42:13,590 Or even 31 bytes slot, as you are pointing out, 987 00:42:13,590 --> 00:42:17,150 for one hold instruction. 988 00:42:17,150 --> 00:42:18,250 Should it be much larger? 989 00:42:18,250 --> 00:42:22,788 Should we make it, I don't know, a thousand byte, well, 10 24? 990 00:42:22,788 --> 00:42:25,776 AUDIENCE: [INAUDIBLE] sparse, because you have to have 991 00:42:25,776 --> 00:42:26,780 [INAUDIBLE]. 992 00:42:26,780 --> 00:42:29,450 PROFESSOR: Yeah, so if you have a lot of function pointers 993 00:42:29,450 --> 00:42:32,530 or lots of sort of indirect jumps, then every time 994 00:42:32,530 --> 00:42:36,160 you want to create some place where you're going to jump to, 995 00:42:36,160 --> 00:42:38,580 you have to pad it out to the next boundary 996 00:42:38,580 --> 00:42:40,530 of whatever this value is. 997 00:42:40,530 --> 00:42:41,830 So with 32, maybe that's OK. 998 00:42:41,830 --> 00:42:44,740 You're like well, worst case, you waste 31 bytes, 999 00:42:44,740 --> 00:42:47,530 because you just need to fast forward to the next boundary. 1000 00:42:47,530 --> 00:42:51,280 But if it's a multiple of 1024, then all of a sudden you're 1001 00:42:51,280 --> 00:42:54,730 wasting a kilobyte of memory for an indirect jump. 1002 00:42:54,730 --> 00:42:59,580 And if you have probably short functions or lots of function 1003 00:42:59,580 --> 00:43:01,280 pointers, then this might actually 1004 00:43:01,280 --> 00:43:04,240 be a memory overhead all of a sudden, as well. 1005 00:43:04,240 --> 00:43:05,930 Does that make sense roughly? 1006 00:43:05,930 --> 00:43:08,330 So yeah, I think the 32 is not set in stone. 1007 00:43:08,330 --> 00:43:11,485 Like Native Client has to have 32 byte blocks, 1008 00:43:11,485 --> 00:43:13,310 but something on that order probably works. 1009 00:43:13,310 --> 00:43:15,330 16 is probably a little short. 1010 00:43:15,330 --> 00:43:17,580 On the other hand, like 64 could work. 1011 00:43:17,580 --> 00:43:21,740 128 maybe is getting a little longish. 1012 00:43:21,740 --> 00:43:23,750 But I don't think you could derive 32 1013 00:43:23,750 --> 00:43:26,231 from first principles. 1014 00:43:26,231 --> 00:43:28,880 Makes sense? 1015 00:43:28,880 --> 00:43:30,090 All right. 1016 00:43:30,090 --> 00:43:33,280 So let's set a plan for reliable disassembly. 1017 00:43:33,280 --> 00:43:38,030 And as a result, the compiler has to be a little bit careful 1018 00:43:38,030 --> 00:43:42,220 when it's compiling your C or C++ code into a Native Client 1019 00:43:42,220 --> 00:43:42,720 binary. 1020 00:43:42,720 --> 00:43:44,344 It has to basically follow these rules. 1021 00:43:44,344 --> 00:43:46,660 So whenever it has a jump, it has 1022 00:43:46,660 --> 00:43:49,640 to add those extra instruction front. 1023 00:43:49,640 --> 00:43:53,049 And whatever it's creating a function 1024 00:43:53,049 --> 00:43:54,840 that it's going to jump to, our instruction 1025 00:43:54,840 --> 00:43:56,673 is going to jump to, as we're talking about, 1026 00:43:56,673 --> 00:43:58,000 it has to pad it out. 1027 00:43:58,000 --> 00:44:00,150 And it can't just pad it out with zeros, 1028 00:44:00,150 --> 00:44:02,590 because all those have to valid up codes. 1029 00:44:02,590 --> 00:44:04,710 So it actually has to pad it out with [INAUDIBLE] 1030 00:44:04,710 --> 00:44:06,535 just to make the validator happy, 1031 00:44:06,535 --> 00:44:08,720 just to make sure that every possible instruction is 1032 00:44:08,720 --> 00:44:09,800 a valid one. 1033 00:44:09,800 --> 00:44:12,390 And luckily on x86, no op is a single byte, 1034 00:44:12,390 --> 00:44:14,940 or at least there is a no op-- that's a single byte. 1035 00:44:14,940 --> 00:44:17,600 There's many no ops on x86. 1036 00:44:17,600 --> 00:44:20,200 So you can always pad things out to a multiple 1037 00:44:20,200 --> 00:44:22,670 of whatever this constant is. 1038 00:44:22,670 --> 00:44:25,040 Make sense? 1039 00:44:25,040 --> 00:44:26,330 All right. 1040 00:44:26,330 --> 00:44:29,030 So what does this guarantee to us? 1041 00:44:29,030 --> 00:44:31,490 I guess let's make sure that we always 1042 00:44:31,490 --> 00:44:34,370 see what happens in terms of the instructions that 1043 00:44:34,370 --> 00:44:35,220 will be executed. 1044 00:44:35,220 --> 00:44:37,630 So this finally gets us this rule. 1045 00:44:37,630 --> 00:44:43,280 So we can be sure there's never a system call being issued. 1046 00:44:43,280 --> 00:44:45,850 What about-- So this is for jumps. 1047 00:44:45,850 --> 00:44:46,700 What about returns? 1048 00:44:46,700 --> 00:44:49,570 How do they deal with the returns? 1049 00:44:49,570 --> 00:44:52,874 Can you return for a function in Native Client? 1050 00:44:52,874 --> 00:44:56,770 What would happen if you ran into a red hot code? 1051 00:44:56,770 --> 00:44:57,731 Would that be good? 1052 00:44:57,731 --> 00:44:58,231 Yeah? 1053 00:44:58,231 --> 00:45:01,640 AUDIENCE: [INAUDIBLE] you don't want the-- [INAUDIBLE] 1054 00:45:01,640 --> 00:45:03,947 modifying your overall [INAUDIBLE]. 1055 00:45:03,947 --> 00:45:06,030 PROFESSOR: Well, it's true that it pops the stack. 1056 00:45:06,030 --> 00:45:09,700 But the stack that Native Client modules use, 1057 00:45:09,700 --> 00:45:13,270 it's actually just some data inside of their section. 1058 00:45:13,270 --> 00:45:16,309 So you don't actually care-- the Native Client contact 1059 00:45:16,309 --> 00:45:18,600 doesn't care whether those guys screws up their stacks, 1060 00:45:18,600 --> 00:45:19,767 overflow their stack, or-- 1061 00:45:19,767 --> 00:45:22,340 AUDIENCE: Wait, but you could put anything on the stack. 1062 00:45:22,340 --> 00:45:24,340 And when you [INAUDIBLE] you jump through that-- 1063 00:45:24,340 --> 00:45:25,090 PROFESSOR: That's true. 1064 00:45:25,090 --> 00:45:27,048 Yeah, so return is almost like an indirect jump 1065 00:45:27,048 --> 00:45:29,160 from a particular weird memory location 1066 00:45:29,160 --> 00:45:30,890 that's at the top of the stack. 1067 00:45:30,890 --> 00:45:33,580 So I guess one thing they could do for return 1068 00:45:33,580 --> 00:45:36,270 is maybe prefix it with a similar check, where maybe like 1069 00:45:36,270 --> 00:45:37,800 pop the top thing of the stack. 1070 00:45:37,800 --> 00:45:40,080 You check whether it's valid, and then you write, 1071 00:45:40,080 --> 00:45:43,240 or you somehow do an AND to a memory operand, 1072 00:45:43,240 --> 00:45:45,360 and that's the top of the stack. 1073 00:45:45,360 --> 00:45:48,640 It seems a little fragile, partly because 1074 00:45:48,640 --> 00:45:49,440 of race conditions. 1075 00:45:49,440 --> 00:45:51,045 Because for example, if you look at the top location 1076 00:45:51,045 --> 00:45:53,020 of the stack, you check that it's OK, 1077 00:45:53,020 --> 00:45:56,060 and then you do a write later, another threat 1078 00:45:56,060 --> 00:45:58,090 in the same module could modify the thing 1079 00:45:58,090 --> 00:45:59,710 at the top of the stack. 1080 00:45:59,710 --> 00:46:02,640 And then you'd be referring to that address. 1081 00:46:02,640 --> 00:46:05,100 AUDIENCE: Would this not be the case for the jumps as well? 1082 00:46:05,100 --> 00:46:06,390 PROFESSOR: Yeah, so what happens with the jump? 1083 00:46:06,390 --> 00:46:09,030 Could our race conditions somehow invalidate this check? 1084 00:46:11,793 --> 00:46:12,292 Yeah? 1085 00:46:12,292 --> 00:46:13,751 AUDIENCE: The code is not writable. 1086 00:46:13,751 --> 00:46:16,000 PROFESSOR: Well the code is not writable, that's true. 1087 00:46:16,000 --> 00:46:17,475 So you can't modify the AND. 1088 00:46:17,475 --> 00:46:21,250 But could another thread modify this jump target 1089 00:46:21,250 --> 00:46:23,350 in between these two instructions? 1090 00:46:23,350 --> 00:46:23,850 Yeah? 1091 00:46:23,850 --> 00:46:25,350 AUDIENCE: It's in a register, so-- 1092 00:46:25,350 --> 00:46:26,975 PROFESSOR: Yeah, that's the cool thing. 1093 00:46:26,975 --> 00:46:29,880 There is basically-- if it modifies it in memory 1094 00:46:29,880 --> 00:46:32,520 or where ever it loaded into EAX from, sure, 1095 00:46:32,520 --> 00:46:35,360 you do it before you load, in which case this EX will be bad, 1096 00:46:35,360 --> 00:46:36,990 but then will clear the bad bits. 1097 00:46:36,990 --> 00:46:38,909 Or it could modify it after, at which point 1098 00:46:38,909 --> 00:46:40,450 it's already in the EX, so it doesn't 1099 00:46:40,450 --> 00:46:43,920 matter that it's modifying the memory location from which 1100 00:46:43,920 --> 00:46:47,130 the EX register was loaded. 1101 00:46:47,130 --> 00:46:50,530 And threads don't actually share the register sets. 1102 00:46:50,530 --> 00:46:52,650 So if another thread modifies the EX register, 1103 00:46:52,650 --> 00:46:55,210 it will not affect this thread's EX register. 1104 00:46:55,210 --> 00:46:57,860 So this instruction actually is sort of 1105 00:46:57,860 --> 00:46:59,050 race-proof in some sense. 1106 00:46:59,050 --> 00:47:03,719 Other threads can't invalidate this instruction sequence. 1107 00:47:03,719 --> 00:47:04,218 Make sense? 1108 00:47:06,930 --> 00:47:08,490 All right. 1109 00:47:08,490 --> 00:47:11,750 So here's another interesting question. 1110 00:47:11,750 --> 00:47:14,370 Could we bypass this AND? 1111 00:47:14,370 --> 00:47:16,760 I can jump around in this address space all I want. 1112 00:47:16,760 --> 00:47:18,796 And when I'm disassembling this instruction, 1113 00:47:18,796 --> 00:47:21,045 this seems like a perfectly fine parallel instruction, 1114 00:47:21,045 --> 00:47:24,680 an AND and a jump. 1115 00:47:24,680 --> 00:47:30,155 And the check for static jumps is that, well, 1116 00:47:30,155 --> 00:47:32,650 it just has to point to some target that was seen. 1117 00:47:32,650 --> 00:47:33,860 So yeah, we saw an AND. 1118 00:47:33,860 --> 00:47:35,360 That's one instruction that's valid. 1119 00:47:35,360 --> 00:47:37,980 We saw a jump, that's another valid instruction. 1120 00:47:37,980 --> 00:47:39,950 So when I see a direct jump up here, 1121 00:47:39,950 --> 00:47:42,280 maybe I jump to some address. 1122 00:47:42,280 --> 00:47:46,530 I don't know, one, two, three, seven. 1123 00:47:46,530 --> 00:47:49,542 That's actually OK, even though it's not a multiple of 32. 1124 00:47:49,542 --> 00:47:53,180 Native Client doesn't generally allow direct jumps 1125 00:47:53,180 --> 00:47:55,290 to arbitrary addresses, as long as 1126 00:47:55,290 --> 00:47:58,420 that address is a instruction that we saw during disassembly, 1127 00:47:58,420 --> 00:48:01,370 as we were just talking about. 1128 00:48:01,370 --> 00:48:05,600 So could I put in this very nicely checked indirect jump, 1129 00:48:05,600 --> 00:48:10,270 and then later on in the code jump to the second instruction 1130 00:48:10,270 --> 00:48:12,220 in that sequence? 1131 00:48:12,220 --> 00:48:14,210 So then I'll load something into EX, 1132 00:48:14,210 --> 00:48:15,850 jump here, and then directly jump 1133 00:48:15,850 --> 00:48:17,910 into this unsandboxed address. 1134 00:48:20,607 --> 00:48:22,190 That will violate the security, right? 1135 00:48:22,190 --> 00:48:23,148 Does everyone see that? 1136 00:48:23,148 --> 00:48:24,120 So how is this avoided? 1137 00:48:24,120 --> 00:48:27,024 AUDIENCE: Well, the NaCl [INAUDIBLE] and the jump 1138 00:48:27,024 --> 00:48:28,274 has to signal instruction. 1139 00:48:28,274 --> 00:48:30,440 PROFESSOR: Yeah, so this is why they call this thing 1140 00:48:30,440 --> 00:48:34,510 a single pseudo instruction. 1141 00:48:34,510 --> 00:48:36,660 And even though at the x86 level, 1142 00:48:36,660 --> 00:48:38,350 they're actually distinct instruction, 1143 00:48:38,350 --> 00:48:40,760 as far as the NaCl validator thinks of it, 1144 00:48:40,760 --> 00:48:42,980 it's actually a single atomic unit. 1145 00:48:42,980 --> 00:48:46,080 So as far as this check for whether it's an instruction 1146 00:48:46,080 --> 00:48:47,980 that you saw before, they think, oh, this 1147 00:48:47,980 --> 00:48:49,730 is the only instruction that I saw before. 1148 00:48:49,730 --> 00:48:51,400 Jumping in the middle is like jumping 1149 00:48:51,400 --> 00:48:53,565 in the middle of this guy. 1150 00:48:53,565 --> 00:48:55,020 It's the same thing. 1151 00:48:55,020 --> 00:48:58,360 So they basically enforce slightly different semantics 1152 00:48:58,360 --> 00:49:02,640 than what x86 enforces in terms of what an instruction is. 1153 00:49:02,640 --> 00:49:05,590 And this might actually mean that you 1154 00:49:05,590 --> 00:49:09,580 can represent certain instruction sequences in NaCl. 1155 00:49:09,580 --> 00:49:12,430 So if you actually had legitimate code that 1156 00:49:12,430 --> 00:49:15,030 looked like this before, this is going 1157 00:49:15,030 --> 00:49:18,002 to be turned into a single out code in NaCl. 1158 00:49:18,002 --> 00:49:19,460 But hopefully that's not a problem. 1159 00:49:19,460 --> 00:49:20,127 Yeah? 1160 00:49:20,127 --> 00:49:21,710 AUDIENCE: Presumably they can out that 1161 00:49:21,710 --> 00:49:27,040 in the trusted code base in the start of the text segment. 1162 00:49:27,040 --> 00:49:30,816 Because that way, you will always replace those two. 1163 00:49:30,816 --> 00:49:33,440 Instead of putting those in the binary that you produce anyway, 1164 00:49:33,440 --> 00:49:36,290 you just jump straight to that jump target that's 1165 00:49:36,290 --> 00:49:37,795 in the privileged section. 1166 00:49:37,795 --> 00:49:40,170 PROFESSOR: In the trusted runtime, you mean or something? 1167 00:49:40,170 --> 00:49:42,660 AUDIENCE: No, so in the first 64 K-- 1168 00:49:42,660 --> 00:49:44,910 PROFESSOR: Yeah, they had these trampolines and yeah-- 1169 00:49:44,910 --> 00:49:46,420 AUDIENCE: So they can make that one of the trampolines. 1170 00:49:46,420 --> 00:49:48,156 Except that it doesn't jump out. 1171 00:49:48,156 --> 00:49:49,332 It jumps back in. 1172 00:49:49,332 --> 00:49:50,040 PROFESSOR: Right. 1173 00:49:50,040 --> 00:49:51,861 AUDIENCE: So that way, it wouldn't 1174 00:49:51,861 --> 00:49:53,152 need to be a super instruction. 1175 00:49:53,152 --> 00:49:56,360 It would just be a single x86 jump 1176 00:49:56,360 --> 00:49:58,194 into there, which would then jump out again. 1177 00:49:58,194 --> 00:49:59,401 PROFESSOR: That's true, yeah. 1178 00:49:59,401 --> 00:50:01,940 That's another sort of clever solution that you could do, 1179 00:50:01,940 --> 00:50:04,710 is instead for the deliverance of [INAUDIBLE] 1180 00:50:04,710 --> 00:50:07,704 so suppose that you didn't want to do this pseudo instruction 1181 00:50:07,704 --> 00:50:12,920 trick, and you just wanted to have a single instruction 1182 00:50:12,920 --> 00:50:14,590 replacing the jump EAX. 1183 00:50:14,590 --> 00:50:16,090 Well, what you can basically come up 1184 00:50:16,090 --> 00:50:18,630 with is a library of all possible indirect jumps 1185 00:50:18,630 --> 00:50:19,710 you can ever do. 1186 00:50:19,710 --> 00:50:26,410 So like well, there is jump EAX, there's jump EBX, and so on. 1187 00:50:26,410 --> 00:50:28,460 And you would construct a library of these guys 1188 00:50:28,460 --> 00:50:31,209 for each of them, you would construct the safe check 1189 00:50:31,209 --> 00:50:32,750 that you'd want to replace them with. 1190 00:50:32,750 --> 00:50:36,040 So for this one, you'd put an AND in front of it, and so on. 1191 00:50:36,040 --> 00:50:38,452 And for this one, you'll also put an AND in front of it, 1192 00:50:38,452 --> 00:50:39,262 and so on. 1193 00:50:39,262 --> 00:50:43,470 And then in the compiled binary, every time 1194 00:50:43,470 --> 00:50:45,830 you want to jump to EAX, what you actually do, 1195 00:50:45,830 --> 00:50:48,690 is actually jump to a fixed address 1196 00:50:48,690 --> 00:50:51,870 that corresponds to this helpful piece of code 1197 00:50:51,870 --> 00:50:55,490 stored somewhere in that low 64 k of the program. 1198 00:50:55,490 --> 00:50:59,660 And then this guy will do the AND and jump again. 1199 00:50:59,660 --> 00:51:01,460 The reason that they probably don't do this 1200 00:51:01,460 --> 00:51:04,450 is performance for this sort of interesting reason. 1201 00:51:04,450 --> 00:51:07,675 So that Intel processor, actually most processors 1202 00:51:07,675 --> 00:51:11,720 these days, have to predict where 1203 00:51:11,720 --> 00:51:14,830 the branch goes to keep the pipeline of the processor 1204 00:51:14,830 --> 00:51:16,025 full at all times. 1205 00:51:16,025 --> 00:51:18,150 It's one of the really complicated branch predictor 1206 00:51:18,150 --> 00:51:20,649 that not only decides whether you're going to branch or not, 1207 00:51:20,649 --> 00:51:21,740 like if statements. 1208 00:51:21,740 --> 00:51:23,949 But also actually guesses where you're going to jump. 1209 00:51:23,949 --> 00:51:25,740 So if you see an indirect jump, it actually 1210 00:51:25,740 --> 00:51:27,880 is going to guess what the address is going to be. 1211 00:51:27,880 --> 00:51:29,338 And this is actually a guess that's 1212 00:51:29,338 --> 00:51:32,720 stored per cache line stored in the jump instruction. 1213 00:51:32,720 --> 00:51:34,980 So if you have a single place where all the jump 1214 00:51:34,980 --> 00:51:37,037 EAXs come from, then the CPU is always 1215 00:51:37,037 --> 00:51:38,120 going to be very confused. 1216 00:51:38,120 --> 00:51:40,250 Because these jump EAXs seem to be going all over the place, 1217 00:51:40,250 --> 00:51:41,045 everywhere. 1218 00:51:41,045 --> 00:51:43,170 Where as if we are really tied to a particular jump 1219 00:51:43,170 --> 00:51:45,215 instruction, it would be a better prediction. 1220 00:51:45,215 --> 00:51:48,620 That's just a performance trick that they play. 1221 00:51:48,620 --> 00:51:49,120 Make sense? 1222 00:51:51,760 --> 00:51:52,860 All right. 1223 00:51:52,860 --> 00:51:56,127 So I guess we roughly understand how 1224 00:51:56,127 --> 00:51:57,710 it's going to disassemble all of these 1225 00:51:57,710 --> 00:52:00,830 instructions how it's going to prevent these instructions. 1226 00:52:00,830 --> 00:52:03,440 So now let's look at the set of rules 1227 00:52:03,440 --> 00:52:05,667 they are going to enforce through this table 1228 00:52:05,667 --> 00:52:08,560 in the paper, table one. 1229 00:52:08,560 --> 00:52:12,880 And it has all these different rules for the validator 1230 00:52:12,880 --> 00:52:15,396 to follow, or that the binaries have to follow 1231 00:52:15,396 --> 00:52:17,010 and the validator checks. 1232 00:52:17,010 --> 00:52:19,176 So I'll go through these rules and just double check 1233 00:52:19,176 --> 00:52:21,350 that we understand why all these rules are there. 1234 00:52:21,350 --> 00:52:28,510 So we have these things, C1, all the way to C7. 1235 00:52:28,510 --> 00:52:32,700 So C1 basically says that once you load the binary memory, 1236 00:52:32,700 --> 00:52:38,720 then the binary is actually not writable at the page table 1237 00:52:38,720 --> 00:52:40,100 level. 1238 00:52:40,100 --> 00:52:42,630 So they set the permission bits for the binary 1239 00:52:42,630 --> 00:52:43,650 can be non-writable. 1240 00:52:43,650 --> 00:52:45,467 So why? 1241 00:52:45,467 --> 00:52:47,050 It should be fairly obvious hopefully. 1242 00:52:49,870 --> 00:52:52,020 The reason is that their whole security 1243 00:52:52,020 --> 00:52:55,749 plan relies on them checking that your binary is correct. 1244 00:52:55,749 --> 00:52:57,290 So once they've checked it, they want 1245 00:52:57,290 --> 00:52:59,300 to make sure you can't modify the binary 1246 00:52:59,300 --> 00:53:02,680 and have it do something illegal that they prohibited. 1247 00:53:02,680 --> 00:53:05,870 So this is I think reasonably clear then. 1248 00:53:05,870 --> 00:53:09,770 So C2 is their plan that basically has to 1249 00:53:09,770 --> 00:53:16,890 linked at zero at start at 64 K. So this requirement, 1250 00:53:16,890 --> 00:53:19,694 I think doesn't actually have to do with security so much. 1251 00:53:19,694 --> 00:53:21,110 I think it's just for convenience, 1252 00:53:21,110 --> 00:53:23,570 because they just want to have a standard layout 1253 00:53:23,570 --> 00:53:25,190 for the program. 1254 00:53:25,190 --> 00:53:27,440 In some sense, it's for simplicity 1255 00:53:27,440 --> 00:53:29,950 so that they don't have to deal with complicated relocation 1256 00:53:29,950 --> 00:53:32,040 records, which means that there's 1257 00:53:32,040 --> 00:53:35,630 fewer things that the validator or a loader might screw up. 1258 00:53:35,630 --> 00:53:39,140 But basically this is sort of a standardization plan for them, 1259 00:53:39,140 --> 00:53:42,280 in terms of how to load their executable. 1260 00:53:42,280 --> 00:53:44,280 Make sense? 1261 00:53:44,280 --> 00:53:44,780 All right. 1262 00:53:44,780 --> 00:53:51,530 So the third requirement is that I guess the indirect jumps use 1263 00:53:51,530 --> 00:53:53,632 the two instruction. 1264 00:53:56,440 --> 00:53:58,860 So the two instruction is this thing above. 1265 00:53:58,860 --> 00:54:01,980 So that, we just talked about, why it needs to ensure this, 1266 00:54:01,980 --> 00:54:05,100 so that you don't jump to the middle of some instruction, 1267 00:54:05,100 --> 00:54:09,542 or somehow invoked [INAUDIBLE], et cetera. 1268 00:54:09,542 --> 00:54:11,530 Make sense? 1269 00:54:11,530 --> 00:54:12,620 All right. 1270 00:54:12,620 --> 00:54:14,430 So what's going on with C4? 1271 00:54:14,430 --> 00:54:22,680 Basically you have to pad out two page boundary with a halt 1272 00:54:22,680 --> 00:54:24,720 instruction. 1273 00:54:24,720 --> 00:54:28,185 Why do they want to pad their binary out with halts? 1274 00:54:31,000 --> 00:54:32,332 Any ideas? 1275 00:54:32,332 --> 00:54:33,876 Yeah? 1276 00:54:33,876 --> 00:54:34,792 AUDIENCE: [INAUDIBLE]. 1277 00:54:41,680 --> 00:54:46,360 PROFESSOR: Yeah, I think-- so I have to admit, 1278 00:54:46,360 --> 00:54:48,300 I don't have a crisp answer for why C4 exists. 1279 00:54:48,300 --> 00:54:49,674 But I think it's roughly what you 1280 00:54:49,674 --> 00:54:52,650 are saying, which is that if you-- the code naturally 1281 00:54:52,650 --> 00:54:53,685 stops at some point. 1282 00:54:53,685 --> 00:54:54,946 There's some end to it. 1283 00:54:54,946 --> 00:54:56,320 And the question is, what happens 1284 00:54:56,320 --> 00:54:59,670 when you just keep executing it, and you get to the end? 1285 00:54:59,670 --> 00:55:02,570 Then the processor might just keep executing past the end, 1286 00:55:02,570 --> 00:55:04,445 and execute some extra instructions. 1287 00:55:04,445 --> 00:55:06,450 Or maybe it wraps around in some weird way. 1288 00:55:06,450 --> 00:55:08,450 So they just want to make sure that there's 1289 00:55:08,450 --> 00:55:12,085 no ambiguity about what happens if you keep running 1290 00:55:12,085 --> 00:55:14,430 and you don't jump, and you just run off the end 1291 00:55:14,430 --> 00:55:15,690 of the instruction screen. 1292 00:55:15,690 --> 00:55:18,220 So let's just make sure that the only answer there 1293 00:55:18,220 --> 00:55:20,835 is if you keep executing, you'll halt, 1294 00:55:20,835 --> 00:55:22,245 and you'll trap into the runtime, 1295 00:55:22,245 --> 00:55:24,139 and you'll terminate the module. 1296 00:55:24,139 --> 00:55:26,180 So it's just sort of about simplicity and safety, 1297 00:55:26,180 --> 00:55:27,545 [INAUDIBLE]. 1298 00:55:27,545 --> 00:55:30,780 I don't think there's a concrete attack that I could have 1299 00:55:30,780 --> 00:55:31,313 [INAUDIBLE]. 1300 00:55:31,313 --> 00:55:32,229 AUDIENCE: [INAUDIBLE]. 1301 00:55:35,130 --> 00:55:35,950 PROFESSOR: Yeah. 1302 00:55:35,950 --> 00:55:37,120 But here's the thing. 1303 00:55:37,120 --> 00:55:39,840 You can't jump past the end. 1304 00:55:39,840 --> 00:55:41,990 So the last thing that you could jump to 1305 00:55:41,990 --> 00:55:44,140 is the last instruction. 1306 00:55:44,140 --> 00:55:46,460 And by this rule, that instruction must be hold. 1307 00:55:46,460 --> 00:55:49,350 So you could jump to the hold, but then would be at the hold. 1308 00:55:49,350 --> 00:55:52,570 And you want to run past the end. 1309 00:55:52,570 --> 00:55:54,890 So I think it's just sort of cleanliness, 1310 00:55:54,890 --> 00:55:58,380 as far as I can tell, a guarantee for them to make sure 1311 00:55:58,380 --> 00:56:00,362 that there's no weirdness in terms 1312 00:56:00,362 --> 00:56:03,870 of wrap around at the engine. 1313 00:56:03,870 --> 00:56:04,850 All right? 1314 00:56:04,850 --> 00:56:10,000 So C5 is basically no instructions 1315 00:56:10,000 --> 00:56:16,160 that span the 32 byte boundary. 1316 00:56:16,160 --> 00:56:18,880 So this is sort of a variant of this rule 1317 00:56:18,880 --> 00:56:22,410 that we talked about before, where every multiple of 32 1318 00:56:22,410 --> 00:56:25,080 must be a valid instruction that we solder in disassembly. 1319 00:56:25,080 --> 00:56:27,880 So otherwise, we'll jump to the middle of an instruction 1320 00:56:27,880 --> 00:56:30,245 and have the problem with that sys call 1321 00:56:30,245 --> 00:56:32,050 that might be hidden there. 1322 00:56:32,050 --> 00:56:32,880 OK. 1323 00:56:32,880 --> 00:56:38,580 And then we have C6, which is basically all instructions 1324 00:56:38,580 --> 00:56:45,584 reachable by disassembly from the start. 1325 00:56:45,584 --> 00:56:47,500 So this ensures that we see every instruction, 1326 00:56:47,500 --> 00:56:49,750 and we can check every instruction that could possibly 1327 00:56:49,750 --> 00:56:51,930 be run at runtime. 1328 00:56:51,930 --> 00:56:55,275 And I guess C7 is this basically all direct jumps. 1329 00:57:00,031 --> 00:57:00,530 OK. 1330 00:57:00,530 --> 00:57:03,020 So this is the example of that jump up there, where you 1331 00:57:03,020 --> 00:57:04,760 code in the target right away. 1332 00:57:04,760 --> 00:57:06,680 So it doesn't have a multiple of 32, 1333 00:57:06,680 --> 00:57:08,770 but it still has to be a valid instruction 1334 00:57:08,770 --> 00:57:12,003 that we solder in the left to right disassembly. 1335 00:57:12,003 --> 00:57:12,503 Question? 1336 00:57:12,503 --> 00:57:16,984 AUDIENCE: So what's the difference between C5 and C3? 1337 00:57:16,984 --> 00:57:17,650 PROFESSOR: Yeah. 1338 00:57:17,650 --> 00:57:22,830 So I think C5 says that if I have an instruction 1339 00:57:22,830 --> 00:57:29,080 that's multiple bytes, it cannot stay on that 32 byte boundary. 1340 00:57:29,080 --> 00:57:32,780 So suppose that I have my instruction stream. 1341 00:57:32,780 --> 00:57:35,900 And here's an address, 32. 1342 00:57:35,900 --> 00:57:37,960 Here's address 64. 1343 00:57:37,960 --> 00:57:40,050 And maybe I have some sort of an AND instruction 1344 00:57:40,050 --> 00:57:43,060 that sort of spans this boundary. 1345 00:57:43,060 --> 00:57:45,120 So this is what C5 prohibits. 1346 00:57:45,120 --> 00:57:46,990 No instructions can span this boundary. 1347 00:57:46,990 --> 00:57:49,470 Because otherwise, we saw this AND instruction. 1348 00:57:49,470 --> 00:57:51,665 But because you can always jump 32 byte multiples, 1349 00:57:51,665 --> 00:57:53,290 you could jump into the middle of that. 1350 00:57:53,290 --> 00:57:55,380 And who knows what will happen there? 1351 00:57:55,380 --> 00:57:57,920 So this is what C5 prohibits for that. 1352 00:57:57,920 --> 00:58:02,090 And C3 is the counterpart to it on the jump side. 1353 00:58:02,090 --> 00:58:04,560 So C3 says that whenever you jump, 1354 00:58:04,560 --> 00:58:07,090 you're going to jump to a multiple of 32 bytes. 1355 00:58:07,090 --> 00:58:10,450 And C5 says that everything you can find in a multiple of 32 1356 00:58:10,450 --> 00:58:13,049 bytes is a safe instruction. 1357 00:58:13,049 --> 00:58:14,882 AUDIENCE: I wonder if there's any redundancy 1358 00:58:14,882 --> 00:58:15,780 because [INAUDIBLE]. 1359 00:58:15,780 --> 00:58:17,090 PROFESSOR: Yeah, I don't know. 1360 00:58:17,090 --> 00:58:17,550 I'm not sure. 1361 00:58:17,550 --> 00:58:19,900 I had a little bit of that feeling when reading this list. 1362 00:58:19,900 --> 00:58:21,691 It seems like, wow, they're all good rules. 1363 00:58:21,691 --> 00:58:24,000 But I'm not sure it's the minimal, non-orthonormal set 1364 00:58:24,000 --> 00:58:31,640 of-- or set of orthonormal rules that you need to enforce this. 1365 00:58:31,640 --> 00:58:33,550 But any other questions about the set 1366 00:58:33,550 --> 00:58:36,650 of restrictions they have? 1367 00:58:36,650 --> 00:58:37,680 All right. 1368 00:58:37,680 --> 00:58:40,869 So I guess let's think about this homework question 1369 00:58:40,869 --> 00:58:41,910 that we sort of assigned. 1370 00:58:41,910 --> 00:58:43,618 It turns out-- I think there was actually 1371 00:58:43,618 --> 00:58:45,243 a bug that Native Client had and that's 1372 00:58:45,243 --> 00:58:46,701 in our sandbox at some point, which 1373 00:58:46,701 --> 00:58:48,510 is that for some complicated instruction, 1374 00:58:48,510 --> 00:58:52,320 I believe they didn't have the length encoding correctly, 1375 00:58:52,320 --> 00:58:55,980 if I remember properly, in which case 1376 00:58:55,980 --> 00:58:58,090 something bad might happen. 1377 00:58:58,090 --> 00:58:59,880 I can't remember exactly what the bug was. 1378 00:58:59,880 --> 00:59:03,100 But suppose that the sandbox validator 1379 00:59:03,100 --> 00:59:06,792 gets the length of some instruction wrong. 1380 00:59:06,792 --> 00:59:08,590 What bad things could happen? 1381 00:59:08,590 --> 00:59:09,860 How would you exploit this? 1382 00:59:09,860 --> 00:59:12,132 AUDIENCE: You can hide a sys call or a [INAUDIBLE] 1383 00:59:12,132 --> 00:59:12,924 potentially. 1384 00:59:12,924 --> 00:59:13,590 PROFESSOR: Yeah. 1385 00:59:13,590 --> 00:59:17,600 So suppose that there's some fancy variant of some AND 1386 00:59:17,600 --> 00:59:19,570 instruction that you could write down. 1387 00:59:19,570 --> 00:59:21,570 And maybe the validator gets that wrong 1388 00:59:21,570 --> 00:59:23,730 and thinks that, oh, this guy is actually 1389 00:59:23,730 --> 00:59:27,370 six bytes, when in reality, it's five bites long. 1390 00:59:27,370 --> 00:59:30,200 So you could plop this down, pull this AND down. 1391 00:59:30,200 --> 00:59:32,660 And then the validator thinks, oh, it's six bites. 1392 00:59:32,660 --> 00:59:34,380 I'll look six bites further. 1393 00:59:34,380 --> 00:59:36,669 And I'll check whether this is a valid instruction. 1394 00:59:36,669 --> 00:59:38,460 And we just have to make sure that whatever 1395 00:59:38,460 --> 00:59:40,920 is six bytes later looks like a valid instruction. 1396 00:59:40,920 --> 00:59:43,450 But the CPU itself, when it runs this code, 1397 00:59:43,450 --> 00:59:45,917 is going to maybe only look five bytes from the AND 1398 00:59:45,917 --> 00:59:48,000 because that's the real length of the instruction. 1399 00:59:48,000 --> 00:59:50,730 So if we can use this extra byte to stick a sys call 1400 00:59:50,730 --> 00:59:52,480 instruction, then we could be in business. 1401 00:59:52,480 --> 00:59:58,524 So if we stick that-- remember from that example above on x86, 1402 00:59:58,524 --> 01:00:00,190 OXCD is how you make an AND instruction. 1403 01:00:00,190 --> 01:00:05,050 So if we stick a CD byte at the end of that AND, 1404 01:00:05,050 --> 01:00:06,870 then maybe we can put something here 1405 01:00:06,870 --> 01:00:08,859 that looks like an instruction but actually is 1406 01:00:08,859 --> 01:00:11,080 going to be part of the AND instruction here. 1407 01:00:11,080 --> 01:00:13,310 And then we can all of a sudden make a sys call 1408 01:00:13,310 --> 01:00:16,433 and escape the inner sandbox. 1409 01:00:16,433 --> 01:00:17,415 Makes sense? 1410 01:00:17,415 --> 01:00:20,380 Any questions? 1411 01:00:20,380 --> 01:00:22,755 So the validator in Native Client 1412 01:00:22,755 --> 01:00:24,330 has to be really in sync with what 1413 01:00:24,330 --> 01:00:27,400 the CPU is doing because it's sort of guessing, well, here's 1414 01:00:27,400 --> 01:00:29,900 exactly how the CPU is going to interpret every instruction. 1415 01:00:29,900 --> 01:00:32,746 It has to be right at every level here. 1416 01:00:32,746 --> 01:00:35,477 So that's going to be a little bit tricky to do right. 1417 01:00:35,477 --> 01:00:37,560 But there are actually some other interesting bugs 1418 01:00:37,560 --> 01:00:39,300 in Native Client that people have found. 1419 01:00:39,300 --> 01:00:42,040 One, I think, has to do with not properly sanitizing 1420 01:00:42,040 --> 01:00:45,390 the environment of the CPU when you're jumping into the trusted 1421 01:00:45,390 --> 01:00:46,270 service runtime. 1422 01:00:46,270 --> 01:00:48,020 I guess we'll talk about this in a second. 1423 01:00:48,020 --> 01:00:50,213 But the trusted service runtime is 1424 01:00:50,213 --> 01:00:52,212 going to basically run with the same sort of set 1425 01:00:52,212 --> 01:00:55,400 of CPU registers initially that the untrusted module was 1426 01:00:55,400 --> 01:00:56,496 running with. 1427 01:00:56,496 --> 01:00:58,120 So if there's something that it forgets 1428 01:00:58,120 --> 01:01:02,230 to clear or reset or whatnot, then the trusted service 1429 01:01:02,230 --> 01:01:05,070 runtime might be tricked into doing something 1430 01:01:05,070 --> 01:01:07,980 that it wasn't meant to do, or the developers 1431 01:01:07,980 --> 01:01:11,330 didn't want to do it initially. 1432 01:01:11,330 --> 01:01:12,489 OK. 1433 01:01:12,489 --> 01:01:13,030 So let's see. 1434 01:01:13,030 --> 01:01:13,910 Where are we now? 1435 01:01:13,910 --> 01:01:15,780 So what we understand now is roughly 1436 01:01:15,780 --> 01:01:17,820 how we can disassemble all the instructions 1437 01:01:17,820 --> 01:01:19,860 and how to prevent disallowed instructions. 1438 01:01:19,860 --> 01:01:24,860 So now let's look at, how do we keep the memory and references 1439 01:01:24,860 --> 01:01:29,550 for both code and data within the bounds of the module? 1440 01:01:29,550 --> 01:01:32,855 So for performance reasons, the Native Client guys actually 1441 01:01:32,855 --> 01:01:34,230 start using some hardware support 1442 01:01:34,230 --> 01:01:36,810 at this point to make sure this actually 1443 01:01:36,810 --> 01:01:38,430 doesn't impose much overhead. 1444 01:01:38,430 --> 01:01:40,664 But before we look at the hardware support they use, 1445 01:01:40,664 --> 01:01:43,330 does anyone have any suggestions for how we could do it actually 1446 01:01:43,330 --> 01:01:44,538 without any hardware support? 1447 01:01:44,538 --> 01:01:48,430 Could we just enforce all the memory accesses 1448 01:01:48,430 --> 01:01:52,085 going in bounds with the machine we have so far? 1449 01:01:52,085 --> 01:01:53,015 Yeah. 1450 01:01:53,015 --> 01:01:56,070 AUDIENCE: You can instrument the instructions 1451 01:01:56,070 --> 01:01:57,370 to clear all the higher bits. 1452 01:01:57,370 --> 01:01:58,370 PROFESSOR: That's right. 1453 01:01:58,370 --> 01:01:58,500 Yeah. 1454 01:01:58,500 --> 01:02:01,080 So actually we see that we have this instruction over here, 1455 01:02:01,080 --> 01:02:02,980 which every time we, for example, 1456 01:02:02,980 --> 01:02:05,770 jump somewhere, right now, we clear the low bits. 1457 01:02:05,770 --> 01:02:08,310 But if we want to keep all the possible code that you're 1458 01:02:08,310 --> 01:02:11,580 executing within the low 256 Megs, 1459 01:02:11,580 --> 01:02:13,330 then you could just replace this with a 0. 1460 01:02:13,330 --> 01:02:16,830 So we end with 0ffffe0. 1461 01:02:16,830 --> 01:02:21,521 So this clears the low bits and also caps to at most 256 Megs. 1462 01:02:21,521 --> 01:02:23,645 So this does exactly what you're sort of suggesting 1463 01:02:23,645 --> 01:02:26,720 and would make sure that whenever you're jumping, 1464 01:02:26,720 --> 01:02:29,940 you're saying within the low 256 Megs. 1465 01:02:29,940 --> 01:02:34,420 And the fact that we're doing disassembly, 1466 01:02:34,420 --> 01:02:36,890 you can also check for all the direct jumps, 1467 01:02:36,890 --> 01:02:39,030 that they're all in bounds. 1468 01:02:39,030 --> 01:02:40,414 And that's actually not so bad. 1469 01:02:40,414 --> 01:02:42,330 The reason I think they don't do this for code 1470 01:02:42,330 --> 01:02:46,340 is because in x86 you can very efficiently encode an AND where 1471 01:02:46,340 --> 01:02:47,820 all the top bits are 1. 1472 01:02:47,820 --> 01:02:50,490 So this turns out to be, I think, 1473 01:02:50,490 --> 01:02:53,185 basically a 3 byte instruction for the AND, 1474 01:02:53,185 --> 01:02:55,410 and a 2 byte instruction for the jump. 1475 01:02:55,410 --> 01:02:57,270 So the overhead is, like, 3 more bytes. 1476 01:02:57,270 --> 01:03:00,260 But if you want to have non-1 high bits, 1477 01:03:00,260 --> 01:03:02,830 then this is actually now a 5 byte instruction all of sudden. 1478 01:03:02,830 --> 01:03:04,240 So I think they're worried a little bit about the overhead 1479 01:03:04,240 --> 01:03:05,500 here. 1480 01:03:05,500 --> 01:03:06,287 Question? 1481 01:03:06,287 --> 01:03:07,870 AUDIENCE: Isn't there also the problem 1482 01:03:07,870 --> 01:03:09,661 that you might have some instructions which 1483 01:03:09,661 --> 01:03:11,840 increment what version that you're trying to get? 1484 01:03:11,840 --> 01:03:14,020 So you might say-- your instruction 1485 01:03:14,020 --> 01:03:16,187 might have a constant offset or something like that. 1486 01:03:16,187 --> 01:03:17,478 PROFESSOR: Well, I think, yeah. 1487 01:03:17,478 --> 01:03:19,240 You would probably prohibit instructions 1488 01:03:19,240 --> 01:03:21,990 that jump to some complicated formula of an address. 1489 01:03:21,990 --> 01:03:24,520 So you will only support an instruction that jumps directly 1490 01:03:24,520 --> 01:03:25,540 to this value. 1491 01:03:25,540 --> 01:03:28,262 And this value always gets ANDed and-- 1492 01:03:28,262 --> 01:03:30,470 AUDIENCE: It's more for memory accesses rather than-- 1493 01:03:30,470 --> 01:03:31,136 PROFESSOR: Yeah. 1494 01:03:31,136 --> 01:03:33,600 So that's a good point because this is just code. 1495 01:03:33,600 --> 01:03:37,060 And for memory access, there's lots of weird ways on x86 1496 01:03:37,060 --> 01:03:40,330 to refer to a particular memory location. 1497 01:03:40,330 --> 01:03:43,070 In that case, you basically have to first compute the memory 1498 01:03:43,070 --> 01:03:47,560 location, then insert an extra and, and then do the access. 1499 01:03:47,560 --> 01:03:50,210 And I think that's the real reason why they're actually 1500 01:03:50,210 --> 01:03:52,210 very worried about the performance overheads 1501 01:03:52,210 --> 01:03:54,020 of this instrumentation. 1502 01:03:54,020 --> 01:03:56,426 So on x86, at least on the 32-bit, which 1503 01:03:56,426 --> 01:03:59,050 is what this paper talks about, they actually use some hardware 1504 01:03:59,050 --> 01:04:03,060 support instead to limit the code and data 1505 01:04:03,060 --> 01:04:07,330 addresses that the untrusted module can refer to. 1506 01:04:07,330 --> 01:04:11,810 So this actually leverages some somewhat esoteric hardware 1507 01:04:11,810 --> 01:04:12,980 in x86. 1508 01:04:12,980 --> 01:04:16,320 So let's see what it looks like first before we start 1509 01:04:16,320 --> 01:04:17,932 figuring out how we're going to use 1510 01:04:17,932 --> 01:04:21,240 it to sandbox the next module. 1511 01:04:21,240 --> 01:04:24,650 So this hardware is called segmentation. 1512 01:04:24,650 --> 01:04:28,220 It's sort of left over from the days before x86 1513 01:04:28,220 --> 01:04:30,650 actually even had paging. 1514 01:04:30,650 --> 01:04:40,080 So the way it works is actually there's a segmentation on x86. 1515 01:04:40,080 --> 01:04:44,170 They way it works is that whenever a process is running, 1516 01:04:44,170 --> 01:04:49,830 there's actually a table maintained by the hardware. 1517 01:04:49,830 --> 01:04:52,450 Let's call it the segment descriptor table. 1518 01:04:59,324 --> 01:05:02,610 And what this table has is just a bunch of segments, 1519 01:05:02,610 --> 01:05:05,670 numbered from 0 up to whatever the size of the table 1520 01:05:05,670 --> 01:05:08,350 is, kind of like file descriptor in Unix. 1521 01:05:08,350 --> 01:05:11,870 Except every entry has two values in it, 1522 01:05:11,870 --> 01:05:16,050 some sort of a base and a length. 1523 01:05:16,050 --> 01:05:19,110 And the same for every entry, base and length. 1524 01:05:21,720 --> 01:05:22,220 OK. 1525 01:05:22,220 --> 01:05:24,790 So what this table does is it tells us 1526 01:05:24,790 --> 01:05:27,040 that we have a couple of segments. 1527 01:05:27,040 --> 01:05:30,070 And whenever we refer to a particular segment, what 1528 01:05:30,070 --> 01:05:33,140 this in some sense means is that we're 1529 01:05:33,140 --> 01:05:37,380 talking about a chunk of memory that starts at address base 1530 01:05:37,380 --> 01:05:42,140 and goes for this length from that base upwards. 1531 01:05:42,140 --> 01:05:43,640 And the way that this actually helps 1532 01:05:43,640 --> 01:05:47,190 us to enforce memory bounds is that on x86, 1533 01:05:47,190 --> 01:05:51,530 every single instruction in one way or another, 1534 01:05:51,530 --> 01:05:53,050 whenever it's talking about memory, 1535 01:05:53,050 --> 01:05:55,150 actually talks about memory with respect 1536 01:05:55,150 --> 01:05:58,820 to a particular segment in this table. 1537 01:05:58,820 --> 01:06:02,366 So for example, when you actually do something like move 1538 01:06:02,366 --> 01:06:09,130 a memory value from a pointer stored in the EAX register 1539 01:06:09,130 --> 01:06:12,400 into maybe another pointer stored in the EBX 1540 01:06:12,400 --> 01:06:16,127 register, what you think it does is it figures out, well, 1541 01:06:16,127 --> 01:06:16,960 what's this address? 1542 01:06:16,960 --> 01:06:18,050 It knows the memory at this address. 1543 01:06:18,050 --> 01:06:20,091 And then it figures out, OK, what's this address? 1544 01:06:20,091 --> 01:06:21,700 And it stores the value there. 1545 01:06:21,700 --> 01:06:25,680 But in fact on x86, whenever you're talking about memory, 1546 01:06:25,680 --> 01:06:27,900 there's an implicit-- what's called a segment 1547 01:06:27,900 --> 01:06:30,822 descriptor, which is kind of like a file descriptor in Unix. 1548 01:06:30,822 --> 01:06:33,744 It's just an index into this descriptor table. 1549 01:06:33,744 --> 01:06:36,450 And unless specified otherwise, every opcode 1550 01:06:36,450 --> 01:06:38,490 has a default segment in it. 1551 01:06:38,490 --> 01:06:40,946 So when you're doing a move, this 1552 01:06:40,946 --> 01:06:45,470 is actually relative to the DS or the data segment register. 1553 01:06:45,470 --> 01:06:47,790 So it's like a special register in your CPU 1554 01:06:47,790 --> 01:06:51,250 that's a 16-bit integer, if I remember correctly. 1555 01:06:51,250 --> 01:06:55,020 And that 16-bit integer points into the descriptor table. 1556 01:06:55,020 --> 01:06:55,810 And the same here. 1557 01:06:55,810 --> 01:06:59,370 This is actually the relative to that DS segment selector. 1558 01:06:59,370 --> 01:07:02,690 Actually, a bunch of these guys are 6 segment selectors on x86. 1559 01:07:02,690 --> 01:07:10,740 There's a code selector CS, DS, ES, FS, GS, and SS. 1560 01:07:10,740 --> 01:07:14,709 And the code selector is sort of implicitly 1561 01:07:14,709 --> 01:07:16,000 used to fetch the instructions. 1562 01:07:16,000 --> 01:07:18,360 So if your instruction pointer points somewhere, 1563 01:07:18,360 --> 01:07:22,300 it's actually relative to what the CS segment selector says. 1564 01:07:22,300 --> 01:07:26,620 And most data references implicitly use either DS or ES. 1565 01:07:26,620 --> 01:07:28,890 And then FS and GS are some special things. 1566 01:07:28,890 --> 01:07:30,920 And SS is always used for the stack operations. 1567 01:07:30,920 --> 01:07:33,020 If you push and pop, they implicitly 1568 01:07:33,020 --> 01:07:35,625 come off of this segment selector. 1569 01:07:35,625 --> 01:07:38,400 It's a fairly baroque machinery, but it turns out 1570 01:07:38,400 --> 01:07:41,270 to be hugely useful for this particular use case 1571 01:07:41,270 --> 01:07:46,630 because what happens is if you access some address at maybe 1572 01:07:46,630 --> 01:07:53,390 some selector DS: some offset or some address here, what 1573 01:07:53,390 --> 01:07:57,250 the hardware will actually do is translate it into-- well, 1574 01:07:57,250 --> 01:07:59,680 it'll put this address, and it'll 1575 01:07:59,680 --> 01:08:07,140 add the table of DS, the base to this guy. 1576 01:08:07,140 --> 01:08:10,730 And it'll actually take the address modulo 1577 01:08:10,730 --> 01:08:13,880 the length from the same table. 1578 01:08:13,880 --> 01:08:16,390 So whenever you're doing a memory access, 1579 01:08:16,390 --> 01:08:20,002 it's actually going to have the base of your segment selectors, 1580 01:08:20,002 --> 01:08:23,200 sort of descriptor table entry, and take your address 1581 01:08:23,200 --> 01:08:25,250 that you're actually specifying and mod it 1582 01:08:25,250 --> 01:08:28,390 with the length of the corresponding segment. 1583 01:08:28,390 --> 01:08:29,689 Does this make sense? 1584 01:08:29,689 --> 01:08:32,750 It's a little baroque, but that's what [INAUDIBLE]. 1585 01:08:32,750 --> 01:08:34,730 AUDIENCE: So why isn't this used, for example, 1586 01:08:34,730 --> 01:08:36,334 for buffer protection? 1587 01:08:36,334 --> 01:08:37,000 PROFESSOR: Yeah. 1588 01:08:37,000 --> 01:08:37,874 It's a good question. 1589 01:08:37,874 --> 01:08:39,709 So could you use this for protecting 1590 01:08:39,709 --> 01:08:40,750 against buffer overflows? 1591 01:08:43,729 --> 01:08:44,910 What's the plan? 1592 01:08:44,910 --> 01:08:48,760 You could basically set up-- for every buffer that you have, 1593 01:08:48,760 --> 01:08:51,080 you could put the buffer's base here. 1594 01:08:51,080 --> 01:08:53,892 You can put the size of the buffer there. 1595 01:08:53,892 --> 01:08:55,892 AUDIENCE: What if you don't need to put it there 1596 01:08:55,892 --> 01:08:57,183 before you want to write to it? 1597 01:08:57,183 --> 01:08:58,890 You wouldn't need it there constantly. 1598 01:08:58,890 --> 01:08:59,569 PROFESSOR: Yeah. 1599 01:08:59,569 --> 01:09:01,250 So I think the reason that this isn't 1600 01:09:01,250 --> 01:09:03,910 used so much for protecting against buffer overflows 1601 01:09:03,910 --> 01:09:09,140 is that this table has at most 2 to the 16 entries 1602 01:09:09,140 --> 01:09:11,605 because these descriptors are actually 16 bits long. 1603 01:09:11,605 --> 01:09:14,380 And in fact, a couple of the bits are used for other stuff. 1604 01:09:14,380 --> 01:09:18,010 So in fact, I think you can only stick 2 to the 13 entries here. 1605 01:09:18,010 --> 01:09:21,584 So if you have more than 2 to the 13 variable size array 1606 01:09:21,584 --> 01:09:24,450 things in your code, then it's probably 1607 01:09:24,450 --> 01:09:26,130 going to overflow this table. 1608 01:09:26,130 --> 01:09:27,630 That was actually a little bit weird 1609 01:09:27,630 --> 01:09:29,339 for the compiler to manipulate this table 1610 01:09:29,339 --> 01:09:30,963 because the way you actually manipulate 1611 01:09:30,963 --> 01:09:32,140 it is through system calls. 1612 01:09:32,140 --> 01:09:33,899 So you can't actually directly write to this table. 1613 01:09:33,899 --> 01:09:36,060 You have to issue a system call to the operating system. 1614 01:09:36,060 --> 01:09:37,934 And the operating system will pull this table 1615 01:09:37,934 --> 01:09:39,800 into the hardware for you. 1616 01:09:39,800 --> 01:09:42,040 So I think most compilers just don't 1617 01:09:42,040 --> 01:09:46,550 bother having this complicated story for managing buffers. 1618 01:09:46,550 --> 01:09:47,890 Multex actually did this though. 1619 01:09:47,890 --> 01:09:50,673 So on Multex, you actually kind of have 2 1620 01:09:50,673 --> 01:09:54,902 to the 18 distinct segments and 2 to the 18 possible offsets 1621 01:09:54,902 --> 01:09:55,610 within a segment. 1622 01:09:55,610 --> 01:09:58,270 And every possible shared library chunk 1623 01:09:58,270 --> 01:10:00,020 or chunk of memory was a distinct segment. 1624 01:10:00,020 --> 01:10:02,240 And then they would all be range checked, 1625 01:10:02,240 --> 01:10:04,134 not maybe at the variable level. 1626 01:10:04,134 --> 01:10:04,634 But still. 1627 01:10:04,634 --> 01:10:05,286 Yeah. 1628 01:10:05,286 --> 01:10:07,119 AUDIENCE: Presumably, it's also a bit slower 1629 01:10:07,119 --> 01:10:09,110 if you have to tap into the kernel all the time to-- 1630 01:10:09,110 --> 01:10:09,455 PROFESSOR: That's right. 1631 01:10:09,455 --> 01:10:09,955 Yeah. 1632 01:10:09,955 --> 01:10:11,330 So there's also the overhead. 1633 01:10:11,330 --> 01:10:13,610 I guess to set this up, there would be some overhead. 1634 01:10:13,610 --> 01:10:16,390 Or if you create a new buffer on the stack, all of a sudden, 1635 01:10:16,390 --> 01:10:20,510 you have to call in to this guy and add an extra. 1636 01:10:20,510 --> 01:10:22,150 So yeah, it is nice machinery. 1637 01:10:22,150 --> 01:10:25,287 But it's mostly used for coarser grain things 1638 01:10:25,287 --> 01:10:28,269 because of the overhead of changing it a bit. 1639 01:10:28,269 --> 01:10:30,750 Makes sense? 1640 01:10:30,750 --> 01:10:31,250 All right. 1641 01:10:31,250 --> 01:10:32,680 So how many of these guys actually use 1642 01:10:32,680 --> 01:10:33,971 now the segmentation machinery? 1643 01:10:33,971 --> 01:10:36,633 Well, you can sort of guess how it works. 1644 01:10:36,633 --> 01:10:38,910 I guess by default all these segments in x86 1645 01:10:38,910 --> 01:10:41,267 have a base of 0 and a length of 2 to the 32. 1646 01:10:41,267 --> 01:10:43,100 So you can access the entire range of memory 1647 01:10:43,100 --> 01:10:44,730 you could possibly want. 1648 01:10:44,730 --> 01:10:48,120 So for Native Client, what they do is code in a base of 0 1649 01:10:48,120 --> 01:10:52,520 and a length of 256 Megs. 1650 01:10:52,520 --> 01:10:56,680 And then they point all these six segment 1651 01:10:56,680 --> 01:11:01,070 selector registers to this entry for a 256 Meg region. 1652 01:11:01,070 --> 01:11:03,700 So then whenever the hardware does a memory access, 1653 01:11:03,700 --> 01:11:04,700 it's going to mod it. 1654 01:11:04,700 --> 01:11:06,410 The offset was 256 Megs. 1655 01:11:06,410 --> 01:11:10,850 So it'll be restricted to the 256 Meg range of memory that's 1656 01:11:10,850 --> 01:11:14,040 allowed for the module to [INAUDIBLE] modify. 1657 01:11:14,040 --> 01:11:16,360 Makes sense? 1658 01:11:16,360 --> 01:11:17,850 All right. 1659 01:11:17,850 --> 01:11:21,370 So I guess we sort of roughly understand now this hardware 1660 01:11:21,370 --> 01:11:25,745 support and how this works and how you could eventually do 1661 01:11:25,745 --> 01:11:28,070 the wealth segment selectors. 1662 01:11:28,070 --> 01:11:31,590 So if we just implement this plan, 1663 01:11:31,590 --> 01:11:33,380 is there anything that could go wrong? 1664 01:11:33,380 --> 01:11:37,160 Could we escape out of the segment selector 1665 01:11:37,160 --> 01:11:38,440 in the untrusted module? 1666 01:11:41,170 --> 01:11:43,640 I guess one thing you have to watch out 1667 01:11:43,640 --> 01:11:46,534 for is that these registers are just like regular registers. 1668 01:11:46,534 --> 01:11:48,700 And you can actually move values in and out of them. 1669 01:11:48,700 --> 01:11:51,630 So you have to make sure that the untrusted module doesn't 1670 01:11:51,630 --> 01:11:54,220 tamper with these registers, the segment selectors, 1671 01:11:54,220 --> 01:11:56,535 because somewhere in your descriptor table 1672 01:11:56,535 --> 01:11:59,830 is also the original segment descriptor 1673 01:11:59,830 --> 01:12:02,295 for your entire process, which has a base of 0 1674 01:12:02,295 --> 01:12:04,560 and a length of 2 to the 32. 1675 01:12:04,560 --> 01:12:06,520 So if the untrusted module could somehow 1676 01:12:06,520 --> 01:12:10,120 change the CS or DS or ES or any of these guys 1677 01:12:10,120 --> 01:12:14,890 to point to this original operating system that 1678 01:12:14,890 --> 01:12:16,370 covers your entire address space, 1679 01:12:16,370 --> 01:12:18,578 then you could then do memory references with respect 1680 01:12:18,578 --> 01:12:22,070 to this segment and get out of this sandbox. 1681 01:12:22,070 --> 01:12:25,137 So as a result, Native Client has 1682 01:12:25,137 --> 01:12:27,930 to add some more instructions to this prohibited list. 1683 01:12:27,930 --> 01:12:31,380 So I think they basically prohibit all instructions that 1684 01:12:31,380 --> 01:12:35,590 move into a segment selector DS, ES, et cetera, 1685 01:12:35,590 --> 01:12:37,810 so that once you're in the sandbox, 1686 01:12:37,810 --> 01:12:41,840 you cannot change the segment that you are referencing things 1687 01:12:41,840 --> 01:12:43,472 with respect to. 1688 01:12:43,472 --> 01:12:44,430 Makes sense? 1689 01:12:44,430 --> 01:12:44,930 Yeah. 1690 01:12:44,930 --> 01:12:47,135 AUDIENCE: The segmentation such and such provides [INAUDIBLE]. 1691 01:12:47,135 --> 01:12:47,801 PROFESSOR: Yeah. 1692 01:12:47,801 --> 01:12:50,494 So it turns out that on x86, the instructions 1693 01:12:50,494 --> 01:12:53,040 to change the segment descriptor table are privileged. 1694 01:12:53,040 --> 01:12:56,210 But changing these indices into the table 1695 01:12:56,210 --> 01:12:58,934 are completely unprivileged. 1696 01:12:58,934 --> 01:13:00,355 Yeah. 1697 01:13:00,355 --> 01:13:01,220 Other questions? 1698 01:13:01,220 --> 01:13:01,847 Yeah. 1699 01:13:01,847 --> 01:13:03,430 AUDIENCE: Can you initialize the table 1700 01:13:03,430 --> 01:13:07,380 to put all 0 lengths in the unused slots? 1701 01:13:07,380 --> 01:13:08,520 PROFESSOR: Well, yeah. 1702 01:13:08,520 --> 01:13:10,532 So the unused slots-- you could-- yeah. 1703 01:13:10,532 --> 01:13:11,990 You can set the length of the table 1704 01:13:11,990 --> 01:13:14,390 to something so there are no unused slots. 1705 01:13:14,390 --> 01:13:18,460 It turns out that you actually need this extra slot containing 1706 01:13:18,460 --> 01:13:22,260 0 and 2 to the 32 because the trusted run time is going 1707 01:13:22,260 --> 01:13:25,680 to need to run in this segment and access the entire memory 1708 01:13:25,680 --> 01:13:26,230 range. 1709 01:13:26,230 --> 01:13:29,470 So you need this entry in there for the trusted runtime 1710 01:13:29,470 --> 01:13:30,390 to work. 1711 01:13:30,390 --> 01:13:31,150 Question? 1712 01:13:31,150 --> 01:13:32,441 AUDIENCE: [INAUDIBLE] set list? 1713 01:13:32,441 --> 01:13:34,920 In order to set the table output to some length, 1714 01:13:34,920 --> 01:13:35,615 do you need to-- 1715 01:13:35,615 --> 01:13:36,615 PROFESSOR: No, actually. 1716 01:13:36,615 --> 01:13:37,420 It's pretty cool. 1717 01:13:37,420 --> 01:13:39,470 It was like something that you don't have any root for. 1718 01:13:39,470 --> 01:13:40,928 On Linux, there's actually a system 1719 01:13:40,928 --> 01:13:45,560 called-- I think it's called modify_ldt for local descriptor 1720 01:13:45,560 --> 01:13:46,370 table. 1721 01:13:46,370 --> 01:13:48,780 And it lets any process modify its own table. 1722 01:13:48,780 --> 01:13:50,792 These tables are actually per process. 1723 01:13:50,792 --> 01:13:53,250 Well, as everything in x86, it's actually more complicated. 1724 01:13:53,250 --> 01:13:55,333 There's a global table, and there's a local table. 1725 01:13:55,333 --> 01:13:57,148 But the local table is for a process 1726 01:13:57,148 --> 01:13:59,930 you can modify [INAUDIBLE]. 1727 01:13:59,930 --> 01:14:01,416 Makes sense? 1728 01:14:01,416 --> 01:14:03,601 All right. 1729 01:14:03,601 --> 01:14:04,100 OK. 1730 01:14:04,100 --> 01:14:06,987 So I guess one thing we could now try to figure out 1731 01:14:06,987 --> 01:14:11,780 is, how do we jump in and out of the Native Client runtime 1732 01:14:11,780 --> 01:14:13,774 or out of the sandbox? 1733 01:14:13,774 --> 01:14:15,440 So what does it mean for us to jump out? 1734 01:14:15,440 --> 01:14:17,510 So we need to run that trusted code. 1735 01:14:17,510 --> 01:14:19,540 And the trusted code lives somewhere up 1736 01:14:19,540 --> 01:14:22,190 above the 256 Meg limit. 1737 01:14:22,190 --> 01:14:24,470 And in order to jump there, we basically 1738 01:14:24,470 --> 01:14:26,960 have to undo all these protections that Native Client 1739 01:14:26,960 --> 01:14:28,220 sets in place. 1740 01:14:28,220 --> 01:14:32,204 And they basically boil down to changing these selectors. 1741 01:14:32,204 --> 01:14:33,745 So we already-- I guess our validator 1742 01:14:33,745 --> 01:14:35,520 isn't going to enforce the same rules 1743 01:14:35,520 --> 01:14:37,880 for the stuff above 256 Megs. 1744 01:14:37,880 --> 01:14:38,800 So that's easy enough. 1745 01:14:38,800 --> 01:14:42,280 But then we need to somehow jump into the trusted runtime 1746 01:14:42,280 --> 01:14:45,710 and reset these segment selectors to the right values, 1747 01:14:45,710 --> 01:14:50,440 to this giant segment that covers the entire process 1748 01:14:50,440 --> 01:14:51,640 address space. 1749 01:14:51,640 --> 01:14:54,490 So the way that works on Native Client 1750 01:14:54,490 --> 01:14:56,220 is through this mechanism they call 1751 01:14:56,220 --> 01:14:58,450 trampolines and springboards. 1752 01:15:03,730 --> 01:15:06,820 So all these guys are things that live 1753 01:15:06,820 --> 01:15:12,020 in the low 64k of the module. 1754 01:15:12,020 --> 01:15:14,494 And the cool thing about that is that these 1755 01:15:14,494 --> 01:15:16,910 are going to be sort of chunks of code laying at the lower 1756 01:15:16,910 --> 01:15:18,910 64k of that process space. 1757 01:15:18,910 --> 01:15:21,460 So that means that this untrusted module can actually 1758 01:15:21,460 --> 01:15:24,850 jump there because it's a valid code address. 1759 01:15:24,850 --> 01:15:27,300 It's going to be on the 32 byte boundary potentially. 1760 01:15:27,300 --> 01:15:29,630 And it's going to be within the 256 Meg limit. 1761 01:15:29,630 --> 01:15:31,675 So you can jump to these trampolines. 1762 01:15:31,675 --> 01:15:33,920 But the Native Client runtime is going 1763 01:15:33,920 --> 01:15:36,370 to actually copy these trampolines 1764 01:15:36,370 --> 01:15:37,560 from somewhere outside. 1765 01:15:37,560 --> 01:15:39,430 So the Native Client module isn't 1766 01:15:39,430 --> 01:15:41,730 allowed to supply its own trampoline code. 1767 01:15:41,730 --> 01:15:43,905 The trampoline code comes from the trusted runtime. 1768 01:15:43,905 --> 01:15:45,405 So as a result, it actually contains 1769 01:15:45,405 --> 01:15:46,800 all these sensitive instructions, 1770 01:15:46,800 --> 01:15:50,390 like moving DS and CS, et cetera, 1771 01:15:50,390 --> 01:15:55,240 that the untrusted code itself is not allowed to have. 1772 01:15:55,240 --> 01:15:58,320 So the way you actually jump out of the sandbox 1773 01:15:58,320 --> 01:16:01,010 and into the trusted runtime to do something like malop 1774 01:16:01,010 --> 01:16:04,790 or create a threat is you jump to a trampoline, which 1775 01:16:04,790 --> 01:16:06,600 lives at a 32 byte offset. 1776 01:16:06,600 --> 01:16:08,150 So maybe it's an address. 1777 01:16:08,150 --> 01:16:08,970 Well, who knows? 1778 01:16:08,970 --> 01:16:12,430 Maybe it's 4,096 plus 32. 1779 01:16:12,430 --> 01:16:15,790 And it's going to have some instructions to basically undo 1780 01:16:15,790 --> 01:16:16,820 these segment selectors. 1781 01:16:16,820 --> 01:16:18,195 So what it's probably going to do 1782 01:16:18,195 --> 01:16:22,820 is it's going to move some value-- I don't know, maybe 7-- 1783 01:16:22,820 --> 01:16:26,420 into the DS register and maybe some points to this entry here 1784 01:16:26,420 --> 01:16:30,670 that's allowed for the entire 2 to the 32 address space. 1785 01:16:30,670 --> 01:16:33,140 And then you're going to effectively move 1786 01:16:33,140 --> 01:16:39,140 CS and then jump somewhere up into the service runtime. 1787 01:16:39,140 --> 01:16:44,382 And this is basically going to be past 256 Megs. 1788 01:16:44,382 --> 01:16:46,340 So there's going to be this jump in here that's 1789 01:16:46,340 --> 01:16:48,140 not regularly allowed. 1790 01:16:48,140 --> 01:16:50,390 But we're going to be OK with it because it's 1791 01:16:50,390 --> 01:16:54,469 going to be into a point in the trusted service runtime that 1792 01:16:54,469 --> 01:16:55,574 is expecting these jumps. 1793 01:16:55,574 --> 01:16:58,440 And it's going to perform proper checks afterwards 1794 01:16:58,440 --> 01:17:01,846 on the arguments and whatever else that is 1795 01:17:01,846 --> 01:17:03,240 being passed around. 1796 01:17:03,240 --> 01:17:05,060 And we can actually do this, move DS here, 1797 01:17:05,060 --> 01:17:06,840 because we know that it's actually safe. 1798 01:17:06,840 --> 01:17:08,466 The code we're going to jump to isn't 1799 01:17:08,466 --> 01:17:10,090 going to do anything arbitrary or funny 1800 01:17:10,090 --> 01:17:13,340 with our untrusted module. 1801 01:17:13,340 --> 01:17:16,930 Makes sense roughly, what's going on? 1802 01:17:16,930 --> 01:17:19,400 So why do these guys bother jumping out of the segments? 1803 01:17:19,400 --> 01:17:22,020 Like, why not just put the whole thing in the trampoline? 1804 01:17:25,310 --> 01:17:27,885 It seems like more work on some level. 1805 01:17:27,885 --> 01:17:28,835 Yeah. 1806 01:17:28,835 --> 01:17:29,937 AUDIENCE: We only have 64. 1807 01:17:29,937 --> 01:17:32,270 PROFESSOR: Yeah, you don't actually have a lot of space. 1808 01:17:32,270 --> 01:17:34,270 Well, I guess you have 64k. 1809 01:17:34,270 --> 01:17:36,595 So that's potentially maybe enough for-- maybe you 1810 01:17:36,595 --> 01:17:38,140 can move a malop in there. 1811 01:17:38,140 --> 01:17:40,820 But the problem is not so much the 64k thing 1812 01:17:40,820 --> 01:17:43,090 but this 32 byte restriction. 1813 01:17:43,090 --> 01:17:45,314 And it's actually not a restriction 1814 01:17:45,314 --> 01:17:47,355 on the trusted code, because the trusted code can 1815 01:17:47,355 --> 01:17:48,490 do whatever it wants here. 1816 01:17:48,490 --> 01:17:49,790 It's not going to be checked. 1817 01:17:49,790 --> 01:17:52,520 The problem is that the untrusted code can 1818 01:17:52,520 --> 01:17:54,890 jump to every 32 byte offset. 1819 01:17:54,890 --> 01:17:56,550 So every 32 byte offset has to be 1820 01:17:56,550 --> 01:17:59,390 prepared to be very special in its arguments. 1821 01:17:59,390 --> 01:18:03,080 So you probably are going to have a hard time writing 1822 01:18:03,080 --> 01:18:05,500 this code here with every 32 bytes 1823 01:18:05,500 --> 01:18:07,970 rechecking the arguments and values and so on. 1824 01:18:07,970 --> 01:18:10,980 So basically, you have to jump out of the trampoline 1825 01:18:10,980 --> 01:18:17,750 and into the runtime up here within 32 bytes of code. 1826 01:18:17,750 --> 01:18:19,375 So then if you jump to the next thing, 1827 01:18:19,375 --> 01:18:21,500 then, well, something else is going to happen here. 1828 01:18:21,500 --> 01:18:26,410 But it's not part of this same trusted routine here. 1829 01:18:26,410 --> 01:18:28,270 Makes sense? 1830 01:18:28,270 --> 01:18:28,850 OK. 1831 01:18:28,850 --> 01:18:32,060 So this is how you sort of jump out of the sandbox. 1832 01:18:32,060 --> 01:18:36,090 To jump back in, you also need to-- you basically 1833 01:18:36,090 --> 01:18:37,850 need to invert these transformations. 1834 01:18:37,850 --> 01:18:41,280 You need to sort of set the DS back and CS back and so on. 1835 01:18:41,280 --> 01:18:44,320 And the tricky thing is that if you're running outside 1836 01:18:44,320 --> 01:18:49,040 of this 256 Meg limit, if you're running inside of the trusted 1837 01:18:49,040 --> 01:18:53,060 run time, then you can't really reset these registers yet, 1838 01:18:53,060 --> 01:18:54,550 because otherwise, you won't then 1839 01:18:54,550 --> 01:18:58,019 be able to access any of the memory in your space outside. 1840 01:18:58,019 --> 01:19:00,310 So what they actually do is they have this thing called 1841 01:19:00,310 --> 01:19:03,211 a springboard, which is how the trusted 1842 01:19:03,211 --> 01:19:05,769 runtime from outside the 256 Meg limit 1843 01:19:05,769 --> 01:19:08,310 is actually going to jump back into the Native Client module. 1844 01:19:08,310 --> 01:19:13,707 So here it's going to reload the DS register with maybe whatever 1845 01:19:13,707 --> 01:19:16,060 that limit in the segment descriptor is. 1846 01:19:16,060 --> 01:19:17,180 Maybe let's say it's 1. 1847 01:19:17,180 --> 01:19:19,180 And then it's going to reset other things, 1848 01:19:19,180 --> 01:19:24,190 and then it'll jump to whatever address 1849 01:19:24,190 --> 01:19:27,460 the trusted runtime wants to return to 1850 01:19:27,460 --> 01:19:30,640 in the untrusted module. 1851 01:19:30,640 --> 01:19:31,230 Makes sense? 1852 01:19:31,230 --> 01:19:32,650 So this is how you sort of jump back in. 1853 01:19:32,650 --> 01:19:34,025 And the only sort of tricky piece 1854 01:19:34,025 --> 01:19:38,120 here is that you don't want the untrusted code to jump 1855 01:19:38,120 --> 01:19:39,840 into the springboard itself. 1856 01:19:39,840 --> 01:19:41,256 Maybe something weird will happen. 1857 01:19:41,256 --> 01:19:41,920 Who knows? 1858 01:19:41,920 --> 01:19:44,940 So what they do is they actually put a halt instruction 1859 01:19:44,940 --> 01:19:49,330 as the first byte of this 32 byte multiple sequence. 1860 01:19:49,330 --> 01:19:52,896 So if you jump to the beginning of this guy, 1861 01:19:52,896 --> 01:19:55,750 you'll immediately halt. The trusted runtime 1862 01:19:55,750 --> 01:19:59,070 is going to jump to one past this byte 1863 01:19:59,070 --> 01:20:01,165 and be able to execute the springboard. 1864 01:20:01,165 --> 01:20:03,800 But this is something that only the trusted runtime can 1865 01:20:03,800 --> 01:20:05,321 do because regularly checked, this 1866 01:20:05,321 --> 01:20:05,950 is not going to be allowed. 1867 01:20:05,950 --> 01:20:06,340 Question? 1868 01:20:06,340 --> 01:20:06,964 AUDIENCE: Wait. 1869 01:20:06,964 --> 01:20:09,570 Is it a springboard in the untrusted module? 1870 01:20:09,570 --> 01:20:12,140 PROFESSOR: So the springboard is within the 0 1871 01:20:12,140 --> 01:20:14,500 to 256 Meg part of the untrusted module. 1872 01:20:14,500 --> 01:20:17,210 But it actually lives in that 64 bit chunk 1873 01:20:17,210 --> 01:20:19,050 at the very beginning that doesn't actually 1874 01:20:19,050 --> 01:20:21,300 come from the binary you download from some website. 1875 01:20:21,300 --> 01:20:22,690 But it's actually patched into it 1876 01:20:22,690 --> 01:20:25,315 by the Native Client runtime when it first 1877 01:20:25,315 --> 01:20:27,123 loads this module into memory. 1878 01:20:27,123 --> 01:20:29,214 AUDIENCE: Why not just have it in the runtime? 1879 01:20:29,214 --> 01:20:29,880 PROFESSOR: Yeah. 1880 01:20:29,880 --> 01:20:30,780 So why not have it in the runtime? 1881 01:20:30,780 --> 01:20:32,762 So what happens if the runtime was allowed 1882 01:20:32,762 --> 01:20:33,845 to supply the springboard? 1883 01:20:38,269 --> 01:20:38,995 Is this bad? 1884 01:20:43,094 --> 01:20:44,528 Yeah. 1885 01:20:44,528 --> 01:20:47,635 AUDIENCE: How would it know-- how would it 1886 01:20:47,635 --> 01:20:49,320 know where to jump back to? 1887 01:20:49,320 --> 01:20:51,930 PROFESSOR: Well, I think what this actually is is it actually 1888 01:20:51,930 --> 01:20:54,290 jumps to something like EAX. 1889 01:20:54,290 --> 01:20:55,780 So the trusted runtime says, oh, I 1890 01:20:55,780 --> 01:20:57,342 want to return to this address. 1891 01:20:57,342 --> 01:20:59,580 It puts it on the EAX register, jumps here. 1892 01:20:59,580 --> 01:21:02,374 The springboard does this, this, this and then jumps to EAX, 1893 01:21:02,374 --> 01:21:05,130 wherever the trusted runtime's set up to jump. 1894 01:21:05,130 --> 01:21:08,960 So what if the module came with its own springboard? 1895 01:21:08,960 --> 01:21:13,366 AUDIENCE: Well, you could do it as a natural jump type thing. 1896 01:21:13,366 --> 01:21:15,782 But it shouldn't know anything about the descriptor table. 1897 01:21:15,782 --> 01:21:16,710 That's a hardware-- 1898 01:21:16,710 --> 01:21:17,376 PROFESSOR: Yeah. 1899 01:21:17,376 --> 01:21:19,734 So actually, this is a really important instruction 1900 01:21:19,734 --> 01:21:22,025 for sandboxing, the fact that we reload that descriptor 1901 01:21:22,025 --> 01:21:25,130 to point at one of those limited descriptors up there. 1902 01:21:25,130 --> 01:21:26,220 It's really important. 1903 01:21:26,220 --> 01:21:30,360 And if the module was allowed to supply its own springboard, 1904 01:21:30,360 --> 01:21:34,205 maybe it'll just skip this part and then not restrict itself 1905 01:21:34,205 --> 01:21:35,750 back to 256 Megs. 1906 01:21:35,750 --> 01:21:37,640 So once you jump through the springboard, 1907 01:21:37,640 --> 01:21:40,050 you'll be able to still access the entire process address 1908 01:21:40,050 --> 01:21:41,050 space. 1909 01:21:41,050 --> 01:21:44,075 So the springboard is part of the enforcement mechanism. 1910 01:21:44,075 --> 01:21:46,050 It sort of sets up the boundaries. 1911 01:21:46,050 --> 01:21:47,642 So this is the reason why I think 1912 01:21:47,642 --> 01:21:51,914 they don't want the springboard to come from the developer. 1913 01:21:51,914 --> 01:21:53,440 Now-- yeah, question? 1914 01:21:53,440 --> 01:21:56,750 AUDIENCE: Can you put the springboard past 256 megabytes? 1915 01:21:56,750 --> 01:21:58,650 PROFESSOR: So I think they don't want 1916 01:21:58,650 --> 01:22:01,505 to put the springboard past the 256 Megs 1917 01:22:01,505 --> 01:22:04,450 because then you might have trouble jumping down. 1918 01:22:04,450 --> 01:22:07,720 So you want to jump to a particular address, 1919 01:22:07,720 --> 01:22:10,780 but you also want to set up extra registers here. 1920 01:22:10,780 --> 01:22:14,660 So if you're-- I think this basically has to-- sorry. 1921 01:22:14,660 --> 01:22:17,500 This has to do with setting that CS code descriptor 1922 01:22:17,500 --> 01:22:20,645 segment because you want to set the code descriptor 1923 01:22:20,645 --> 01:22:23,060 segment to this bounded segment, and you 1924 01:22:23,060 --> 01:22:25,789 want to jump to some particular address at the same time. 1925 01:22:25,789 --> 01:22:27,330 So I think it's easier for these guys 1926 01:22:27,330 --> 01:22:30,010 to do it through a springboard because you first sort of jump 1927 01:22:30,010 --> 01:22:30,640 to here. 1928 01:22:30,640 --> 01:22:32,436 Then you can set your CS value. 1929 01:22:32,436 --> 01:22:34,060 But you can still execute the same code 1930 01:22:34,060 --> 01:22:40,355 you're still running because you're within the 256 bound. 1931 01:22:40,355 --> 01:22:42,215 Makes sense? 1932 01:22:42,215 --> 01:22:44,500 I think basically it has to do with what 1933 01:22:44,500 --> 01:22:47,510 atomic primitives the hardware provides to you. 1934 01:22:47,510 --> 01:22:50,145 So basically, you want to set a whole bunch of these DS segment 1935 01:22:50,145 --> 01:22:52,644 selector registers and the CS register and jump to somewhere 1936 01:22:52,644 --> 01:22:53,870 at the same time. 1937 01:22:53,870 --> 01:22:59,560 So this is one way for them to do it. 1938 01:22:59,560 --> 01:23:02,330 I think that's maybe not as [INAUDIBLE]. 1939 01:23:02,330 --> 01:23:04,532 Probably, if you tried hard, you could probably 1940 01:23:04,532 --> 01:23:06,490 come up with some x86 instruction sequence that 1941 01:23:06,490 --> 01:23:10,039 could do it from outside the bound of the address 1942 01:23:10,039 --> 01:23:12,558 space in the module. 1943 01:23:12,558 --> 01:23:13,433 Makes sense? 1944 01:23:13,433 --> 01:23:13,932 All right. 1945 01:23:13,932 --> 01:23:17,212 So I guess that's it for Native Client. 1946 01:23:17,212 --> 01:23:18,580 And I'll see you guys next week. 1947 01:23:18,580 --> 01:23:21,630 We'll talk about web security as far as I know.