Thursday, 14 December 2017

rr 5.1.0 Released

This is a minor maintenance release. It fixes a few issues that showed up in Ubuntu 17.10 and Fedora 27, such as glibc switching to the openat system call which then had to be supported by rr's syscall buffering for good performance. info proc maps works in gdb during rr replay now. Of course various other bugs were fixed.

One interesting thing about this release is that it's the first to have guaranteed backward compatibility with an earlier release: traces made by rr 5.0.0 should be replayable in rr 5.1.0 (and any later release, I hope).

Saturday, 2 December 2017

Maintaining An Independent Browser Is Incredibly Expensive

Mozilla's revenue increased to over $500M in 2016. Good for them! Some people have asked why all that money, and Mozilla's 1,200-ish staff, are needed just to build Firefox.

In practice building and maintaining a truly independent browser is incredibly expensive. (By truly independent, I mean a browser with its own implementation of HTML, CSS, JS, etc; this kind of independence is critically important to the open Web, and the world, and hence Mozilla's mission.)

Why is it so expensive? First you have to do the obvious stuff: implement the client browser engine and interface. Web standards are vast and complicated and ever-evolving, so this is a vast and complicated task. For this kind of security-critical, long-lived software in an intensely competitive mass market, you have do a very high-quality job, paying attention to all the various "ilities" — security, compatibility, performance, portability, accessibility, internationalization, maintainability, and so on. But also these days a large server-side investment is needed: downloads, updates, addons, crash collection, telemetry, push notifications, sync, and so on. Then you have to support all your developers with CI, massive test infrastructure, analysis and viewing of crash and telemetry data, etc. You also support your developers by writing custom tools and improving open-source tools; for example the rr project was born at Mozilla to improve life for Mozilla's C++ developers.

If you care about the open Web standards you're implementing, then your people need to spend time doing standards work. Since you have an independent engine you need to constantly evangelise Web developers and manage other external relationships.

If you want to stay competitive for the long term you need something like Mozilla Research, building stuff like Rust and Servo to explore technology that may give you a competitive edge in years to come.

Your product needs to be in the hands of users to be relevant, so you need marketing, distribution, events and other kinds of user outreach.

Then of course you have all the people needed to let the above people do their work effectively — HR, PR, lawyers, accountants, logistics, office managers, personnel managers, executives, and so on.

I worked at Mozilla for a long time. Over the last five years headcount was at about the quoted level, even during the FirefoxOS years. We were constantly butting up against headcount limits, having more work than we had people to do it. 1,200 people is barely enough. In the future it might not be enough.

Of course if you're willing to give up on engine independence you can save a lot of those expenses by adopting another vendor's engine, probably Chromium, and drafting off Google's investment. It's no surprise that for-profit companies would take that path, and that only Apple and Microsoft, companies with deep pockets and deep fear of Google, have declined to do so (though even Microsoft has caved on Android). Of course, using the same engine as Chrome limits your options for competing against Chrome, but it's tough to argue that those extra options are worth more than the cost. This is one reason among many why Mozilla is so important: it's Mozilla's mission that justifies the costs of maintaining an independent browser engine.

Friday, 24 November 2017

In Praise Of Rust's structopt For Command Line Parsing

I've built a lot of command-line tools over the years, mostly in C or C++, but also in Java, Python, Rust, Turbo Pascal, etc. I mostly rolled my own command-line parsing because I did not find getopt very useful, and in most of those languages importing third-party libraries is more effort than reward for such a relatively simple task. In Rust I used the clap library because it provides more functionality (e.g. useful help text) at a lower cost (Rust makes managing library dependencies so easy). I recently discovered structopt and tried it out. Finally, the one true way to parse command-line options!

With structopt you provide a Rust data structure defining a simple AST for your command-line options. You mark it up with structopt-specific attributes describing more details of the syntax, e.g. option names. Markup is minimized using sensible defaults and leveraging Rust conventions: doc-comments are used as help text, Option makes arguments optional, subcommands use enums, value are parsed using the FromStr trait, etc. Then structopt generates code (using Rust's "custom derive") that parses the command line options into your data structure. It uses clap underneath so you get helpful error messages, support for generating shell completion scripts, etc. But unlike using clap directly, you get the final parsed results which you can use from Rust code in a completely natural way, e.g. using match on subcommand enums. It's beautiful. It also has practical advantages for maintenance: for example, unused arguments are unused fields and produce compiler warnings. Take a look at the examples.

This is a special case of deserialization. A lot of programming is serializing and deserializing, and we have also used Rust's serde library to great effect. There must be more opportunities to use Rust custom-derive to implement DSLs for specialized serialization and deserialization problems.

Monday, 20 November 2017

Tararua Southern Crossing

I spent three days last week hiking the Tararua Southern Crossing in the Tararua Ranges north of Wellington with one of my children, and had a great time!

On the first day we took the train from Wellington city up the coast to Waikanae on the Kapiti Coast, then were driven east into the ranges, to Otaki Forks where the track starts. It took about five hours to walk to Kime Hut, at about 1400m — an altitude gain of about 1200m. From there we watched a spectacular sunset over the northern end of the South Island, which was wholly visible from the Marlborough Sounds in the west to the Kaikoura Ranges in the east. Kime has no heating and has a reputation for being cold, but it was upgraded in 2014 and although there was a hard frost outside, we were fine sleeping in our clothes inside our sleeping bags.

The next day we hiked over "the tops" — semi-alpine terrain above the tree line. This area is notoriously windy and potentially dangerous in bad weather, but the weather was fine and the wind tolerable. The DoC office had warned us not to take the route if the wind forecast for Powell Hut further north was 50km/h or higher, and I was able to download a fresh forecast in the morning from near Kime Hut which forecast 35km/h. In some places, notably the south side of Mount Hector, the wind was a little unnerving, but it was never a real problem. In places the track is narrow with steep drops on both sides, and although I'm generally not good with heights, I was fine just keeping my eyes on the track; wielding a couple of hiking poles helped. We were cautious and it took us about five hours to reach that day's destination, Alpha Hut. Along the way we had spectacular views from the Kapiti Coast in the west, around to the Hutt Valley, Wellington, and snow-capped peaks in the South Island to the south, and over to the Wairarapa valley in the east. It was a wonderful day.

The final day was a long walk through the bush along the Marchant Ridge down to rural Kaitoke. It took us about eight hours of walking, after which we had a taxi take us to Upper Hutt and then a train back to Wellington. It's a bit of a slog, but has more good views and generally fun. I tripped on a root near the end and banged my knee, which is still sore a few days later, but so it goes.

I'd never been tramping in the Tararuas before, and from the visitor books it looked like most trampers in this area are locals. I'm glad I got a chance to try it. We were lucky that the weather was excellent; it's often wet and/or foggy. Although the area between Kime and Alpha is classed as a "route" and most of the rest is "tramping track" grade, we found almost all the track well-defined and in good condition, though a lot of stepping up and down rocks and tree roots is required!

After the tramp we met up with the rest of the family for a couple of days in Wellington, in particular to visit the World War I exhibitions at Te Papa museum and the Dominion Museum. They are excellent, though required a significant amount of more walking which probably didn't help my knee.

Sunday, 29 October 2017

Auckland Half Marathon 2017

Not as good a time as last year, but OK. I seemed to run out of steam a bit towards the end this year; I'm not sure why. Maybe I pushed too hard too early, or just had a bad day. I should try running more fast 10Ks in the lead-up next year.

I followed Alfredo's advice to reduce the wear on my bare feet by sticking some small pieces of climbing tape to the balls of my feet. It worked really well. The tape almost entirely wore off during the race, and my feet didn't feel any different while I was running, but the skin didn't wear away. In experiments on training runs I discovered that strips of tape parallel to the side of the foot work better than strips across the foot because in the latter case, the flexing of the foot seems to pull the tape off.

Thursday, 19 October 2017

Microsoft's Chrome Exploitation And The Limitations Of Control Flow Integrity

Microsoft published an interesting blog post about exploiting a V8 bug to achieve arbitrary code execution in a Chrome content sandbox. They rightly point out that then even if you don't escape the sandbox, you can break important Web security properties (e.g., assuming the process is allowed to host content from more than one origin, you can break same-origin restrictions). However, the message we're supposed to take away from this article is that Microsoft's CFI would prevent similar bugs in Edge from having the same impact. I think that message is basically wrong.

The problem is, once you've achieved arbitrary memory read/write from Javascript, it's very likely you can break those Web security properties without running arbitrary machine code, without using ROP, and without violating CFI at all. For example if you want to violate same-origin restrictions, your JS code could find the location in memory where the origin of the current document is stored and rewrite it to be a different origin. In practice it would quite a lot more complicated than that, but the basic idea should work, and once you've implemented the technique it could be used to exploit any arbitrary read/write bug. It might even be easier to write some exploits this way than using traditional arbitrary code execution; JS is a more convenient programming language than ROP gadgets.

The underlying technical problem is that once you've achieved arbitrary read/write you can almost completely violate data-flow integrity within the process. As I recently wrote, DFI is extremely important and (unlike CFI) it's probably impossible to dynamically enforce with low overhead in the presence of arbitrary read/write, with any reasonable granularity.

I think there's also an underlying cultural problem here, which is that traditionally "Remote Code Execution" — of unconstrained machine code — has been the gold standard for a working exploit, which is why techniques to prevent that, like CFI, have attracted so much attention. But Javascript (or some other interpreter, or even some Turing-complete interpreter-like behavior) armed with an arbitrary memory read/write primitive is just as bad in a lot of cases.

Sunday, 15 October 2017

"Slow To Become Angry"

James 1:19-20

My dear brothers and sisters, take note of this: Everyone should be quick to listen, slow to speak and slow to become angry, because human anger does not produce the righteousness that God desires.

Online media exploit the intoxicating effects of righteous anger to generate "engagement". But even — or especially — when the targets of one's anger richly deserve it, becoming a person whose life is characterized by anger is contrary to God's will.

Something to remember when I'm tempted to click on yet another link about some villain getting what he deserves.