
Systemd v228 local root exploit - papey
http://www.openwall.com/lists/oss-security/2017/01/24/4
======
implr
>We would like to see that systemd upstream retrieves CVE's themself for their
own bugs, even if its believed that its just a local DoS.

So not only they didn't notice this was exploitable, they also seem to think
that a local DoS is not enough for a CVE or a public report. Excellent.

~~~
bkor
CVE is an invite only system, applied to just a few projects. See e.g.
[https://cve.mitre.org/cve/data_sources_product_coverage.html](https://cve.mitre.org/cve/data_sources_product_coverage.html).
Generally you need to know someone to get such an id.

If you have a bug in some github project you cannot request a CVE for that. If
a CVE is reported you'd usually include that in the commit. But that's not the
same as every security bug should have a CVE. Often way easier to just fix
bugs instead of figuring out if it is a security bug (=method Linus uses).

~~~
berdario
I don't know any insider, but obtaining a CVE was not really difficult:

[http://seclists.org/oss-sec/2016/q3/231](http://seclists.org/oss-
sec/2016/q3/231)

(and it was not even my project... I just reported the bug)

Now the workflow changed a bit, in the link that you shared in fact it says
"For open source software products not listed below, request a CVE ID through
the Distributed Weakness Filing Project CNA." which is just an easy-to-fill
Google form. Not such a close system as you seem to imply

(OTOH, obviously CVE cannot guarantee or pretend to have universal coverage of
every security issue ever existed)

I generally like systemd, but it's irresponsible to not publicly communicate
about such an issue if you're aware that it's actually a security issue

fix bugs before investigating, that's ok... but not communicating it means
that you'll leave users downstream exposed to it, since it won't prompt
maintainers to ship the patch/upgrade

~~~
bkor
If you go to [https://cve.mitre.org/](https://cve.mitre.org/) it has a link
"Request a CVE ID" which IMO explains that it is only for some products, not
all. Alternatively there's also a weblink below it which want GPG key, etc.
Alternatively you can email some mailing list, but I don't see where this is
documented.

The complaint was that the CVE should've 1) been included in the commit 2)
been made. IMO the entire thing is confusing.

Also like to repeat: it's super nice that things are reported and have a CVE.
But that doesn't mean every security commit will be seen as related to
security.

I'm pretty sure I've seen enough interesting commits in gdk-pixbuf:
[https://git.gnome.org/browse/gdk-
pixbuf/commit/?id=49dcd2d58...](https://git.gnome.org/browse/gdk-
pixbuf/commit/?id=49dcd2d58ec3695f858c1db003851bd944a14f05)

------
kogepathic
> "new services as a service"

Accurately describes systemd's development over the past few years.

------
api
Local security on Linux is completely forfeit. It's a single user OS. Anyone
with access has root. There's just too much surface area between all the
different subsystems and nobody's been paying much attention to local security
for a very long time.

I've thought for a long time that containers and even virtualization are kind
of a parody of this. They shouldn't be necessary. If the OS had good multi-
tenancy, resource control, and local security you could have multiple tenants
(even untrusted ones!) on the same "box" without requiring any of those layers
of complexity.

------
bandrami
Why does systemd implement touch(1) as a library function? Isn't the whole
point of coreutils to keep stuff like that centrally maintained so we don't
have a million different (and possibly broken) implementations of it?

~~~
loeg
Fork and exec is an absurdly expensive way to implement what is essentially
open().

You might instead ask, why doesn't coreutils provide a libcoreutils, with
touch(1) a thin shim around that? And then systemd could use that.

~~~
bandrami
Sure, security has performance costs, but I don't think an init system (whose
job, ultimately, is to fork and exec a lot of things) is going to be harmed by
it.

And, anyways, if you had a libcoreutils, suddenly you're stuck worrying about
symbol versions, LD_PRELOAD, etc., etc., whereas simply executing the binary
is pretty simple.

~~~
ajross
> I don't think an init system (whose job, ultimately, is to fork and exec a
> lot of things) is going to be harmed by it.

