Understanding Meltdown

January 12, 2018 1:43 pm

I've been trying to understand the Meltdown vulnerability that's been in the news lately (a vulnerability in Intel's CPU design allowing an attacker to obtain access to any data in memory on the system).  I understand it at a high level, but every time I've tried to dive into the details to understand an example it falls apart on me.  So I'm going to write this to force myself to fully dissect the parts I'm missing and maybe help someone else in the same boat.

This is not a post intended for a general audience.  I don't expect it will be meaningful or useful to anyone that doesn't already understand programming to some degree.

Eben Upton has a great write up over at RaspberryPi.org which will be the basis of my post.  I'm not going to recreate his work, but instead I'm going to dive into greater detail starting at "Putting it all together".

We start with his pseudocode:

t = a+b
u = t+c
v = u+d
if v:
   w = kern_mem[address]   # if we get here, fault
   x = w & 0b100           # * Modified, See Note
   y = user_mem[x]
* Modification Note:
The original was "x = w&0x100" which I've replaced with "x = w & 0b100".  0x100 is hexadecimal shorthand for the binary 000100000000.  I'm going to use an 8-bit example, so I'm replacing it with 0x4, since my example will only use binary I rewrote it to 0b100.  It is irrelevant to the method of the attack, only changed for convenience.

For those of us that spend our time on higher-level programming languages (like Java, Groovy, Python, JavaScript, etc.) the bit-twiddling needs a little more detail.  That detail is the remainder of my post.

Let's suppose we live in a 8-bit world for this example (mainly so I don't have to write out really long numbers that are irrelevant to the point I'm making).  In our 8-bit world each of our memory locations holds 8-bits.

Now, let's dissect Upton's pseudocode staring inside the "if":

w = kern_mem[address]   # if we get here, fault

This finds the 8-bits contained at "address" in a privileged part of the memory which we shouldn't be able to access, here called "kern_mem".

When the CPU sees us attempt to use that data, it will stop us (i.e., "if we get here, fault").  The crux of this vulnerability is that the CPU will fetch this information for us even though we're not allowed to see it; later it will realize we're not allowed to see it and stop us.  But we do something clever which lets us know what is in that memory even though we never saw it.

Those 8-bits from memory location kern_mem[address] are assigned to the variable "w", let's suppose those bits are 01010101.

w == 01010101 # A Number we're not allowed to see
-----
x = w & 0b100

This is a "masking" operation (think masking-tape when painting).  0b100 is the mask, which is shorthand for 00000100.  This line will "mask" out everything except 1 bit of "w".  The result will always either be 00000000 or 00000100; note that this is either all zeroes or the same value as the mask.  Since both the mask and "w" have 1 as the 3rd bit, the resulting value, in our example, will be 00000100 and assigned to the variable "x".

w == 01010101 # A Number we're not allowed to see
x == 00000100 # A single bit from that number
----
y = user_mem[x]

Now we're going to get the 8-bits contained at "x" in a piece of memory we are allowed to access, here called "user_mem".  "x" is the single bit from the-number-we-cannot-see.  In this case we'll get the 8-bits located at user_mem[00000100] and assign those 8-bits to the variable "y".

We don't care at all what the 8-bits from that location in memory actually are.  The important thing is that the memory system went and got them for us from main memory and loaded them into a local cache.  This process may have taken, say, 100ns.  Next time I ask for the 8-bits in user_mem[00000100] the memory system will say "Oh, I already have that in cache, here ya go" and it will only take, say, 3ns.  Keep this in mind.

w == 01010101 # A Number we're not allowed to see
x == 00000100 # A single bit from that number
y == we_dont_care # Cached value of user_mem[00000100]

These 3 things happen before the CPU realizes we're not allowed to see "w".  Once it makes that realization, it undoes the work so that "w", "x", and "y" no longer have these values so that we can't get to them (effectively at least).

So what good does it do us as an attacker if we can't actually get that data in "w" that we tried to access?

The memory cache still has user_mem[00000100] loaded in to it!

After tricking the CPU into doing this work for me I attempt to access user_mem[00000100].  I know to access user_mem[00000100] because 00000100 was the mask I chose (0b100).  I don't care at all what value is actually stored at user_mem[00000100].  I only care how long it takes to access: I note the current time, access the memory location, and then see how much time has passed.

If it takes ~3ns to access that memory, it must have been in the cache.  It would only be in the cache if "x" had been 00000100.  "x" would only have been 00000100 if the 3rd bit of "w" was 1.

I now know that "w" looks like ?????1??.  That was a lot of work for just a little bit of information (pun intended).  But CPUs are quick and this can all be happening without you being aware of it.  So, now let's repeat the process, but this time we'll change our mask:

w == 01010101 # A Number we're not allowed to see
-----
x = w & 0b10

The mask has been moved over one bit.  Because the 2nd bit of "w" is 0, "x" holds the 8-bits 00000000.

w == 01010101 # A Number we're not allowed to see
x == 00000000 # A single bit from that number
----
y = user_mem[x]

This time we get the 8-bits located at user_mem[00000000] loaded in to the cache.

w == 01010101 # A Number we're not allowed to see
x == 00000000 # A single bit from that number
y == we_dont_care # Cached value of user_mem[00000000]

This time the mask was 00000010, so we time how long it takes us to access user_mem[00000010].  This time it takes ~100ns, by which we determine that it must not have been in the cache.  That could only be true if "x" had been 00000000.  "x" could only have been 00000000 if the 2nd bit of "w" had been 0.

Now we know that "w" looks like ?????10?.  Keep doing this over and over again and we can read any data we like, we just have to piece it together.

Is it not a strange fate that we should suffer so much fear and doubt for so small a thing? So small a thing!

-- Boromir, "The Fellowship of the Ring"

Like Sauron's One Ring, this truly is a small thing, but will bring about much pain and anguish.

One [Flaw] to bring them all and in the darkness bind them.

Undermining the Credibility of an Investigation - A Game-Theoretic Analysis

January 3, 2018 10:21 am

Let's suppose you were the subject of a serious criminal investigation.  Further suppose you were also a prominent and influential public figure.  You know a priori whether there's anything damning that the investigation may find.  Should you choose to use your influence to affect the credibility of the investigation?  Should you bolster the credibility or undermine it?  Let's take a game-theoretic approach.

Like almost all game theory analyses we'll construct a payoff matrix to guide our analysis.  I suggest one axis capture the eventual outcome of the investigation: evidence of wrongdoing found (guilty) vs. no evidence of wrongdoing found (innocent).  The other axis will capture the subject's three possible actions regarding using their influence: bolster credibility (bolster), do nothing (null), undermine credibility (undermine).

Payoff matrix for subject using influence to affect credibility of investigation - Empty
Bolster Null Undermine
Innocent
Guilty

We now need to consider each possibility in the matrix and assign a relative payoff.  The payoff value represents the utility of the scenario to the subject, that is, how much does the subject benefit based on the scenario represented by each cell.

I don't think it's particularly controversial to argue that any "Innocent" outcome will be good for the subject.  Better if the credibility has been bolstered, but slightly worse if the credibility is undermined.

Payoff matrix for subject using influence to affect credibility of investigation - Partial
Bolster Null Undermine
Innocent 20 10 7
Guilty

Again, it shouldn't be controversial to assume that a "Guilty" outcome will be bad for the subject.  Worse if the credibility is bolstered, but slightly better if the credibility is undermined.

Payoff matrix for subject using influence to affect credibility of investigation - Complete
Bolster Null Undermine
Innocent 20 10 7
Guilty -20 -10 -7

At a global view, it seems like the only reason to actively undermine the credibility of the investigation is if you believe the outcome will be "Guilty" as it will increase your utility.  That should be concerning to anyone paying attention to current U.S. politics.

I think there is one potential argument for modifying the "Undermine" payoffs.  If the undermining is an attack on the biases and motivations of the investigation, the supporters of the subject may see an "Innocent/Undermine" outcome as better than "Innocent/Null" because "even the biased investigation couldn't find anything."  A similar argument could be made about the "Guilty/Undermine" payoff.  The increased nuance becomes important if you think that the subject's actions are more directly tuned to either the supporters or opposers.

Payoff matrix for subject using influence to affect credibility of investigation - Supporters/Opposers
Bolster Null Undermine
Supporters Opposers
Innocent 20 10 14 0
Guilty -20 -10 0 -14

These supporter/opposer payoffs are probably up for much debate, but I think this is probably a good ballpark.

With an "Innocent/Undermine" outcome, opposers will use the attacks on the credibility of the investigation against the subject.  But, supporters will see it as stronger evidence of innocence ("even the biased investigation couldn't find anything").

With a "Guilty/Undermine" outcome, supporters will see it as "proof" that the investigation was biased and not valid.  Opposers will see it as an attempt to evade justice.

What's interesting is if the subject cares only about supporters then the only better possible outcome than undermining the investigation is to bolster an investigation that finds the subject innocent.  If the subject, knowing a priori the truth of their actions, believes that the likelihood of the investigation concluding "Innocence" is almost zero and cares most about their supporters' response then undermining the investigation becomes overwhelmingly the best action to take.

Does the President care so little about those who oppose him that he's willing to take another hit from them in the event that the Mueller investigation finds nothing?  Or is he expecting the investigation to find evidence of wrong-doing and he's laying the groundwork to salvage the only group possible?  Or is my analysis completely wrong?

Solar Eclipse 2017

August 21, 2017 8:10 pm

We had fun watching the eclipse today.  Livermore had ~75% occlusion at peak.  It was also Heather's first day of school (separate post coming).  They took the kids outside to watch pinhole cameras and then let them use eclipse glasses one-at-a-time so they could ensure they were being worn properly.

Heather helped me make eclipse cookies yesterday.

My sugar cookie skills could use some work...

Corinne got a kick out of the eclipse proclaiming, "Moon! I see the moon!" (by which she, of course, meant sun).

We used the colander to get pinhole-camera-style shadows.

And I had my camera set up with filters taking pictures.  I just kind of guessed at settings.  Some came out better than others.  Here's the picture from the peak eclipse:

And here's one I got as it was ending where you can see a line of spots.  I don't know if they're technically sunspots, but they weren't just dust on my lens--they stayed with the sun throughout the event.

My weather station noticed the eclipse too:

The variations in the readings are due to varying cloud cover that, thankfully, almost completely cleared out during the eclipse.

The temperature even dropped a hair:

10 Years with a 2007 Honda Civic LX

July 9, 2017 2:56 pm

I got my 2007 Honda Civic LX in April 2007.  It's now just over ten years old and going strong.  I just passed 90,000 miles.  I fully expect it to keep going for another 10 years, though I may decide to swap it for an electric vehicle before it's totally worn out.

In 10 years I have had zero issues in terms of reliability or mechanical functionality.  It has received all services as scheduled by the built-in "Maintenance Minder" system.  It is on its third set of tires, its second set of brake pads, and its third battery (all counts include the factory-installed items).

Efficiency has been consistent though it appears to be slowly dropping, but that might be a false interpretation of the data as, since we bought the Odyssey, the Civic no longer goes on long trips and has none of the up-ticks in efficiency gained from long highway traveling.

The lifetime efficiency is 29.86 miles-per-gallon (total miles traveled divided by total gallons of gas consumed; not the average of the per-tank efficiencies).

The amount of driving I've done with the Civic has been quite consistent over the years.  You can see some areas of rapid increase which signify long car trips driven over just a few days or weeks.

Overall, it has been a great car, though not without some minor annoyances.

The minor annoyances

A few of the LED segments on the speedometer display flicker, especially in hot weather.  Probably a weak piece of solder or something that becomes inconsistent in the heat.  Slightly annoying, but not a big deal.

The driver-seat height adjustment seems to slowly sink back down.  The height adjustment is a pneumatic system (as far as I can tell) that I think slowly leaks out the air pressure and causes the seat to drop back down to the bottom.  I usually pump it back up once a month or so and I only move it up a centimeter or two so it's not a big deal.

The driver-side window auto-retract system is overeager.  That's the system that prevents you from closing the window on an object when you use the "auto close" feature by pulling the switch all the way up.  The window will reach about an inch from closing and then retract back down.  Holding the switch overrides the auto-retract system.  So, again, slightly annoying, but not a big deal.

Honestly, those three things are the only functionality issues with the entire vehicle.  No mechanical issues, just minor annoyances.

Here I'm excluding recall work which could have affected the vehicle's reliability/safety, but was corrected for free and a priori to any incident.  The only particularly notable ones have been the possibly faulty O-ring on a speed sensor which may cause wheel failure and the faulty airbag inflater (part of the Takata recalls).  Both of which were corrected without issue.

The paint problem

The biggest problem with the car has been paint failure.  Several years ago Honda issued a voluntary recall due to an identified issue with paint longevity, but I misread the notice and missed the window to have them pay for some repainting.  Which may be somewhat moot.  The recall was for paint failure on the hood, roof, and trunk--which I had in great quantity--but I also had paint failure on the door panels and fenders.  I'm sure part of the problem was my not regularly cleaning and waxing the car, but even so, the paint should have held up better (which Honda admits).

In anticipation of owning the Civic for another 10 years I decided to get it repainted to both protect the metal and so it doesn't look terrible.

The first picture does not do a good job of exposing the differences from before (top) to after (bottom):

But once we start looking at the details it becomes obvious.  Left is before, right is after.

Top is before (obviously), bottom is after:

Here's to another 10 years!

The Weather in our Kingdom

June 17, 2017 9:50 pm

Jess got me a weather station for my birthday which is now installed up on the roof:

The unit is an Ambient Weather WS-1400-IP.  It reports temperature, humidity, wind speed, wind direction, rainfall, solar radiation, etc.  It comes with an indoor unit that also reports inside temperature and humidity.

The data is sent to wunderground.com and you can find it here: https://www.wunderground.com/personal-weather-station/dashboard?ID=KCALIVER107

But, wunderground can be a little flaky, so I'm also capturing the data into my own database and serving it up.  On the sidebar of the blog you can find a widget that looks like this:

I'm using the "Weather Station" WordPress plugin to read a Cumulus-style file.  Now, the Ambient Weather ObserverIP unit does not produce the Cumulus "Realtime.txt" file that the WordPress plugin needs.  But, I have programming super powers.  So I wrote a shim that scrapes the data from the ObserverIP web interface and writes out a "Realtime.txt" file that I serve up for the WordPress plugin.

I also write out a human-readable page with the weather data on it you can see here: http://weather.serindu.com/

It's not very pretty right now, but it's up and running, updating every 5 minutes.  I'll get around to improve the aesthetics at some point.

Having the indoor and outdoor sensors I'm thinking I'll have to write up something that will notify me when the temperatures outside and inside cross so I'm alerted to open or close the windows as appropriate.  But I haven't got that far yet.

The shim I wrote to put all these pieces together is available on GitHub: https://github.com/kdickerson/weather

It's just a Python script set to run every 5 minutes via Cron.  It scrapes the data off the ObserverIP unit, formats it and inserts it into the SQLite database, computes daily high/low values from the stored data, and writes Realtime.txt and index.html into a folder being served by Apache.