Bug 623431

Summary: telinit doesn't talk to init
Product: [Fedora] Fedora Reporter: Bill Nottingham <notting>
Component: systemdAssignee: Lennart Poettering <lpoetter>
Status: CLOSED UPSTREAM QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: low    
Version: 14CC: dwalsh, lpoetter, metherid, mschmidt, nicolas.mailhot, plautrba, rvokal
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-08-24 19:03:25 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 538278    
Attachments:
Description Flags
This patch initializes labeling for systemd and call selabel_lookup for the label of the fifo file.
none
Updated patch to remove process label from label_fifo_set and only load labels if label_mkdir is called. none

Description Bill Nottingham 2010-08-11 19:04:30 UTC
Description of problem:

[root@localhost ~]# telinit 3
Failed to talk to init daemon.
[root@localhost ~]# systemctl
UNIT                                          LOAD   ACTIVE       SUB          JOB             DESCRIPTION
auditd.service                                loaded active       running     
basic.target                                  loaded active       active  
...

Version-Release number of selected component (if applicable):

systemd-7-1.fc14.x86_64
systemd-sysvinit-7-1.fc14.x86_64

How reproducible:

100%

Comment 1 Michal Schmidt 2010-08-11 20:11:45 UTC
It's an issue with /dev/initctl:

# systemctl | grep initctl
systemd-initctl.socket                        loaded maintenance  maintenance
# systemctl start systemd-initctl.socket
Job failed, see logs for details.
# dmesg|grep initctl
init[1]: systemd-initctl.socket failed to listen on sockets: No such file or directory
init[1]: Unit systemd-initctl.socket entered maintenance state.
init[1]: systemd-initctl.socket failed to listen on sockets: No such file or directory

And it's related to SELinux, though there's no AVC.

# setenforce 0
# systemctl start systemd-initctl.socket
# telinit 3
#

Comment 2 Bill Nottingham 2010-08-11 20:21:00 UTC
Hm. It doesn't show up with dontaudit disabled, either.

Comment 3 Bill Nottingham 2010-08-11 20:54:29 UTC
It's only tangentially related to selinux, it's a systemd error:

static int fifo_address_create(
                const char *path,
                mode_t directory_mode,
                mode_t socket_mode,
                const char *label, 
                int *_fd) {

        int fd = -1, r = 0;
        struct stat st;
        mode_t old_mask;

        assert(path);
        assert(_fd);

        mkdir_parents(path, directory_mode);

        if ((r = label_fifofile_set(label, path)) < 0)
                goto fail;

        /* Enforce the right access mode for the fifo */
        old_mask = umask(~ socket_mode);

        /* Include the original umask in our mask */
        umask(~socket_mode | old_mask);

...

If you look at label_fifofile_set:

int label_fifofile_set(const char *label, const char *path) {
        int r = 0;

#ifdef HAVE_SELINUX
        security_context_t filecon = NULL;

        if (!use_selinux() || !label)
                return 0;

        if (((r = label_get_file_label_from_path(label, path, "fifo_file", &filecon)) == 0)) {
                if ((r = setfscreatecon(filecon)) < 0) {
                        log_error("Failed to set SELinux file context (%s) on %s: %m", label, path);
                        r = -errno;
                }

                freecon(filecon);
        }

        if (r < 0 && security_getenforce() == 0)
                r = 0;
#endif

        return r;
}

The error it's getting in this case is the error from label_get_file_from_path... that the path doesn't exist yet.

However, if we're in non-enforcing mode, we return 0. So we
think this succeeds, and we continue down the path to create the
socket. In enforcing mode, we propogate the error, and don't
create the socket, because it's not there.

Comment 4 Michal Schmidt 2010-08-11 21:07:23 UTC
socket_open_fds()
  label_get_socket_label_from_exe()
  fifo_address_create()
    label_fifofile_set()
      label_get_file_label_from_path()
        getfilecon("/dev/initctl")

socket_open_fds() uses label_get_socket_label_from_exe() to establish that
/dev/initctl shall be created with the context "system_u:system_r:init_t:s0".
It passes the information to fifo_address_create()...
In the end getfilecon("/dev/initctl") returns -1 with errno == ENOENT.

CC Dan Walsh, he wrote the SELinux support in systemd.

Comment 5 Bill Nottingham 2010-08-11 21:14:36 UTC
I would think we'd want to ignore ENOENT from label_get_file_label_from_path(). Although I'm unclear why we're setting the label *before* we create the device.

Comment 6 Lennart Poettering 2010-08-12 02:50:55 UTC
Hmm, telinit should actually talk to systemd via D-Bus and only fallback to /dev/initctl if that doesn't work. There seem to be two issues here:

1) telinit fails to use D-Bus