The performance overhead of the script-heavy init system that preceded it is
in fact one of the core design points of systemd. Boot time still matters in
some environments, and the old init scripts were completely out of hand.

~~~
JdeBP
> _the script-heavy init system that preceded it_

... was the non-shell-script upstart on at least two major operating systems,
for quite a few years.

* [http://uselessd.darknedgy.net./ProSystemdAntiSystemd/](http://uselessd.darknedgy.net./ProSystemdAntiSystemd/)

* [http://blog.darknedgy.net/technology/2015/09/05/0/](http://blog.darknedgy.net/technology/2015/09/05/0/)

~~~
ajross
Poeterring works for Red Hat and it was written on Fedora. Yes, Ubuntu had
something else. I don't see how that's relevant to a discussion of systemd's
design goals.

~~~
JdeBP
Fedora was one of those two systems, using upstart since Fedora 9. If you are
going to participate in a systemd discussion, you should know what you are
talking about, lest you once again (as indeed you are) promote the _There Is
Only System 5 init And systemd_ fallacy. Read the Uselessd Guy's articles
already pointed to. Read the Debian Hoo-Hah where there were _four_ choices.
Read Lennart Poettering's own explanation, widely published a couple of years
ago now, of how upstart was the motivator.

------
mangix
Fun fact: the person who fixed this is an Arch Linux developer. The whole
issue based on the commit seems like an oversight (thinking mode_t is signed).

This doesn't appear to be malicious in any way. Note that many apps have sign
issues like these, with the difference being that it's not enough to give
root.

------
dijit
I do not doubt that issues like this will become more common in future. Code
quality/clarity is nearing that of OpenSSL.

------
belorn
v228 is too new for Debian stable. Unstable had a update on feb 11, 2016.

Ubuntu never ran with such early version, since their first uploaded version
was 229.

~~~
lclarkmichalek
If you are on a systemd system, you can check your version with

    
    
        $ init --version
        systemd 231
        +PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT -GNUTLS -ACL +XZ -LZ4 +SECCOMP +BLKID -ELFUTILS +KMOD -IDN

~~~
mhotchen
Despite being in the man page, the flag --version didn't work for me on Ubuntu
16.04 (various different installations):

    
    
        $ init --version
        init: unrecognised option '--version'
    

systemd --version works though:

    
    
        $ systemd --version
        systemd 229

~~~
ilkkao
systemctl --version on Fedora

~~~
tonyhb
Same thing on Nix. Thanks.

------
baq
here's the fix:
[https://github.com/systemd/systemd/commit/06eeacb6fe029804f2...](https://github.com/systemd/systemd/commit/06eeacb6fe029804f296b065b3ce91e796e1cd0e)

questions to the local experts:

1) would using a differently designed open() api prevent the issue?

2) would not using C to write systemd prevent the issue? specifically, would
using rust, ocaml, ats or ada prevent the issue?

~~~
benmmurphy
2) maybe. mode_t is unsigned and MODE_INVALID was defined as: #define
MODE_INVALID ((mode_t) -1) and the problem was in a check: fd = open(path,
O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);

so maybe the author thought MODE_INVALID < 0\. though, maybe safe languages
will let you do this explicit cast as well so maybe they won't save you.

the other thing is maybe in a safe language you would use an Option/Maybe type
here instead of a plain mode_t type.

~~~
JdeBP
It wasn't really anything to do with the language, and far more to do with the
operating system kernel API.

The fchown() system call supports passing -1, cast to the appropriate type, as
a no-op value. The systemd people were attempting to wrap similar semantics
around fchmod(). Originally in 2014 M. Sievers specified (mode_t)0 as the no-
op value, which wasn't a good choice, with M. Poettering changing it to
(mode_t)-1 in 2015 but overlooking one place where the value remained tested
against 0.

