> Unfortunately, the lock-in they're creating will deprive people of the ability to vote with their feet and switch to better alternatives.
This might sound like a dumb question, and I'm not saying I agree with him, but if I did, I'd vote with my feet by... what? Don't most distros use it now? I'm genuinely curious if this is a practical option for me, though I'm not likely to do it.
It is interesting for more than just the use of runit...
For anyone else wanting to completely purge systemd from an Arch install, here is a good and thorough description; takes less than one hour to switch if you read it thoroughly, about ten minutes if you just do as it says in the code listings.
I'd submit that, in order to use systemd, you must have to give up the term "distro" to describe yourself.
With that in mind, there are only 5 distributions left:
1) Devuan
2) Slackware (including Slax)
3) Void Linux
4) Gentoo (including Calculate Linux)
5) systemd
If you wanted to vote with your feet, and wanted to keep .deb compatability, you'd move to Devuan. Otherwise, there are four other choices, two of which have LiveCD/LiveUSB install options.
This is not a correct description of what happened, note. Kay Sievers originally used 0 to represent an invalid value. Lennart Poettering changed this to -1, because 0 is clearly not an invalid value. The bug resulted because he missed changing one of the comparison-against-zero validity checks.
Yes, that's exactly the kind of mistake that happens when you use magic values to represent invalid values instead of distinct types.
M. Poettering was in fact doing the right thing and correcting the problem, replacing the unexplained constant literals written by M. Sievers ("mode > 0") with named constants ("mode != MODE_INVALID"). It is an example of the problem, one of whose symptoms is the question "Well which of these is the specific constant and which just happens to also be that number?", that M. Poettering missed a "mode > 0" that also needed replacing.
Make no mistake. M. Poettering was actually applying the long-time well-understood fix for this.
Here's Ted Holt talking about unexplained constant literals in RPG 4:
* https://www.itjungle.com/2004/08/18/fhg081804-story01/
This same problem, and the approach of turning unexplained literals into named constants to improve maintainability, is explained all over the place, from William Allan Wulf's Fundamental structures of computer science published in 1983, through Niklaus Wirth in the 1975 Proceedings of the IEEE Conference on Reliable Software and Clark and Horning in a SIGPLAN paper in September 1973, to several of Gary Cornell's books on QuickBASIC and Visual BASIC in the 1990s.
This is not a new thing, not language-specific, (clearly!) not addressed by changing language, nor addressed by types.
Is Systemd being coded with the same level of 'care' as OpenSSL was before being pwned?
Anyone who works on systemd is doing difficult work. We should treat these teams better and give them support rather than just brow-beat them for their mistakes.
The open syscall should reject unrecognized flags in the mode argument (EINVAL), rather than just truncating down to recognized flags. That would also prevent this specific problem with the sentinel value being used on accident.
* http://lxr.free-electrons.com/source/include/uapi/linux/stat...
* http://lxr.free-electrons.com/source/include/linux/types.h#L...
Here is the specific place where Linux truncates the bogus mode, instead of rejecting it: http://lxr.free-electrons.com/source/fs/open.c#L906
(S_IALLUGO defined here: http://lxr.free-electrons.com/source/include/linux/stat.h#L9 )
This change would fix this class of issue:
--- a/fs/open.c
+++ b/fs/open.c
@@ -889,9 +889,11 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
int lookup_flags = 0;
int acc_mode = ACC_MODE(flags);
- if (flags & (O_CREAT | __O_TMPFILE))
+ if (flags & (O_CREAT | __O_TMPFILE)) {
+ if ((mode & ~S_IALLUGO) != 0)
+ return -EINVAL;
op->mode = (mode & S_IALLUGO) | S_IFREG;
- else
+ } else
op->mode = 0;
/* Must never be set by userspace */This seems inaccurate. The phrase "strongly recommend" appears once in the manpage, where it is strongly recommended that you use either the standard libc resolver API, with libnss_resolve, or the D-Bus API.
Applications should be using the libc resolver API instead of implementing DNS themselves. There are some applications like Chrome that implement DNS themselves because they care very much about DNS; those applications presumably know how to do all the things systemd-resolved does. Everyone else should get name resolution functionality from libc. That's what you've been supposed to do for decades, and it's a standard UNIX interface. That standard interface supports things like LLMNR that you don't get if you implement DNS yourself.
Unfortunately, the standard UNIX interface is synchronous, which is why libraries like ares or adns exist. If you want to use such a library, you can point it at 127.0.0.53, but you still have the limitations of what can be expressed in DNS. (And you're still using a nonstandard API to speak to libares or libadns.) No API exists that is standard, async, and does everything that libc getaddrinfo() is capable of doing. So systemd built one.
That's pretty standard behavior for systemd: implement compatibility interfaces where they exist, recommend them if they're good (systemd explicitly recommends /etc/fstab over writing native mount units, because /etc/fstab is a perfectly good format), implement them anyway if they're not, and write a better API, based on D-Bus, when needed. The latter bit not going through a multi-implementer standards committee isn't great, but it's nowhere near as bad as presented.
Anyway, this is completely irrelevant to the rest of the analysis, which seems absolutely correct, and I'm not sure why the author included this parting shot.
It says:
- option 1 (recommended): use systemd-resolved API.
- option 2: use glibc API with a glibc NSS module to resolve host names via systemd-resolved.
- option 3 (not recommended): local DNS stub listener on loopback to connect direct request to systemd-resolved.
Author included this part to illustrate how the real issue is that systemd is an unprecedented lock-in. Honestly an init process implementing a DNS resolver? Where is my kitchen sink ?
Systemd is a project that manages a large number of low-level services and programs that work together to try to help create a cohesive operating system.
Systemd is also the name of a init program.
These have the same name, but are not the same thing.
Systemd init process does not provide any DNS resolver features. Systemd-resolved, however, does.
> The native, fully-featured API systemd-resolved exposes on the bus. See the API Documentation[1] for details. Usage of this API is generally recommended to clients as it is asynchronous and fully featured
They built an API that was async and does everything that getaddrinfo is capable of doing. They did not build an API that was standard. They did not build an API that even had the potential to become standard, because many systems do not use D-Bus, and they are not going to add it just for a slightly better DNS resolution API than what already exists.
What could they have done instead? Either or both of:
(1) Implement an extension to the DNS protocol that handles whatever extra bits they need. This is probably the best approach due to the multitude of applications that bypass libc already. Actually, I'm not convinced after reading the manpage that an extension is even necessary... what's the issue with link-local addresses? Can't they just have the DNS server on localhost synthesize records when needed? In fact, based on the rest of the manpage, aren't they already doing that? And what's the issue with Unicode? Can't they translate between DNS punycode and whatever encoding LLMNR uses?
But if an extension to DNS really is needed, it has the potential to be proposed as a standard and eventually become ubiquitous, whereas an ad-hoc replacement interface does not.
(2) (Worse idea, probably:) Propose a libc API that would be an async version of getaddrinfo with whatever enhancements are desired. Implement a portable polyfill library that either calls getaddrinfo on a thread or (if the API has extended functionality in addition to being async) uses their D-Bus stuff, depending on platform.
Admittedly, both options seem more fiddly and more work than 'just' adding some D-Bus calls. But when the existing story for name resolution is largely fully cross-platform, it seems like a bad idea to abandon that just for the sake of small improvements.
However, getaddrinfo is not a great inferface: you still can't use it to e.g. look up an MX record. For that you need res_query(3), which does not have an async interface in libc. Pottering himself wrote a library to use res_query in a separate thread http://0pointer.de/lennart/projects/libasyncns/.
However, I don't like threads, and will avoid them where possible in libraries (an example reason: I like to be in a defined state after fork()). Which means I need an async dns library that implements a resumable state machine. Lately I've been using http://25thandclement.com/~william/projects/dns.c.html
http://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/... https://github.com/OpenSMTPD/libasr
The fact that systemd keeps making decisions like this that are architecturally dubious and lead to lock-in is most certainly grounds for criticism.
The current NSS system works nicely though, it just needs an async API.
It's providing local name resolution services. And for very good reasons.
By your logic things like NSS is useless as well because programs themselves can read ldap configuration files and /etc/resolv.conf on their own using libraries or whatever else they feel like using.
Everybody loves kicking systemd as they re-invent various wheels; see... even I can't resist!
Anyway it is a local exploit on an old release, not a good thing but containable.
> 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.
> Rewriting systemd in a safer language would not transform it into quality software, ...