Skip to Content [alt-c]

Andrew Ayer


Thoughts on the Systemd Root Exploit

Sebastian Krahmer of the SUSE Security Team has discovered a local root exploit in systemd v228. A local user on a system running systemd v228 can escalate to root privileges. That's bad.

At a high level, the exploit is trivial:

  1. Systemd uses -1 to represent an invalid mode_t (filesystem permissions) value.
  2. Systemd was accidentally passing this value to open when creating a new file, resulting in a file with all permission bits set: that is, world-writable, world-executable, and setuid-root.
  3. The attacker writes an arbitrary program to this file, which succeeds because it's world-writable.
  4. The attacker executes this file, which succeeds because it's world-executable.
  5. The attacker-supplied program runs as root, because the file is setuid-root.

In mitigation: The vulnerability was fixed a year ago and less than three months after it was introduced. It is present only in v228.

In aggravation: The vulnerability was mislabeled at the time as a local denial-of-service and the systemd team did not request a CVE-ID for it. Had they requested a CVE-ID, someone may have noticed that this was more than a DoS. (Krahmer accurately points out that the systemd commit log is "really huge," which makes it hard to spot security-relevant commits.)

In mitigation: The vulnerability depends on a yet-unfixed hole in how Linux clears a file's setuid and setgid bits when writing to it. Systemd merely creates an empty setuid-root file. Gaining root requires writing to this file, and when a non-root user writes to a setuid-root file, the setuid bit is supposed to be cleared. halfdog found a clever way to circumvent this by tricking a root process into writing to the file instead. This is an extremely interesting vulnerability in itself and I can't wait to dive deeper into it.

In aggravation: The vulnerability would have been prevented if systemd used a fail-safe umask rather than setting it to 0, something I called out last September as evidence of systemd's poor security hygiene. A more sensible umask, such as 022, would have caused open to create the setuid-root file without world-writable permissions, preventing exploitation. However, systemd maintainer David Strauss rejected a safe umask with a completely illogical argument that shows his cluelessness over how systemd uses umask.

Lastly, this is yet another example of "The Billion Dollar Mistake": systemd was using a magic value (-1) to represent an invalid mode_t value, and C's type system did not prevent passing it to the mode argument of open. A language with a better type system, such as Rust or C++ (which has std::optional) can help prevent this kind of error.

That said, this is not about programming languages. Dovecot (among a handful of others) has demonstrated that adherence to good coding practices can produce secure software written in C. Rewriting systemd in a safer language would not transform it into quality software, although certain classes of bugs would likely be reduced or eliminated.

Rather, this is about lock-in. Systemd is introducing unprecedented lock-in to the Linux userspace. They are replacing previously-independent userspace services with ones whose development is controlled by the systemd project and which only work if systemd is PID 1. They are defining their own non-standard protocols and encouraging applications to use them. They have even replaced DNS with a dbus-based protocol, which they "strongly recommend" applications use instead of DNS. Sadly, the most recent version of Ubuntu ships with this travesty.

Systemd's developers have repeatedly demonstrated their poor judgment and unfitness to hold such responsibility. Unfortunately, the lock-in they're creating will deprive people of the ability to vote with their feet and switch to better alternatives.

Hi, I'm Andrew. I'm the founder of SSLMate, a service which automates your SSL certificate deployment. I also develop open source projects like git-crypt and titus.

I blog here about a variety of technology topics, including security, devops, IPv6, and reliable programming. If you liked this post, check out my other posts or subscribe to my Atom feed.

My email address is I'm AGWA at GitHub and @__agwa on Twitter.


The comments below are owned by whoever posted them. I am not responsible for them in any way.

Heh... The lock-in is from people that haven't a single damned clue about "mission critical" code from the beginning.

Lennart hasn't done a single project that wasn't troubled, painful, and didn't work so hot until he left it behind. Not PulseAudio, not Avahi, not systemd. He didn't really manage to get it "right" with his very first little project on the design front (You inject as much as 100 msec of latency into sound the perception level of human hearing...making games difficult to get right...just for starters)- and filled with design features that are...iffy to begin with. Network audio?

Avahi's overengineered but finally useful. Pulse is MOSTLY "good".

But that's in-spite of Lennart. And you're letting this man design and oversee coding that is very much and fundamentally mission critical is job one. They don't care because if it crashes and takes the whole OS with it, we'll just launch a new Container. Yes, this was all done to make containers easier and NOTHING ELSE. There's other ways, other answers to do that, but we're off letting Red Hat lock us in, yet again, into what is good for them and really solely them (ALSA was another example...OSS4, if we'd sorted out the licensing issues was superior and easier to work with, etc. But Red Hat jammed THAT down our throats as well...)

Well, some are working, rather than just bitching, on answers there, myself included.

| Posted on 2017-01-26 at 16:32:12 UTC by Reader Nobody of Import | Reply to This

My comment will be an off-topic criticism of systemd.

I don't understand why people still think of systemd as an init system, when it's not; in my opinion, systemd is a high-level kernel designed to run on top of a low-level kernel, which is Linux. The two projects may as well be merged into one, and then sensible people would just reinvent the old script-based init for practical reasons.

Systemd's developers have repeatedly demonstrated their poor judgment and unfitness to hold such responsibility. Unfortunately, the lock-in they're creating will deprive people of the ability to vote with their feet and switch to better alternatives.

There exist alternative distros in the form of Devuan and Slackware, so voting with feet is still possible.

Finally I'll leave this here, a list of things that systemd does (yet probably shouldn't):

| Posted on 2017-02-08 at 10:00:59 UTC by Anonymous | Reply to This

Post a Comment

Your comment will be public. If you would like to contact me privately, please email me. Please keep your comment on-topic, polite, and comprehensible. Use the "Preview" button to make sure your comment is properly formatted. Name and email address are optional. If you specify an email address it will be kept confidential.

Post Comment

(Optional; will be published)

(Optional; will not be published)

(Optional; will be published)

  • Blank lines separate paragraphs.
  • Lines starting with ">" are indented as block quotes.
  • Lines starting with two spaces are reproduced verbatim.
  • Text surrounded by *asterisks* is italicized.
  • Text surrounded by `back ticks` is monospaced.
  • URLs are turned into links.