[systemd-bugs] [Bug 80537] New: sysv-generator implements 'wants' relationships backwards: "wanted" service ends up depending on "wanting" service

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Wed Jun 25 13:54:09 PDT 2014


https://bugs.freedesktop.org/show_bug.cgi?id=80537

          Priority: medium
            Bug ID: 80537
          Assignee: systemd-bugs at lists.freedesktop.org
           Summary: sysv-generator implements 'wants' relationships
                    backwards: "wanted" service ends up depending on
                    "wanting" service
        QA Contact: systemd-bugs at lists.freedesktop.org
          Severity: critical
    Classification: Unclassified
                OS: All
          Reporter: awilliam at redhat.com
          Hardware: All
            Status: NEW
           Version: unspecified
         Component: general
           Product: systemd

This was discussed downstream in Fedora Rawhide:
https://bugzilla.redhat.com/show_bug.cgi?id=1112908 (and previously on a
mailing list thread). Myself and Bruno Wolff noted that remaining sysv services
on our systems seemed to be being started, even though we had not explicitly
enabled them and they did not appear as SXX(service) symlinks in /etc/rc*.d/
(which is what indicates them as 'enabled' so far as SysV is concerned).

I noticed that the affected services seem to appear in
/run/systemd/generator.late/network-online.target.wants , and traced things out
from there.

I found that if a file in /etc/init.d contains an LSB stanza like:

# Required-Start: $network

then, on boot, there will be a symlink to the sysv-generator converted service
in /run/systemd/generator.late/network-online.target.wants . (This also applies
to Should-Start and I think to NetworkManager-wait-online - I think this will
be triggered by anything considered to match SPECIAL_NETWORK_ONLINE_TARGET in
sysv-generator around line 515).

Poking through sysv-generator.c , I believe I figured out what's going on here.
What it's actually trying to do is the converse: to implement the "service
wants the network to be up" dependency expressed by "Required-Start: $network"
or similar, create a symlink to network-online.target in foo.service.wants/ .
But the argument ordering is wrong for at least *this* case.

generate_unit_file() does this, for s->wants relationships:

        STRV_FOREACH(p, s->wants) {
                r = add_symlink(*p, s->name);
                if (r < 0)
                        log_error_unit(s->name, "Failed to create 'Wants'
symlink to %s: %s", *p, strerror(-r));
        }

At least in the affected case, it's basically calling add_symlink(wanting
service,wanted service) . but the logic of add_symlink() is
add_symlink(from,to), so it winds up creating a symlink from wanting.service to
wanted.service.wants/wanting.service - making wanted.service depend on
wanting.service, exactly the opposite of what we want.

So, I wrote a patch to fix that, by simply inverting the order of the
add_symlink() parameters:

                r = add_symlink(s->name, *p);

but I found a couple of problems. This gets the logic right for the affected
case, but still doesn't actually work, because it winds up creating a symlink
like this:

/run/systemd/generator.late/plague-server.service.wants/network-online.target
-> /run/systemd/generator.late/network-online.target

it should point to /lib/systemd/system/network-online.target , but it's not
smart enough to realize that. I also realized that sysv-generator uses the
generate_unit_file() wants stuff in two other cases, and for at least one of
those, the ordering is correct. e.g. I create a symlink:

/etc/rc3.d/S50foo -> /etc/init.d/foo

So setting the service foo to be 'enabled' for runlevel 3, in sysv language.
Now when I boot, sysv-generator creates:

/run/systemd/generator.late/runlevel3.target.wants/foo.service ->
/run/systemd/generator.late/foo.service

that's using the same bit of generate_unit_file(), but for *this* usage, the
ordering is correct, and does what we actually want: foo will run in
'runlevel3'. So we can't simply invert the ordering of the add_symlink() call
without causing other problems.

So I think we need to go to load_sysv() and look at the special handling of the
network online target:

                                        if (streq(m,
SPECIAL_NETWORK_ONLINE_TARGET) && !is_before) {
                                                /* the network-online target is
special, as it needs to be actively pulled in */
                                                r = strv_extend(&s->after, m);
                                                if (r < 0)
                                                        return log_oom();
                                                r = strv_extend(&s->wants, m);
                                                if (r < 0)
                                                        return log_oom();
                                        }

and do...something different there. But I'm afraid my C isn't quite up to
handling that 'something different', I don't think. I hope I've correctly
analyzed the problem at least, though.

Obviously this bug is fairly serious - it means all sysv services present on
the system will be started any time network-online.target is "Wanted" by
anything *else* (which is usually the case, on a typical system). This could
even cause a security problem - imagine you have /etc/init.d/telnet ...

-- 
You are receiving this mail because:
You are the QA Contact for the bug.
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/systemd-bugs/attachments/20140625/1a76f664/attachment.html>


More information about the systemd-bugs mailing list