2) systemd labels something incorrectly which makes /dev/initctl unusable too

Comment 7 Lennart Poettering 2010-08-12 03:03:34 UTC
Hmm, so the current code reads the label from the file node, because it wants to create the file node with it? Hmm, doesn't sound right.

Dan?

Comment 8 Lennart Poettering 2010-08-13 02:52:14 UTC
Fixed issue 2 mentioned on #6 now upstream. Leaves the SELinux issue.

Comment 9 Daniel Walsh 2010-08-13 19:42:57 UTC
Created attachment 438747 [details]
This patch initializes labeling for systemd and call selabel_lookup for the label of the fifo file.

This patch asks the system how the fifo file should be labeled.

Comment 10 Lennart Poettering 2010-08-14 14:51:14 UTC
*** Bug 624194 has been marked as a duplicate of this bug. ***

Comment 11 Lennart Poettering 2010-08-14 17:37:57 UTC
Dan, do we really need label_init() in systemctl? systemctl does little more than talking to systemd via D-Bus, so I don't think we need the policy db loaded here?

The other part looks good to me, and I'll commit it right-away.

Comment 12 Lennart Poettering 2010-08-14 17:56:30 UTC
Hmm, actually the patch doesn't look right to me. The label argument of label_fifofile_set() is now completely ignored.

What confuses me a bit is that label_get_socket_label_from_exe() is called for both the listening fifos and the listening sockets we created. Looking at the function there's nothing socket-specific in it, so maybe the function should be called differently?

Dan?

Comment 13 Daniel Walsh 2010-08-15 12:37:03 UTC
Lennart systemctl calls mkdir_parent which needs to make sure the labels are correct.  We could probably change the first call to mkdir_parent to call label_init if the handle is not set. Then it would only call it when needed.

label_fifofile_set no longer needs the label of the processes executing it.  The original code was to check for transitions, but the new code is just asking the system what the default label is for this  fifo file.

Comment 14 Daniel Walsh 2010-08-15 12:39:18 UTC
Created attachment 438823 [details]
Updated patch to remove process label from label_fifo_set and only load labels if label_mkdir is called.

Comment 15 Lennart Poettering 2010-08-16 22:31:45 UTC
Dan, the updated patch still doesn't use the "label" argument of label_fifofile_set(). This doesn't seem right! Dan, please explain!

systemctl is a client utility. It doesn't really create any directories on behalf of other processes, so I am wondering why we need the label stuff initialized in systemctl.c. The current code of mkdir_parent() already bypasses the selinux stuff if the label stuff is not initialized, which should normally do the right thing?

Comment 16 Lennart Poettering 2010-08-20 00:34:18 UTC
I have now reworked the patch and dropped the label argument from the fifo label calls. This is now commited:

http://cgit.freedesktop.org/systemd/commit/?id=049f86421bfe8afcbb00c7ee5a76fd14841f8bbf

Dan, could have a look on this?

I dropped the part changing systemctl, because I don't think it is appropriate, since it is a simple client too which will only create dirs beneath /etc/systemd/system/ which probably should be labelled all the same. The normal policy system should be able to cope with that.

Dan, if you OK this, then I'll close the bug!

Comment 17 Daniel Walsh 2010-08-23 17:48:13 UTC
Looks good to me.

Comment 18 Lennart Poettering 2010-08-24 19:03:25 UTC
Thanks, Dan!

OK, closing then.

Will do a new upload with this included tonight.