* [https://github.com/systemd/systemd/commit/c38dfac9ed6c1c3beb...](https://github.com/systemd/systemd/commit/c38dfac9ed6c1c3beb3dd88ebf82a13d1e561ff8#diff-17b65efc8e12341f488ffdf9b5f52840R3388)

~~~
JdeBP
Incidentally: M. Sievers' original choice of (mode_t)0 as a no-op value lives
on to this day in systemd-udevd.

* [https://github.com/systemd/systemd/blob/v232/src/udev/udev-r...](https://github.com/systemd/systemd/blob/v232/src/udev/udev-rules.c#L2527)

------
zakk
> mode_t is unsigned, so MODE_INVALID < 0 can never be true.

Wouldn't GCC complain about a comparison which is always true?

~~~
twoodfin
benmmurphy's comment below points out that the flawed test was "mode > 0".

[https://news.ycombinator.com/item?id=13470516](https://news.ycombinator.com/item?id=13470516)

~~~
zokier
I'd still expect GCC to warn about that

~~~
0xffff2
Warn about what? "mode > 0" is _not_ always true.

~~~
twoodfin
Eh, I feel like I've seen even pickier static analysis warnings. If the next
-Wall told me I should rewrite this as "mode != 0" to confirm the intent, that
wouldn't seem crazy to me.

------
Esau
It's a shame that SystemD, has this issue. Hopefully, once the fix is made,
they can get back to the business of obfuscating the init process.

~~~
jwilk
> SystemD

[https://lists.debian.org/878ttl9go6.fsf@hope.eyrie.org](https://lists.debian.org/878ttl9go6.fsf@hope.eyrie.org)

~~~
JdeBP
Same subject, same mailing list, two months earlier:

* [https://lists.debian.org/debian-devel/2016/08/msg00547.html](https://lists.debian.org/debian-devel/2016/08/msg00547.html)

~~~
rconti
Well, now I guess I know how I should write SystemD going forward!

------
tinus_hn
Why does systemd have functionality to create files as root for unprivileged
users anyway? What's the point?

~~~
djsumdog
I don't like systemd, but for the benefit of the doubt. One of the dangerous
lines of code is in a touch_file function:

[https://github.com/systemd/systemd/blob/ee735086f8670be1591f...](https://github.com/systemd/systemd/blob/ee735086f8670be1591fa9593e80dd60163a7a2f/src/basic/fs-
util.c)

..and most init systems do have a legitimate use case for touching a file.

~~~
bandrami
If only UNIX provided an existing utility to do that...

~~~
xena
So you want pid1 constantly calling out to userland binaries to do basic
filesystem manipulation tasks?

~~~
bandrami
Well, _I_ want PID 1 to make exactly one userland binary call and then start
reaping orphans. I want that PID 2, the RC system, to read some configuration
file(s) and, yeah, fork and exec a bunch of userland binaries. It's kind of
the whole point, right?

~~~
bonzini
What's the advantage of such an architecture?

~~~
bandrami
The advantage is that the kernel panics if PID 1 ever crashes, so I want PID 1
never to crash or even be able to crash. It also means I want the binary to
have as little of an attack surface as possible, and particularly I don't want
it listening to dbus or having links to a QR generation library.

This is a solved problem with multiple good solutions [1] [2] [3], so I can
easily avoid those issues by not using systemd.

[1]
[http://www.gnu.org.ua/software/pies/](http://www.gnu.org.ua/software/pies/)

[2] [http://universe2.us/epoch.html](http://universe2.us/epoch.html)

[3] [http://core.suckless.org/sinit](http://core.suckless.org/sinit)

~~~
bonzini
So add a signal handler that just enters an endless loop. That's what systemd
does, so as not to panic the kernel on a crash.

By the way, systemd doesn't listen to dbus (it uses the dbus protocol for IPC)
and does not link to a QR generation library (journalctl does, which is your
usual unprivileged program).

