[systemd-commits] 8 commits - Makefile-man.am TODO man/sd_bus_negotiate_fds.xml man/systemd.exec.xml src/core src/fsck src/initctl src/journal src/libsystemd src/libsystemd-network src/login src/machine src/network src/nspawn src/readahead src/reply-password src/shared src/shutdownd src/socket-proxy src/test src/tmpfiles src/tty-ask-password-agent src/udev src/vconsole

Lennart Poettering lennart at kemper.freedesktop.org
Tue Mar 18 13:09:10 PDT 2014


 Makefile-man.am                                     |   12 +
 TODO                                                |    4 
 man/sd_bus_negotiate_fds.xml                        |  176 ++++++++++++++++++++
 man/systemd.exec.xml                                |    7 
 src/core/audit-fd.c                                 |    2 
 src/core/automount.c                                |   41 +---
 src/core/busname.c                                  |   27 +--
 src/core/busname.h                                  |    2 
 src/core/cgroup.c                                   |    8 
 src/core/dbus.c                                     |    5 
 src/core/execute.c                                  |   58 ++----
 src/core/ima-setup.c                                |    6 
 src/core/load-fragment-gperf.gperf.m4               |    1 
 src/core/load-fragment.c                            |    2 
 src/core/machine-id-setup.c                         |    7 
 src/core/main.c                                     |    2 
 src/core/manager.c                                  |   32 +--
 src/core/path.c                                     |    6 
 src/core/service.c                                  |    6 
 src/core/smack-setup.c                              |    2 
 src/core/socket.c                                   |   44 +----
 src/core/switch-root.c                              |   35 +--
 src/core/umount.c                                   |    8 
 src/core/unit.c                                     |    3 
 src/fsck/fsck.c                                     |    9 -
 src/initctl/initctl.c                               |    5 
 src/journal/cat.c                                   |    9 -
 src/journal/catalog.c                               |    8 
 src/journal/coredumpctl.c                           |    3 
 src/journal/journal-authenticate.c                  |    5 
 src/journal/journal-file.c                          |    4 
 src/journal/journal-send.c                          |   14 -
 src/journal/journal-verify.c                        |   12 -
 src/journal/journalctl.c                            |    5 
 src/journal/journald-console.c                      |    2 
 src/journal/journald-kmsg.c                         |   14 -
 src/journal/journald-server.c                       |   22 --
 src/journal/journald-stream.c                       |    7 
 src/journal/sd-journal.c                            |    3 
 src/journal/test-journal-verify.c                   |    2 
 src/journal/test-mmap-cache.c                       |    6 
 src/libsystemd-network/dhcp-network.c               |    4 
 src/libsystemd-network/ipv4ll-network.c             |    2 
 src/libsystemd-network/sd-dhcp-client.c             |   15 -
 src/libsystemd-network/sd-ipv4ll.c                  |    4 
 src/libsystemd/sd-bus/bus-container.c               |    6 
 src/libsystemd/sd-bus/bus-kernel.c                  |   30 +--
 src/libsystemd/sd-bus/bus-kernel.h                  |    2 
 src/libsystemd/sd-bus/bus-message.c                 |    4 
 src/libsystemd/sd-bus/bus-socket.c                  |    4 
 src/libsystemd/sd-bus/sd-bus.c                      |   76 +++++++-
 src/libsystemd/sd-bus/sd-memfd.c                    |    4 
 src/libsystemd/sd-bus/test-bus-chat.c               |    2 
 src/libsystemd/sd-bus/test-bus-kernel-benchmark.c   |    2 
 src/libsystemd/sd-bus/test-bus-kernel.c             |    6 
 src/libsystemd/sd-event/sd-event.c                  |   31 +--
 src/libsystemd/sd-login/sd-login.c                  |    8 
 src/libsystemd/sd-resolve/sd-resolve.c              |    3 
 src/libsystemd/sd-rtnl/sd-rtnl.c                    |    4 
 src/login/logind-button.c                           |    2 
 src/login/logind-inhibit.c                          |   12 -
 src/login/logind-session.c                          |   18 --
 src/login/logind.c                                  |    6 
 src/login/pam-module.c                              |    2 
 src/login/test-inhibit.c                            |    4 
 src/machine/machinectl.c                            |    6 
 src/network/sd-network.c                            |    2 
 src/nspawn/nspawn.c                                 |   31 +--
 src/readahead/readahead-collect.c                   |   22 --
 src/readahead/readahead-common.c                    |    2 
 src/readahead/readahead-replay.c                    |   18 --
 src/reply-password/reply-password.c                 |    6 
 src/shared/ask-password-api.c                       |   17 -
 src/shared/fdset.c                                  |    2 
 src/shared/install.c                                |   12 -
 src/shared/log.c                                    |   25 --
 src/shared/logs-show.c                              |    8 
 src/shared/spawn-polkit-agent.c                     |    4 
 src/shared/util.c                                   |   76 ++++----
 src/shared/util.h                                   |    6 
 src/shared/watchdog.c                               |    3 
 src/shutdownd/shutdownd.c                           |    3 
 src/socket-proxy/socket-proxyd.c                    |   16 -
 src/test/test-util.c                                |    2 
 src/tmpfiles/tmpfiles.c                             |    6 
 src/tty-ask-password-agent/tty-ask-password-agent.c |   25 --
 src/udev/net/link-config.c                          |    3 
 src/vconsole/vconsole-setup.c                       |    3 
 88 files changed, 594 insertions(+), 581 deletions(-)

New commits:
commit cb9da7f24fb057813606c87f9a73fdb941baa78c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 21:06:08 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index 9ffe6b0..c37b56e 100644
--- a/TODO
+++ b/TODO
@@ -182,6 +182,7 @@ Features:
   - port to sd-resolve for connecting to TCP dbus servers
   - constructors for bus messages should probably not be OK with a NULL bus pointer
   - .busname units should not use get_user_creds()/get_cgroup_creds() but instead do NSS only in temporarily forked off child
+  - .busname units need settings for controlling the attached creds, and timestamps for messages queued into its names.
 
 * sd-event
   - allow multiple signal handlers per signal?

commit ce236b57bee9a081d62db04bcc5be34e3ba6d217
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 21:05:16 2014 +0100

    man: dcument sd_bus_negotiate_fds() and friends

diff --git a/Makefile-man.am b/Makefile-man.am
index 079ba63..d772def 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -698,6 +698,7 @@ MANPAGES += \
 	man/sd_bus_message_append_strv.3 \
 	man/sd_bus_message_get_cookie.3 \
 	man/sd_bus_message_get_monotonic_usec.3 \
+	man/sd_bus_negotiate_fds.3 \
 	man/sd_bus_new.3 \
 	man/sd_bus_open_user.3 \
 	man/sd_bus_path_encode.3 \
@@ -750,6 +751,8 @@ MANPAGES_ALIAS += \
 	man/sd_bus_message_get_realtime_usec.3 \
 	man/sd_bus_message_get_reply_cookie.3 \
 	man/sd_bus_message_get_seqnum.3 \
+	man/sd_bus_negotiate_creds.3 \
+	man/sd_bus_negotiate_timestamps.3 \
 	man/sd_bus_open_system.3 \
 	man/sd_bus_open_system_container.3 \
 	man/sd_bus_open_system_remote.3 \
@@ -803,6 +806,8 @@ man/sd_bus_message_append_string_space.3: man/sd_bus_message_append_string_memfd
 man/sd_bus_message_get_realtime_usec.3: man/sd_bus_message_get_monotonic_usec.3
 man/sd_bus_message_get_reply_cookie.3: man/sd_bus_message_get_cookie.3
 man/sd_bus_message_get_seqnum.3: man/sd_bus_message_get_monotonic_usec.3
+man/sd_bus_negotiate_creds.3: man/sd_bus_negotiate_fds.3
+man/sd_bus_negotiate_timestamps.3: man/sd_bus_negotiate_fds.3
 man/sd_bus_open_system.3: man/sd_bus_open_user.3
 man/sd_bus_open_system_container.3: man/sd_bus_open_user.3
 man/sd_bus_open_system_remote.3: man/sd_bus_open_user.3
@@ -946,6 +951,12 @@ man/sd_bus_message_get_reply_cookie.html: man/sd_bus_message_get_cookie.html
 man/sd_bus_message_get_seqnum.html: man/sd_bus_message_get_monotonic_usec.html
 	$(html-alias)
 
+man/sd_bus_negotiate_creds.html: man/sd_bus_negotiate_fds.html
+	$(html-alias)
+
+man/sd_bus_negotiate_timestamps.html: man/sd_bus_negotiate_fds.html
+	$(html-alias)
+
 man/sd_bus_open_system.html: man/sd_bus_open_user.html
 	$(html-alias)
 
@@ -1430,6 +1441,7 @@ EXTRA_DIST += \
 	man/sd_bus_message_append_strv.xml \
 	man/sd_bus_message_get_cookie.xml \
 	man/sd_bus_message_get_monotonic_usec.xml \
+	man/sd_bus_negotiate_fds.xml \
 	man/sd_bus_new.xml \
 	man/sd_bus_open_user.xml \
 	man/sd_bus_path_encode.xml \
diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml
new file mode 100644
index 0000000..38e1fad
--- /dev/null
+++ b/man/sd_bus_negotiate_fds.xml
@@ -0,0 +1,176 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+This file is part of systemd.
+
+Copyright 2014 Lennart Poettering
+
+systemd is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+systemd is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_bus_negotiate_fds" conditional="ENABLE_KDBUS">
+
+  <refentryinfo>
+    <title>sd_bus_new</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart at poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_bus_negotiate_fds</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_bus_negotiate_fds</refname>
+    <refname>sd_bus_negotiate_timestamps</refname>
+    <refname>sd_bus_negotiate_creds</refname>
+
+    <refpurpose>Control feature negotiation on bus connections</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_bus_negotiate_fds</function></funcdef>
+        <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+        <paramdef>int <parameter>b</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_bus_negotiate_timestamp</function></funcdef>
+        <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+        <paramdef>int <parameter>b</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_bus_negotiate_creds</function></funcdef>
+        <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+        <paramdef>int <parameter>b</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_bus_negotiate_fds()</function> controls whether
+    file descriptor passing shall be negotiated for the specified bus
+    connection. Takes a bus object and a boolean, which when true
+    enables file descriptor passing, and when false disables it. Note
+    that not all transports and servers support file descriptor
+    passing. To find out whether file descriptor passing is available
+    after negotiation use
+    <citerefentry><refentrytitle>sd_bus_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    and pass <constant>SD_BUS_TYPE_UNIX_FD</constant>. Note that file
+    descriptor passing is always enabled for both sending and
+    receiving or for neither, but never only in one direction. By
+    default file descriptor passing is negotiated for all
+    connections.</para>
+
+    <para>Note that when bus activation is used it is highly
+    recommended to set the <option>AcceptFileDescriptors=</option>
+    setting in the <filename>.busname</filename> unit file to the same
+    setting as negotiated by the program ultimately activated. By
+    default file descriptor passing is enabled for both.</para>
+
+    <para><function>sd_bus_negotiate_timestamps()</function> controls
+    whether implicit sender timestamps shall be attached automatically
+    to all incoming messages. Takes a bus object and a boolean, which
+    when true enables timestamping, and when false disables it. If
+    this is disabled,
+    <citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_get_seqno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    fail with <constant>-ENODATA</constant> on incoming messages. Note
+    that not all transports support timestamping of messages. On local
+    transports the timestamping is applied by the kernel and cannot be
+    manipulated by userspace.</para>
+
+    <para><function>sd_bus_negotiate_creds()</function> controls
+    whether implicit sender credentials shall be attached
+    automatically to all incoming messages. Takes a bus object and a
+    bit mask value, which controls which credential parameters are
+    attached. If this is not used,
+    <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    fails with <constant>-ENODATA</constant> on incoming
+    messages. Note that not all transports support attaching sender
+    credentials to messages, or do not support all types of sender
+    credential parameters. On local transports the sender credentials
+    are attached by the kernel and cannot be manipulated by
+    userspace. By default no sender credentials are attached.</para>
+
+    <para>These functions may be called only before the connection has
+    been started with
+    <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, these functions returns 0 or a
+    positive integer. On failure, it returns a negative errno-style
+    error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><varname>-EPERM</varname></term>
+
+        <listitem><para>The bus connection has already been started.</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Notes</title>
+
+    <para><function>sd_bus_negotiate_fs()</function> and the other
+    functions described here are available as a shared library, which
+    can be compiled and linked to with the
+    <constant>libsystemd</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+    file.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_bus_message_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>

commit 2ce97e2b04c9f9ee51529488f3114693d5204ff1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 21:03:37 2014 +0100

    sd-bus: if we got a message with fds attached even though we didn't negotiate it, refuse to take it
    
    This makes sure we don't mishandle if developers specificy a different
    AcceptFileDescriptors= setting in .busname units then they set for the
    bus connection in the activated program.

diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 2794a44..6a1f459 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1885,12 +1885,17 @@ _public_ int sd_bus_call(
 
                                 if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
 
-                                        if (reply)
-                                                *reply = incoming;
-                                        else
-                                                sd_bus_message_unref(incoming);
+                                        if (incoming->n_fds <= 0 || (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
+                                                if (reply)
+                                                        *reply = incoming;
+                                                else
+                                                        sd_bus_message_unref(incoming);
+
+                                                return 1;
+                                        }
+
+                                        r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
 
-                                        return 1;
                                 } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
                                         r = sd_bus_error_copy(error, &incoming->error);
                                 else
@@ -2108,8 +2113,9 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
 }
 
 static int process_reply(sd_bus *bus, sd_bus_message *m) {
+        _cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL;
         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
-        struct reply_callback *c;
+        _cleanup_free_ struct reply_callback *c = NULL;
         int r;
 
         assert(bus);
@@ -2126,13 +2132,32 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
         if (c->timeout != 0)
                 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
 
-        r = sd_bus_message_rewind(m, true);
-        if (r < 0)
-                return r;
+        if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
+
+                /* If the reply contained a file descriptor which we
+                 * didn't want we pass an error instead. */
+
+                r = bus_message_new_synthetic_error(
+                                bus,
+                                m->reply_cookie,
+                                &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"),
+                                &synthetic_reply);
+                if (r < 0)
+                        return r;
+
+                r = bus_seal_synthetic_message(bus, synthetic_reply);
+                if (r < 0)
+                        return r;
+
+                m = synthetic_reply;
+        } else {
+                r = sd_bus_message_rewind(m, true);
+                if (r < 0)
+                        return r;
+        }
 
         r = c->callback(bus, m, c->userdata, &error_buffer);
         r = bus_maybe_reply_error(m, r, &error_buffer);
-        free(c);
 
         return r;
 }
@@ -2244,6 +2269,29 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
         return 1;
 }
 
+static int process_fd_check(sd_bus *bus, sd_bus_message *m) {
+        assert(bus);
+        assert(m);
+
+        /* If we got a message with a file descriptor which we didn't
+         * want to accept, then let's drop it. How can this even
+         * happen? For example, when the kernel queues a message into
+         * an activatable names's queue which allows fds, and then is
+         * delivered to us later even though we ourselves did not
+         * negotiate it. */
+
+        if (m->n_fds <= 0)
+                return 0;
+
+        if (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)
+                return 0;
+
+        if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
+                return 1; /* just eat it up */
+
+        return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Message contains file descriptors, which I cannot accept. Sorry.");
+}
+
 static int process_message(sd_bus *bus, sd_bus_message *m) {
         int r;
 
@@ -2272,6 +2320,10 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
         if (r != 0)
                 goto finish;
 
+        r = process_fd_check(bus, m);
+        if (r != 0)
+                goto finish;
+
         r = process_filter(bus, m);
         if (r != 0)
                 goto finish;

commit 3f9da416457c4265b8f1179516a32ad1a987ff7d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 20:54:32 2014 +0100

    core: add new AcceptFD= setting to .busname units
    
    AcceptFD= defaults to true, thus making sure that by default fd passing
    is enabled for all activatable names. Since for normal bus connections
    fd passing is enabled too by default this makes sure fd passing works
    correctly regardless whether a service is already activated or not.
    
    Making this configurable on both busname units and in bus connections is
    messy, but unavoidable since busnames are established and may queue
    messages before the connection feature negotiation is done by the
    service eventually activated. Conversely, feature negotiation on bus
    connections takes place before the connection acquires its names.
    
    Of course, this means developers really should make sure to keep the
    settings in .busname units in sync with what they later intend to
    negotiate.

diff --git a/src/core/busname.c b/src/core/busname.c
index 9d7a796..ccef32e 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -43,6 +43,7 @@ static void busname_init(Unit *u) {
         assert(u->load_state == UNIT_STUB);
 
         n->starter_fd = -1;
+        n->accept_fd = true;
 }
 
 static void busname_done(Unit *u) {
@@ -170,10 +171,12 @@ static void busname_dump(Unit *u, FILE *f, const char *prefix) {
         fprintf(f,
                 "%sBus Name State: %s\n"
                 "%sResult: %s\n"
-                "%sName: %s\n",
+                "%sName: %s\n"
+                "%sAccept FD: %s\n",
                 prefix, busname_state_to_string(n->state),
                 prefix, busname_result_to_string(n->result),
-                prefix, n->name);
+                prefix, n->name,
+                prefix, yes_no(n->accept_fd));
 }
 
 static void busname_unwatch_fd(BusName *n) {
@@ -226,8 +229,10 @@ static int busname_open_fd(BusName *n) {
         if (n->starter_fd >= 0)
                 return 0;
 
-        n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
-                                                  n->name, n->policy);
+        n->starter_fd = bus_kernel_create_starter(
+                        UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
+                        n->name, n->accept_fd, n->policy);
+
         if (n->starter_fd < 0) {
                 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
                 return n->starter_fd;
diff --git a/src/core/busname.h b/src/core/busname.h
index f79f510..7f59197 100644
--- a/src/core/busname.h
+++ b/src/core/busname.h
@@ -56,6 +56,8 @@ struct BusName {
 
         sd_event_source *event_source;
 
+        bool accept_fd;
+
         LIST_HEAD(BusNamePolicy, policy);
 };
 
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index f85d868..c793a1e 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -256,6 +256,7 @@ BusName.AllowUser,               config_parse_bus_policy,            0,
 BusName.AllowGroup,              config_parse_bus_policy,            0,                             0
 BusName.AllowWorld,              config_parse_bus_policy,            0,                             0
 BusName.SELinuxContext,          config_parse_exec_selinux_context,  0,                             0
+BusName.AcceptFileDescriptors,   config_parse_bool,                  0,                             offsetof(BusName, accept_fd)
 m4_dnl
 Mount.What,                      config_parse_string,                0,                             offsetof(Mount, parameters_fragment.what)
 Mount.Where,                     config_parse_path,                  0,                             offsetof(Mount, where)
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index 445bd7f..64a74d6 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1378,7 +1378,7 @@ static void bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbu
         }
 }
 
-int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *policy) {
+int bus_kernel_create_starter(const char *bus, const char *name, bool accept_fd, BusNamePolicy *policy) {
         struct kdbus_cmd_hello *hello;
         struct kdbus_item *n;
         size_t policy_cnt = 0;
@@ -1420,7 +1420,7 @@ int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *
         }
 
         hello->size = size;
-        hello->conn_flags = KDBUS_HELLO_ACTIVATOR|KDBUS_HELLO_ACCEPT_FD;
+        hello->conn_flags = KDBUS_HELLO_ACTIVATOR | (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
         hello->pool_size = KDBUS_POOL_SIZE;
 
         if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h
index a1e9691..3a9794f 100644
--- a/src/libsystemd/sd-bus/bus-kernel.h
+++ b/src/libsystemd/sd-bus/bus-kernel.h
@@ -67,7 +67,7 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority);
 
 int bus_kernel_create_bus(const char *name, bool world, char **s);
 int bus_kernel_create_domain(const char *name, char **s);
-int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *policy);
+int bus_kernel_create_starter(const char *bus, const char *name, bool accept_fd, BusNamePolicy *policy);
 int bus_kernel_create_monitor(const char *bus);
 
 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated);

commit 63405595065fb60811440680b148261e9ec50704
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 19:31:44 2014 +0100

    test

diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index e229baf..445bd7f 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1420,7 +1420,7 @@ int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *
         }
 
         hello->size = size;
-        hello->conn_flags = KDBUS_HELLO_ACTIVATOR;
+        hello->conn_flags = KDBUS_HELLO_ACTIVATOR|KDBUS_HELLO_ACCEPT_FD;
         hello->pool_size = KDBUS_POOL_SIZE;
 
         if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {

commit 03e334a1c7dc8c20c38902aa039440763acc9b17
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 19:22:43 2014 +0100

    util: replace close_nointr_nofail() by a more useful safe_close()
    
    safe_close() automatically becomes a NOP when a negative fd is passed,
    and returns -1 unconditionally. This makes it easy to write lines like
    this:
    
            fd = safe_close(fd);
    
    Which will close an fd if it is open, and reset the fd variable
    correctly.
    
    By making use of this new scheme we can drop a > 200 lines of code that
    was required to test for non-negative fds or to reset the closed fd
    variable afterwards.

diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c
index 5955bd8..4326d17 100644
--- a/src/core/audit-fd.c
+++ b/src/core/audit-fd.c
@@ -55,7 +55,7 @@ int get_audit_fd(void) {
 void close_audit_fd(void) {
 
         if (initialized && audit_fd >= 0)
-                close_nointr_nofail(audit_fd);
+                safe_close(audit_fd);
 
         initialized = true;
         audit_fd = -ECONNRESET;
diff --git a/src/core/automount.c b/src/core/automount.c
index 889b20e..77d80b2 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -90,9 +90,7 @@ static void unmount_autofs(Automount *a) {
         automount_send_ready(a, -EHOSTDOWN);
 
         a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
-
-        close_nointr_nofail(a->pipe_fd);
-        a->pipe_fd = -1;
+        a->pipe_fd = safe_close(a->pipe_fd);
 
         /* If we reload/reexecute things we keep the mount point
          * around */
@@ -310,8 +308,7 @@ static int open_dev_autofs(Manager *m) {
 
         init_autofs_dev_ioctl(&param);
         if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
-                close_nointr_nofail(m->dev_autofs_fd);
-                m->dev_autofs_fd = -1;
+                m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
                 return -errno;
         }
 
@@ -411,8 +408,9 @@ static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, in
 }
 
 int automount_send_ready(Automount *a, int status) {
-        int ioctl_fd, r;
+        _cleanup_close_ int ioctl_fd = -1;
         unsigned token;
+        int r;
 
         assert(a);
         assert(status <= 0);
@@ -421,10 +419,8 @@ int automount_send_ready(Automount *a, int status) {
                 return 0;
 
         ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
-        if (ioctl_fd < 0) {
-                r = ioctl_fd;
-                goto fail;
-        }
+        if (ioctl_fd < 0)
+                return ioctl_fd;
 
         if (status)
                 log_debug_unit(UNIT(a)->id, "Sending failure: %s", strerror(-status));
@@ -450,18 +446,15 @@ int automount_send_ready(Automount *a, int status) {
                         r = k;
         }
 
-fail:
-        if (ioctl_fd >= 0)
-                close_nointr_nofail(ioctl_fd);
-
         return r;
 }
 
 static void automount_enter_waiting(Automount *a) {
+        _cleanup_close_ int ioctl_fd = -1;
         int p[2] = { -1, -1 };
         char name[32], options[128];
         bool mounted = false;
-        int r, ioctl_fd = -1, dev_autofs_fd;
+        int r, dev_autofs_fd;
         struct stat st;
 
         assert(a);
@@ -500,8 +493,7 @@ static void automount_enter_waiting(Automount *a) {
 
         mounted = true;
 
-        close_nointr_nofail(p[1]);
-        p[1] = -1;
+        p[1] = safe_close(p[1]);
 
         if (stat(a->where, &st) < 0) {
                 r = -errno;
@@ -528,9 +520,6 @@ static void automount_enter_waiting(Automount *a) {
          * the direct mount will not receive events from the
          * kernel. */
 
-        close_nointr_nofail(ioctl_fd);
-        ioctl_fd = -1;
-
         r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
         if (r < 0)
                 goto fail;
@@ -543,10 +532,7 @@ static void automount_enter_waiting(Automount *a) {
         return;
 
 fail:
-        assert_se(close_pipe(p) == 0);
-
-        if (ioctl_fd >= 0)
-                close_nointr_nofail(ioctl_fd);
+        close_pipe(p);
 
         if (mounted)
                 repeat_unmount(a->where);
@@ -713,9 +699,7 @@ static int automount_deserialize_item(Unit *u, const char *key, const char *valu
                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                         log_debug_unit(u->id, "Failed to parse pipe-fd value %s", value);
                 else {
-                        if (a->pipe_fd >= 0)
-                                close_nointr_nofail(a->pipe_fd);
-
+                        safe_close(a->pipe_fd);
                         a->pipe_fd = fdset_remove(fds, fd);
                 }
         } else
@@ -809,8 +793,7 @@ fail:
 static void automount_shutdown(Manager *m) {
         assert(m);
 
-        if (m->dev_autofs_fd >= 0)
-                close_nointr_nofail(m->dev_autofs_fd);
+        m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
 }
 
 static void automount_reset_failed(Unit *u) {
diff --git a/src/core/busname.c b/src/core/busname.c
index bd7d02d..9d7a796 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -56,11 +56,7 @@ static void busname_done(Unit *u) {
         unit_ref_unset(&n->service);
 
         n->event_source = sd_event_source_unref(n->event_source);
-
-        if (n->starter_fd >= 0) {
-                close_nointr_nofail(n->starter_fd);
-                n->starter_fd = -1;
-        }
+        n->starter_fd = safe_close(n->starter_fd);
 }
 
 static int busname_add_default_default_dependencies(BusName *n) {
@@ -122,8 +118,6 @@ static int busname_add_extras(BusName *n) {
         return 0;
 }
 
-
-
 static int busname_verify(BusName *n) {
         char *e;
 
@@ -202,8 +196,7 @@ static void busname_close_fd(BusName *n) {
         if (n->starter_fd <= 0)
                 return;
 
-        close_nointr_nofail(n->starter_fd);
-        n->starter_fd = -1;
+        n->starter_fd = safe_close(n->starter_fd);
 }
 
 static int busname_watch_fd(BusName *n) {
@@ -454,8 +447,7 @@ static int busname_deserialize_item(Unit *u, const char *key, const char *value,
                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                         log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
                 else {
-                        if (n->starter_fd >= 0)
-                                close_nointr_nofail(n->starter_fd);
+                        safe_close(n->starter_fd);
                         n->starter_fd = fdset_remove(fds, fd);
                 }
         } else
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 18de888..9cc8544 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -862,8 +862,7 @@ int manager_setup_cgroup(Manager *m) {
         }
 
         /* 5. And pin it, so that it cannot be unmounted */
-        if (m->pin_cgroupfs_fd >= 0)
-                close_nointr_nofail(m->pin_cgroupfs_fd);
+        safe_close(m->pin_cgroupfs_fd);
 
         m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
         if (r < 0) {
@@ -888,10 +887,7 @@ void manager_shutdown_cgroup(Manager *m, bool delete) {
         if (delete && m->cgroup_root)
                 cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
 
-        if (m->pin_cgroupfs_fd >= 0) {
-                close_nointr_nofail(m->pin_cgroupfs_fd);
-                m->pin_cgroupfs_fd = -1;
-        }
+        m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd);
 
         free(m->cgroup_root);
         m->cgroup_root = NULL;
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 72f36bd..d482e6c 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -1086,10 +1086,7 @@ void bus_done(Manager *m) {
         if (m->private_listen_event_source)
                 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
 
-        if (m->private_listen_fd >= 0) {
-                close_nointr_nofail(m->private_listen_fd);
-                m->private_listen_fd = -1;
-        }
+        m->private_listen_fd = safe_close(m->private_listen_fd);
 }
 
 int bus_fdset_add_all(Manager *m, FDSet *fds) {
diff --git a/src/core/execute.c b/src/core/execute.c
index ca807dc..a46f25d 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -123,7 +123,7 @@ static int shift_fds(int fds[], unsigned n_fds) {
                         if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
                                 return -errno;
 
-                        close_nointr_nofail(fds[i]);
+                        safe_close(fds[i]);
                         fds[i] = nfd;
 
                         /* Hmm, the fd we wanted isn't free? Then
@@ -209,7 +209,7 @@ static int open_null_as(int flags, int nfd) {
 
         if (fd != nfd) {
                 r = dup2(fd, nfd) < 0 ? -errno : nfd;
-                close_nointr_nofail(fd);
+                safe_close(fd);
         } else
                 r = nfd;
 
@@ -234,12 +234,12 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons
 
         r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
         if (r < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         if (shutdown(fd, SHUT_RD) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -263,7 +263,7 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons
 
         if (fd != nfd) {
                 r = dup2(fd, nfd) < 0 ? -errno : nfd;
-                close_nointr_nofail(fd);
+                safe_close(fd);
         } else
                 r = nfd;
 
@@ -280,7 +280,7 @@ static int open_terminal_as(const char *path, mode_t mode, int nfd) {
 
         if (fd != nfd) {
                 r = dup2(fd, nfd) < 0 ? -errno : nfd;
-                close_nointr_nofail(fd);
+                safe_close(fd);
         } else
                 r = nfd;
 
@@ -340,7 +340,7 @@ static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty
 
                 if (fd != STDIN_FILENO) {
                         r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                 } else
                         r = STDIN_FILENO;
 
@@ -504,7 +504,7 @@ static int setup_confirm_stdio(int *_saved_stdin,
         }
 
         if (fd >= 2)
-                close_nointr_nofail(fd);
+                safe_close(fd);
 
         *_saved_stdin = saved_stdin;
         *_saved_stdout = saved_stdout;
@@ -512,20 +512,15 @@ static int setup_confirm_stdio(int *_saved_stdin,
         return 0;
 
 fail:
-        if (saved_stdout >= 0)
-                close_nointr_nofail(saved_stdout);
-
-        if (saved_stdin >= 0)
-                close_nointr_nofail(saved_stdin);
-
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(saved_stdout);
+        safe_close(saved_stdin);
+        safe_close(fd);
 
         return r;
 }
 
 _printf_(1, 2) static int write_confirm_message(const char *format, ...) {
-        int fd;
+        _cleanup_close_ int fd = -1;
         va_list ap;
 
         assert(format);
@@ -538,8 +533,6 @@ _printf_(1, 2) static int write_confirm_message(const char *format, ...) {
         vdprintf(fd, format, ap);
         va_end(ap);
 
-        close_nointr_nofail(fd);
-
         return 0;
 }
 
@@ -561,11 +554,8 @@ static int restore_confirm_stdio(int *saved_stdin,
                 if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
                         r = -errno;
 
-        if (*saved_stdin >= 0)
-                close_nointr_nofail(*saved_stdin);
-
-        if (*saved_stdout >= 0)
-                close_nointr_nofail(*saved_stdout);
+        safe_close(*saved_stdin);
+        safe_close(*saved_stdout);
 
         return r;
 }
@@ -1125,10 +1115,9 @@ finish:
 static void do_idle_pipe_dance(int idle_pipe[4]) {
         assert(idle_pipe);
 
-        if (idle_pipe[1] >= 0)
-                close_nointr_nofail(idle_pipe[1]);
-        if (idle_pipe[2] >= 0)
-                close_nointr_nofail(idle_pipe[2]);
+
+        safe_close(idle_pipe[1]);
+        safe_close(idle_pipe[2]);
 
         if (idle_pipe[0] >= 0) {
                 int r;
@@ -1143,12 +1132,11 @@ static void do_idle_pipe_dance(int idle_pipe[4]) {
                         fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
                 }
 
-                close_nointr_nofail(idle_pipe[0]);
+                safe_close(idle_pipe[0]);
 
         }
 
-        if (idle_pipe[3] >= 0)
-                close_nointr_nofail(idle_pipe[3]);
+        safe_close(idle_pipe[3]);
 }
 
 static int build_environment(
@@ -2730,9 +2718,7 @@ int exec_runtime_deserialize_item(ExecRuntime **rt, Unit *u, const char *key, co
                 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
                         log_debug_unit(u->id, "Failed to parse netns socket value %s", value);
                 else {
-                        if ((*rt)->netns_storage_socket[0] >= 0)
-                                close_nointr_nofail((*rt)->netns_storage_socket[0]);
-
+                        safe_close((*rt)->netns_storage_socket[0]);
                         (*rt)->netns_storage_socket[0] = fdset_remove(fds, fd);
                 }
         } else if (streq(key, "netns-socket-1")) {
@@ -2745,9 +2731,7 @@ int exec_runtime_deserialize_item(ExecRuntime **rt, Unit *u, const char *key, co
                 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
                         log_debug_unit(u->id, "Failed to parse netns socket value %s", value);
                 else {
-                        if ((*rt)->netns_storage_socket[1] >= 0)
-                                close_nointr_nofail((*rt)->netns_storage_socket[1]);
-
+                        safe_close((*rt)->netns_storage_socket[1]);
                         (*rt)->netns_storage_socket[1] = fdset_remove(fds, fd);
                 }
         } else
diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c
index 7f8ec23..ed65096 100644
--- a/src/core/ima-setup.c
+++ b/src/core/ima-setup.c
@@ -47,7 +47,7 @@ int ima_setup(void) {
        struct stat st;
        ssize_t policy_size = 0, written = 0;
        char *policy;
-       int policyfd = -1, imafd = -1;
+       _cleanup_close_ int policyfd = -1, imafd = -1;
        int result = 0;
 
        if (stat(IMA_POLICY_PATH, &st) < 0)
@@ -98,10 +98,6 @@ int ima_setup(void) {
 out_mmap:
        munmap(policy, policy_size);
 out:
-       if (policyfd >= 0)
-                close_nointr_nofail(policyfd);
-       if (imafd >= 0)
-                close_nointr_nofail(imafd);
        if (result)
                 return result;
 #endif /* HAVE_IMA */
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 06e3031..1c7ac75 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3085,7 +3085,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
         f = fdopen(fd, "re");
         if (!f) {
                 r = -errno;
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return r;
         }
 
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 43720d6..d459afe 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -78,7 +78,7 @@ static int generate(char id[34], const char *root) {
         fd = open(dbus_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd >= 0) {
                 k = loop_read(fd, id, 33, false);
-                close_nointr_nofail(fd);
+                safe_close(fd);
 
                 if (k == 33 && id[32] == '\n') {
 
@@ -104,7 +104,7 @@ static int generate(char id[34], const char *root) {
                 fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
                 if (fd >= 0) {
                         k = loop_read(fd, uuid, 36, false);
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
 
                         if (k >= 36) {
                                 r = shorten_uuid(id, uuid);
@@ -216,8 +216,7 @@ int machine_id_setup(const char *root) {
                         return 0;
         }
 
-        close_nointr_nofail(fd);
-        fd = -1;
+        fd = safe_close(fd);
 
         /* Hmm, we couldn't write it? So let's write it to
          * /run/machine-id as a replacement */
diff --git a/src/core/main.c b/src/core/main.c
index cc876ef..e0fbb6e 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -240,7 +240,7 @@ static int console_setup(bool do_reset) {
         if (r < 0)
                 log_error("Failed to reset /dev/console: %s", strerror(-r));
 
-        close_nointr_nofail(tty_fd);
+        safe_close(tty_fd);
         return r;
 }
 
diff --git a/src/core/manager.c b/src/core/manager.c
index ce5888e..632ce74 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -250,8 +250,7 @@ static int manager_setup_time_change(Manager *m) {
 
         if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
                 log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
-                close_nointr_nofail(m->time_change_fd);
-                m->time_change_fd = -1;
+                m->time_change_fd = safe_close(m->time_change_fd);
                 return 0;
         }
 
@@ -793,14 +792,10 @@ void manager_free(Manager *m) {
         sd_event_source_unref(m->idle_pipe_event_source);
         sd_event_source_unref(m->run_queue_event_source);
 
-        if (m->signal_fd >= 0)
-                close_nointr_nofail(m->signal_fd);
-        if (m->notify_fd >= 0)
-                close_nointr_nofail(m->notify_fd);
-        if (m->time_change_fd >= 0)
-                close_nointr_nofail(m->time_change_fd);
-        if (m->kdbus_fd >= 0)
-                close_nointr_nofail(m->kdbus_fd);
+        safe_close(m->signal_fd);
+        safe_close(m->notify_fd);
+        safe_close(m->time_change_fd);
+        safe_close(m->kdbus_fd);
 
         manager_close_idle_pipe(m);
 
@@ -1756,9 +1751,7 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint
 
         /* Restart the watch */
         m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
-
-        close_nointr_nofail(m->time_change_fd);
-        m->time_change_fd = -1;
+        m->time_change_fd = safe_close(m->time_change_fd);
 
         manager_setup_time_change(m);
 
@@ -2042,7 +2035,7 @@ int manager_open_serialization(Manager *m, FILE **_f) {
 
         f = fdopen(fd, "w+");
         if (!f) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -2263,11 +2256,8 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         if (safe_atoi(l + 10, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                                 log_debug("Failed to parse notify fd: %s", l + 10);
                         else {
-                                if (m->notify_fd >= 0) {
-                                        m->notify_event_source = sd_event_source_unref(m->notify_event_source);
-                                        close_nointr_nofail(m->notify_fd);
-                                }
-
+                                m->notify_event_source = sd_event_source_unref(m->notify_event_source);
+                                safe_close(m->notify_fd);
                                 m->notify_fd = fdset_remove(fds, fd);
                         }
 
@@ -2289,9 +2279,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         if (safe_atoi(l + 9, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                                 log_debug("Failed to parse kdbus fd: %s", l + 9);
                         else {
-                                if (m->kdbus_fd >= 0)
-                                        close_nointr_nofail(m->kdbus_fd);
-
+                                safe_close(m->kdbus_fd);
                                 m->kdbus_fd = fdset_remove(fds, fd);
                         }
 
diff --git a/src/core/path.c b/src/core/path.c
index 93c51bb..20e454d 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -152,11 +152,7 @@ void path_spec_unwatch(PathSpec *s) {
         assert(s);
 
         s->event_source = sd_event_source_unref(s->event_source);
-
-        if (s->inotify_fd >= 0) {
-                close_nointr_nofail(s->inotify_fd);
-                s->inotify_fd = -1;
-        }
+        s->inotify_fd = safe_close(s->inotify_fd);
 }
 
 int path_spec_fd_event(PathSpec *s, uint32_t revents) {
diff --git a/src/core/service.c b/src/core/service.c
index 386692a..fe7ddd1 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -226,8 +226,7 @@ static void service_close_socket_fd(Service *s) {
         if (s->socket_fd < 0)
                 return;
 
-        close_nointr_nofail(s->socket_fd);
-        s->socket_fd = -1;
+        s->socket_fd = safe_close(s->socket_fd);
 }
 
 static void service_connection_unref(Service *s) {
@@ -2684,8 +2683,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                         log_debug_unit(u->id, "Failed to parse socket-fd value %s", value);
                 else {
 
-                        if (s->socket_fd >= 0)
-                                close_nointr_nofail(s->socket_fd);
+                        safe_close(s->socket_fd);
                         s->socket_fd = fdset_remove(fds, fd);
                 }
         } else if (streq(key, "main-exec-status-pid")) {
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index a68605c..5f6dabf 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -87,7 +87,7 @@ static int write_rules(const char* dstpath, const char* srcdir) {
                 if (!policy) {
                         if (r == 0)
                                 r = -errno;
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         log_error("Failed to open %s: %m", entry->d_name);
                         continue;
                 }
diff --git a/src/core/socket.c b/src/core/socket.c
index b39bec2..b2a3e95 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -121,9 +121,7 @@ void socket_free_ports(Socket *s) {
 
                 sd_event_source_unref(p->event_source);
 
-                if (p->fd >= 0)
-                        close_nointr_nofail(p->fd);
-
+                safe_close(p->fd);
                 free(p->path);
                 free(p);
         }
@@ -700,7 +698,7 @@ static void socket_close_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                close_nointr_nofail(p->fd);
+                p->fd = safe_close(p->fd);
 
                 /* One little note: we should never delete any sockets
                  * in the file system here! After all some other
@@ -709,8 +707,6 @@ static void socket_close_fds(Socket *s) {
                  * we delete sockets in the file system before we
                  * create a new one, not after we stopped using
                  * one! */
-
-                p->fd = -1;
         }
 }
 
@@ -880,9 +876,7 @@ static int fifo_address_create(
 
 fail:
         label_context_clear();
-
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -917,8 +911,7 @@ static int special_address_create(
         return 0;
 
 fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -977,9 +970,7 @@ static int mq_address_create(
         return 0;
 
 fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
-
+        safe_close(fd);
         return r;
 }
 
@@ -1472,7 +1463,7 @@ static void socket_enter_running(Socket *s, int cfd) {
                 log_debug_unit(UNIT(s)->id, "Suppressing connection request on %s since unit stop is scheduled.", UNIT(s)->id);
 
                 if (cfd >= 0)
-                        close_nointr_nofail(cfd);
+                        safe_close(cfd);
                 else  {
                         /* Flush all sockets by closing and reopening them */
                         socket_close_fds(s);
@@ -1520,7 +1511,7 @@ static void socket_enter_running(Socket *s, int cfd) {
 
                 if (s->n_connections >= s->max_connections) {
                         log_warning_unit(UNIT(s)->id, "%s: Too many incoming connections (%u)", UNIT(s)->id, s->n_connections);
-                        close_nointr_nofail(cfd);
+                        safe_close(cfd);
                         return;
                 }
 
@@ -1535,7 +1526,7 @@ static void socket_enter_running(Socket *s, int cfd) {
 
                         /* ENOTCONN is legitimate if TCP RST was received.
                          * This connection is over, but the socket unit lives on. */
-                        close_nointr_nofail(cfd);
+                        safe_close(cfd);
                         return;
                 }
 
@@ -1586,9 +1577,7 @@ fail:
                          bus_error_message(&error, r));
 
         socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
-
-        if (cfd >= 0)
-                close_nointr_nofail(cfd);
+        safe_close(cfd);
 }
 
 static void socket_run_next(Socket *s) {
@@ -1819,8 +1808,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1839,8 +1827,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1859,8 +1846,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1878,8 +1864,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1897,8 +1882,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
diff --git a/src/core/switch-root.c b/src/core/switch-root.c
index ce0e41d..518ec1f 100644
--- a/src/core/switch-root.c
+++ b/src/core/switch-root.c
@@ -41,11 +41,10 @@ int switch_root(const char *new_root) {
                 "/sys\0"
                 "/run\0";
 
-        int r, old_root_fd = -1;
+        _cleanup_close_ int old_root_fd = -1;
         struct stat new_root_stat;
         bool old_root_remove;
-        const char *i;
-        _cleanup_free_ char *temporary_old_root = NULL;
+        const char *i, *temporary_old_root;
 
         if (path_equal(new_root, "/"))
                 return 0;
@@ -56,16 +55,13 @@ int switch_root(const char *new_root) {
          * directory we choose for this, but it should be more likely
          * than not that /mnt exists and is suitable as mount point
          * and is on the same fs as the old root dir */
-        temporary_old_root = strappend(new_root, "/mnt");
-        if (!temporary_old_root)
-                return -ENOMEM;
+        temporary_old_root = strappenda(new_root, "/mnt");
 
         old_root_remove = in_initrd();
 
         if (stat(new_root, &new_root_stat) < 0) {
-                r = -errno;
                 log_error("Failed to stat directory %s: %m", new_root);
-                goto fail;
+                return -errno;
         }
 
         /* Work-around for a kernel bug: for some reason the kernel
@@ -104,9 +100,8 @@ int switch_root(const char *new_root) {
         }
 
         if (chdir(new_root) < 0) {
-                r = -errno;
                 log_error("Failed to change directory to %s: %m", new_root);
-                goto fail;
+                return -errno;
         }
 
         if (old_root_remove) {
@@ -123,27 +118,23 @@ int switch_root(const char *new_root) {
                 /* Immediately get rid of the old root. Since we are
                  * running off it we need to do this lazily. */
                 if (umount2(temporary_old_root, MNT_DETACH) < 0) {
-                        r = -errno;
                         log_error("Failed to umount old root dir %s: %m", temporary_old_root);
-                        goto fail;
+                        return -errno;
                 }
 
         } else if (mount(new_root, "/", NULL, MS_MOVE, NULL) < 0) {
-                r = -errno;
                 log_error("Failed to mount moving %s to /: %m", new_root);
-                goto fail;
+                return -errno;
         }
 
         if (chroot(".") < 0) {
-                r = -errno;
                 log_error("Failed to change root: %m");
-                goto fail;
+                return -errno;
         }
 
         if (chdir("/") < 0) {
-                r = -errno;
                 log_error("Failed to change directory: %m");
-                goto fail;
+                return -errno;
         }
 
         if (old_root_fd >= 0) {
@@ -157,11 +148,5 @@ int switch_root(const char *new_root) {
                 }
         }
 
-        r = 0;
-
-fail:
-        if (old_root_fd >= 0)
-                close_nointr_nofail(old_root_fd);
-
-        return r;
+        return 0;
 }
diff --git a/src/core/umount.c b/src/core/umount.c
index 2d166c1..d1258f0 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -329,14 +329,14 @@ static int dm_list_get(MountPoint **head) {
 }
 
 static int delete_loopback(const char *device) {
-        int fd, r;
+        _cleanup_close_ int fd = -1;
+        int r;
 
-        if ((fd = open(device, O_RDONLY|O_CLOEXEC)) < 0)
+        fd = open(device, O_RDONLY|O_CLOEXEC);
+        if (fd < 0)
                 return errno == ENOENT ? 0 : -errno;
 
         r = ioctl(fd, LOOP_CLR_FD, 0);
-        close_nointr_nofail(fd);
-
         if (r >= 0)
                 return 1;
 
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index b6691c9..f60cc1d 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -142,7 +142,7 @@ static int process_progress(int fd) {
 
         f = fdopen(fd, "r");
         if (!f) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -329,15 +329,12 @@ int main(int argc, char *argv[]) {
         } else if (pid == 0) {
                 /* Child */
                 if (progress_pipe[0] >= 0)
-                        close_nointr_nofail(progress_pipe[0]);
+                        safe_close(progress_pipe[0]);
                 execv(cmdline[0], (char**) cmdline);
                 _exit(8); /* Operational error */
         }
 
-        if (progress_pipe[1] >= 0) {
-                close_nointr_nofail(progress_pipe[1]);
-                progress_pipe[1] = -1;
-        }
+        progress_pipe[1] = safe_close(progress_pipe[1]);
 
         if (progress_pipe[0] >= 0) {
                 process_progress(progress_pipe[0]);
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 468df35..f9613ea 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -245,7 +245,7 @@ static void fifo_free(Fifo *f) {
                 if (f->server)
                         epoll_ctl(f->server->epoll_fd, EPOLL_CTL_DEL, f->fd, NULL);
 
-                close_nointr_nofail(f->fd);
+                safe_close(f->fd);
         }
 
         free(f);
@@ -257,8 +257,7 @@ static void server_done(Server *s) {
         while (s->fifos)
                 fifo_free(s->fifos);
 
-        if (s->epoll_fd >= 0)
-                close_nointr_nofail(s->epoll_fd);
+        safe_close(s->epoll_fd);
 
         if (s->bus) {
                 sd_bus_flush(s->bus);
diff --git a/src/journal/cat.c b/src/journal/cat.c
index 02b7564..60625cb 100644
--- a/src/journal/cat.c
+++ b/src/journal/cat.c
@@ -152,7 +152,7 @@ int main(int argc, char *argv[]) {
         }
 
         if (fd >= 3)
-                close_nointr_nofail(fd);
+                safe_close(fd);
 
         fd = -1;
 
@@ -170,11 +170,8 @@ int main(int argc, char *argv[]) {
         log_error("Failed to execute process: %s", strerror(-r));
 
 finish:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
-
-        if (saved_stderr >= 0)
-                close_nointr_nofail(saved_stderr);
+        safe_close(fd);
+        safe_close(saved_stderr);
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/src/journal/catalog.c b/src/journal/catalog.c
index 2823232..3ed0b7e 100644
--- a/src/journal/catalog.c
+++ b/src/journal/catalog.c
@@ -469,18 +469,18 @@ static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p
                 return -errno;
 
         if (fstat(fd, &st) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         if (st.st_size < (off_t) sizeof(CatalogHeader)) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -EINVAL;
         }
 
         p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
         if (p == MAP_FAILED) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -491,7 +491,7 @@ static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p
             h->incompatible_flags != 0 ||
             le64toh(h->n_items) <= 0 ||
             st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 munmap(p, st.st_size);
                 return -EBADMSG;
         }
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
index 3bceb48..bf943bc 100644
--- a/src/journal/coredumpctl.c
+++ b/src/journal/coredumpctl.c
@@ -490,8 +490,7 @@ static int run_gdb(sd_journal *j) {
                 goto finish;
         }
 
-        close_nointr_nofail(fd);
-        fd = -1;
+        fd = safe_close(fd);
 
         pid = fork();
         if (pid < 0) {
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index f416b79..5ab1982 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -418,10 +418,9 @@ finish:
         if (m)
                 munmap(m, PAGE_ALIGN(sizeof(FSSHeader)));
 
-        if (fd >= 0)
-                close_nointr_nofail(fd);
-
+        safe_close(fd);
         free(p);
+
         return r;
 }
 
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 0e1fc7f..f2f1f35 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -133,9 +133,7 @@ void journal_file_close(JournalFile *f) {
         if (f->header)
                 munmap(f->header, PAGE_ALIGN(sizeof(Header)));
 
-        if (f->fd >= 0)
-                close_nointr_nofail(f->fd);
-
+        safe_close(f->fd);
         free(f->path);
 
         if (f->mmap)
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index ca9199f..d92e84b 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -66,7 +66,7 @@ retry:
         fd_inc_sndbuf(fd, SNDBUF_SIZE);
 
         if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 goto retry;
         }
 
@@ -316,7 +316,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
 
         n = writev(buffer_fd, w, j);
         if (n < 0) {
-                close_nointr_nofail(buffer_fd);
+                safe_close(buffer_fd);
                 return -errno;
         }
 
@@ -336,7 +336,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
         mh.msg_controllen = cmsg->cmsg_len;
 
         k = sendmsg(fd, &mh, MSG_NOSIGNAL);
-        close_nointr_nofail(buffer_fd);
+        safe_close(buffer_fd);
 
         if (k < 0)
                 return -errno;
@@ -412,12 +412,12 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
 
         r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
         if (r < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         if (shutdown(fd, SHUT_RD) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -445,12 +445,12 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
 
         r = loop_write(fd, header, l, false);
         if (r < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return (int) r;
         }
 
         if ((size_t) r != l) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 9434cc9..31bae5a 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -1222,9 +1222,9 @@ int journal_file_verify(
         mmap_cache_close_fd(f->mmap, entry_fd);
         mmap_cache_close_fd(f->mmap, entry_array_fd);
 
-        close_nointr_nofail(data_fd);
-        close_nointr_nofail(entry_fd);
-        close_nointr_nofail(entry_array_fd);
+        safe_close(data_fd);
+        safe_close(entry_fd);
+        safe_close(entry_array_fd);
 
         if (first_contained)
                 *first_contained = le64toh(f->header->head_entry_realtime);
@@ -1247,17 +1247,17 @@ fail:
 
         if (data_fd >= 0) {
                 mmap_cache_close_fd(f->mmap, data_fd);
-                close_nointr_nofail(data_fd);
+                safe_close(data_fd);
         }
 
         if (entry_fd >= 0) {
                 mmap_cache_close_fd(f->mmap, entry_fd);
-                close_nointr_nofail(entry_fd);
+                safe_close(entry_fd);
         }
 
         if (entry_array_fd >= 0) {
                 mmap_cache_close_fd(f->mmap, entry_array_fd);
-                close_nointr_nofail(entry_array_fd);
+                safe_close(entry_array_fd);
         }
 
         return r;
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 0619b25..0196290 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -1290,7 +1290,7 @@ static int setup_keys(void) {
         n = now(CLOCK_REALTIME);
         n /= arg_interval;
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
         fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
         if (fd < 0) {
                 log_error("Failed to open %s: %m", k);
@@ -1389,8 +1389,7 @@ static int setup_keys(void) {
         r = 0;
 
 finish:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         if (k) {
                 unlink(k);
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 35da52a..3db5fc5 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -107,5 +107,5 @@ void server_forward_console(
         if (writev(fd, iovec, n) < 0)
                 log_debug("Failed to write to %s for logging: %m", tty);
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
 }
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index 05b128f..35948ea 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -428,19 +428,14 @@ int server_open_dev_kmsg(Server *s) {
         return 0;
 
 fail:
-        if (s->dev_kmsg_event_source)
-                s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source);
-
-        if (s->dev_kmsg_fd >= 0) {
-                close_nointr_nofail(s->dev_kmsg_fd);
-                s->dev_kmsg_fd = -1;
-        }
+        s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source);
+        s->dev_kmsg_fd = safe_close(s->dev_kmsg_fd);
 
         return r;
 }
 
 int server_open_kernel_seqnum(Server *s) {
-        int fd;
+        _cleanup_close_ int fd;
         uint64_t *p;
 
         assert(s);
@@ -457,18 +452,15 @@ int server_open_kernel_seqnum(Server *s) {
 
         if (posix_fallocate(fd, 0, sizeof(uint64_t)) < 0) {
                 log_error("Failed to allocate sequential number file, ignoring: %m");
-                close_nointr_nofail(fd);
                 return 0;
         }
 
         p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
         if (p == MAP_FAILED) {
                 log_error("Failed to map sequential number file, ignoring: %m");
-                close_nointr_nofail(fd);
                 return 0;
         }
 
-        close_nointr_nofail(fd);
         s->kernel_seqnum = p;
 
         return 0;
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index ef39d0a..c2a60d5 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1432,8 +1432,7 @@ static int server_open_hostname(Server *s) {
                 if (r == -EPERM) {
                         log_warning("Failed to register hostname fd in event loop: %s. Ignoring.",
                                         strerror(-r));
-                        close_nointr_nofail(s->hostname_fd);
-                        s->hostname_fd = -1;
+                        s->hostname_fd = safe_close(s->hostname_fd);
                         return 0;
                 }
 
@@ -1643,20 +1642,11 @@ void server_done(Server *s) {
         sd_event_source_unref(s->hostname_event_source);
         sd_event_unref(s->event);
 
-        if (s->syslog_fd >= 0)
-                close_nointr_nofail(s->syslog_fd);
-
-        if (s->native_fd >= 0)
-                close_nointr_nofail(s->native_fd);
-
-        if (s->stdout_fd >= 0)
-                close_nointr_nofail(s->stdout_fd);
-
-        if (s->dev_kmsg_fd >= 0)
-                close_nointr_nofail(s->dev_kmsg_fd);
-
-        if (s->hostname_fd >= 0)
-                close_nointr_nofail(s->hostname_fd);
+        safe_close(s->syslog_fd);
+        safe_close(s->native_fd);
+        safe_close(s->stdout_fd);
+        safe_close(s->dev_kmsg_fd);
+        safe_close(s->hostname_fd);
 
         if (s->rate_limit)
                 journal_rate_limit_free(s->rate_limit);
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index c46ffe5..89da150 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -341,8 +341,7 @@ void stdout_stream_free(StdoutStream *s) {
                 s->event_source = sd_event_source_unref(s->event_source);
         }
 
-        if (s->fd >= 0)
-                close_nointr_nofail(s->fd);
+        safe_close(s->fd);
 
 #ifdef HAVE_SELINUX
         if (s->security_context)
@@ -377,13 +376,13 @@ static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revent
 
         if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
                 log_warning("Too many stdout streams, refusing connection.");
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return 0;
         }
 
         stream = new0(StdoutStream, 1);
         if (!stream) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return log_oom();
         }
 
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index b54bc21..7587211 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -1850,8 +1850,7 @@ _public_ void sd_journal_close(sd_journal *j) {
         hashmap_free(j->directories_by_path);
         hashmap_free(j->directories_by_wd);
 
-        if (j->inotify_fd >= 0)
-                close_nointr_nofail(j->inotify_fd);
+        safe_close(j->inotify_fd);
 
         if (j->mmap) {
                 log_debug("mmap cache statistics: %u hit, %u miss", mmap_cache_get_hit(j->mmap), mmap_cache_get_missed(j->mmap));
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index 0540074..3b181c6 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -48,7 +48,7 @@ static void bit_toggle(const char *fn, uint64_t p) {
         r = pwrite(fd, &b, 1, p/8);
         assert(r == 1);
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
 }
 
 static int raw_verify(const char *fn, const char *verification_key) {
diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c
index 7d03bfe..b7bb260 100644
--- a/src/journal/test-mmap-cache.c
+++ b/src/journal/test-mmap-cache.c
@@ -72,9 +72,9 @@ int main(int argc, char *argv[]) {
 
         mmap_cache_unref(m);
 
-        close_nointr_nofail(x);
-        close_nointr_nofail(y);
-        close_nointr_nofail(z);
+        safe_close(x);
+        safe_close(y);
+        safe_close(z);
 
         return 0;
 }
diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 934e8bf..29e915c 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -52,7 +52,7 @@ int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
                 return -errno;
 
         if (bind(s, &link->sa, sizeof(link->ll)) < 0) {
-                close_nointr_nofail(s);
+                safe_close(s);
                 return -errno;
         }
 
@@ -73,7 +73,7 @@ int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port)
                 return -errno;
 
         if (bind(s, &src.sa, sizeof(src.in)) < 0) {
-                close_nointr_nofail(s);
+                safe_close(s);
                 return -errno;
         }
 
diff --git a/src/libsystemd-network/ipv4ll-network.c b/src/libsystemd-network/ipv4ll-network.c
index 51734d7..68666fb 100644
--- a/src/libsystemd-network/ipv4ll-network.c
+++ b/src/libsystemd-network/ipv4ll-network.c
@@ -48,7 +48,7 @@ int arp_network_bind_raw_socket(int index, union sockaddr_union *link) {
         link->ll.sll_halen = ETH_ALEN;
 
         if (bind(s, &link->sa, sizeof(link->ll)) < 0) {
-                close_nointr_nofail(s);
+                safe_close(s);
                 return -errno;
         }
 
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 5374db7..2d3af2f 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -184,9 +184,7 @@ static int client_stop(sd_dhcp_client *client, int error) {
         client->receive_message =
                 sd_event_source_unref(client->receive_message);
 
-        if (client->fd >= 0)
-                close_nointr_nofail(client->fd);
-        client->fd = -1;
+        client->fd = safe_close(client->fd);
 
         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
 
@@ -546,12 +544,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         sd_dhcp_client *client = userdata;
         int r;
 
-        if (client->fd >= 0) {
-                client->receive_message =
-                        sd_event_source_unref(client->receive_message);
-                close_nointr_nofail(client->fd);
-                client->fd = -1;
-        }
+        client->receive_message = sd_event_source_unref(client->receive_message);
+        client->fd = safe_close(client->fd);
 
         client->state = DHCP_STATE_REBINDING;
         client->attempt = 1;
@@ -849,8 +843,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
                         client->receive_message =
                                 sd_event_source_unref(client->receive_message);
-                        close_nointr_nofail(client->fd);
-                        client->fd = -1;
+                        client->fd = safe_close(client->fd);
                 }
 
                 r = 0;
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index c6f6e01..689dce9 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -113,9 +113,7 @@ static int ipv4ll_stop(sd_ipv4ll *ll, int event) {
         assert(ll);
 
         ll->receive_message = sd_event_source_unref(ll->receive_message);
-        if (ll->fd >= 0)
-                close_nointr_nofail(ll->fd);
-        ll->fd = -1;
+        ll->fd = safe_close(ll->fd);
 
         ll->timer = sd_event_source_unref(ll->timer);
 
diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
index d330363..2cd0e1f 100644
--- a/src/libsystemd/sd-bus/bus-container.c
+++ b/src/libsystemd/sd-bus/bus-container.c
@@ -154,8 +154,7 @@ int bus_container_connect_kernel(sd_bus *b) {
         if (child == 0) {
                 pid_t grandchild;
 
-                close_nointr_nofail(pair[0]);
-                pair[0] = -1;
+                pair[0] = safe_close(pair[0]);
 
                 r = namespace_enter(pidnsfd, mntnsfd, rootfd);
                 if (r < 0)
@@ -202,8 +201,7 @@ int bus_container_connect_kernel(sd_bus *b) {
                 _exit(si.si_status);
         }
 
-        close_nointr_nofail(pair[1]);
-        pair[1] = -1;
+        pair[1] = safe_close(pair[1]);
 
         r = wait_for_terminate(child, &si);
         if (r < 0)
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index 5c955f4..e229baf 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -811,7 +811,7 @@ static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
                 if (d->type == KDBUS_ITEM_FDS)
                         close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
                 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
-                        close_nointr_nofail(d->memfd.fd);
+                        safe_close(d->memfd.fd);
         }
 }
 
@@ -1165,7 +1165,7 @@ static void close_and_munmap(int fd, void *address, size_t size) {
         if (size > 0)
                 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
 }
 
 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
@@ -1313,14 +1313,14 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) {
         make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
 
         if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         /* The higher 32bit of the flags field are considered
          * 'incompatible flags'. Refuse them all for now. */
         if (make->flags > 0xFFFFFFFFULL) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOTSUP;
         }
 
@@ -1329,7 +1329,7 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) {
 
                 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
                 if (!p) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -ENOMEM;
                 }
 
@@ -1424,7 +1424,7 @@ int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *
         hello->pool_size = KDBUS_POOL_SIZE;
 
         if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -1432,12 +1432,12 @@ int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *
          * 'incompatible flags'. Refuse them all for now. */
         if (hello->bus_flags > 0xFFFFFFFFULL ||
             hello->conn_flags > 0xFFFFFFFFULL) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOTSUP;
         }
 
         if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash)) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOTSUP;
         }
 
@@ -1469,14 +1469,14 @@ int bus_kernel_create_domain(const char *name, char **s) {
         make->flags = KDBUS_MAKE_ACCESS_WORLD;
 
         if (ioctl(fd, KDBUS_CMD_DOMAIN_MAKE, make) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         /* The higher 32bit of the flags field are considered
          * 'incompatible flags'. Refuse them all for now. */
         if (make->flags > 0xFFFFFFFFULL) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOTSUP;
         }
 
@@ -1485,7 +1485,7 @@ int bus_kernel_create_domain(const char *name, char **s) {
 
                 p = strappend("/dev/kdbus/domain/", name);
                 if (!p) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -ENOMEM;
                 }
 
@@ -1515,7 +1515,7 @@ int bus_kernel_create_monitor(const char *bus) {
         hello->pool_size = KDBUS_POOL_SIZE;
 
         if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -1523,7 +1523,7 @@ int bus_kernel_create_monitor(const char *bus) {
          * 'incompatible flags'. Refuse them all for now. */
         if (hello->bus_flags > 0xFFFFFFFFULL ||
             hello->conn_flags > 0xFFFFFFFFULL) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOTSUP;
         }
 
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index e32f2b8..4fcc693 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -70,7 +70,7 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
                         if (part->mapped > 0)
                                 assert_se(munmap(part->data, part->mapped) == 0);
 
-                        close_nointr_nofail(part->memfd);
+                        safe_close(part->memfd);
                 }
 
         } else if (part->munmap_this)
@@ -1274,7 +1274,7 @@ static int message_push_fd(sd_bus_message *m, int fd) {
         f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
         if (!f) {
                 m->poisoned = true;
-                close_nointr_nofail(copy);
+                safe_close(copy);
                 return -ENOMEM;
         }
 
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 016f8a1..bccf501 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -750,7 +750,7 @@ int bus_socket_exec(sd_bus *b) {
                 assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
 
                 if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
-                        close_nointr_nofail(s[1]);
+                        safe_close(s[1]);
 
                 fd_cloexec(STDIN_FILENO, false);
                 fd_cloexec(STDOUT_FILENO, false);
@@ -767,7 +767,7 @@ int bus_socket_exec(sd_bus *b) {
                 _exit(EXIT_FAILURE);
         }
 
-        close_nointr_nofail(s[1]);
+        safe_close(s[1]);
         b->output_fd = b->input_fd = s[0];
 
         bus_socket_setup(b);
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index ba8a8a2..2794a44 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -63,10 +63,10 @@ static void bus_close_fds(sd_bus *b) {
         detach_io_events(b);
 
         if (b->input_fd >= 0)
-                close_nointr_nofail(b->input_fd);
+                safe_close(b->input_fd);
 
         if (b->output_fd >= 0 && b->output_fd != b->input_fd)
-                close_nointr_nofail(b->output_fd);
+                safe_close(b->output_fd);
 
         b->input_fd = b->output_fd = -1;
 }
diff --git a/src/libsystemd/sd-bus/sd-memfd.c b/src/libsystemd/sd-bus/sd-memfd.c
index 8f9e236..fcf3e73 100644
--- a/src/libsystemd/sd-bus/sd-memfd.c
+++ b/src/libsystemd/sd-bus/sd-memfd.c
@@ -107,7 +107,7 @@ _public_ int sd_memfd_new(sd_memfd **m, const char *name) {
 
         n = new0(struct sd_memfd, 1);
         if (!n) {
-                close_nointr_nofail(cmd->fd);
+                safe_close(cmd->fd);
                 return -ENOMEM;
         }
 
@@ -144,7 +144,7 @@ _public_ void sd_memfd_free(sd_memfd *m) {
         if (m->f)
                 fclose(m->f);
         else
-                close_nointr_nofail(m->fd);
+                safe_close(m->fd);
 
         free(m);
 }
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index 113d15b..1b9d98f 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -232,7 +232,7 @@ static int server(sd_bus *bus) {
 
                         if (write(fd, &x, 1) < 0) {
                                 log_error("Failed to write to fd: %m");
-                                close_nointr_nofail(fd);
+                                safe_close(fd);
                                 goto fail;
                         }
 
diff --git a/src/libsystemd/sd-bus/test-bus-kernel-benchmark.c b/src/libsystemd/sd-bus/test-bus-kernel-benchmark.c
index bfeee59..90257d4 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel-benchmark.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel-benchmark.c
@@ -270,7 +270,7 @@ int main(int argc, char *argv[]) {
                 CPU_SET(0, &cpuset);
                 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
 
-                close_nointr_nofail(bus_ref);
+                safe_close(bus_ref);
                 sd_bus_unref(b);
 
                 switch (mode) {
diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c
index 2f0f5aa..34d000f 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel.c
@@ -137,14 +137,12 @@ int main(int argc, char *argv[]) {
 
         assert_se(write(pipe_fds[1], "x", 1) == 1);
 
-        close_nointr_nofail(pipe_fds[1]);
-        pipe_fds[1] = -1;
+        pipe_fds[1] = safe_close(pipe_fds[1]);
 
         r = sd_bus_message_append(m, "h", pipe_fds[0]);
         assert_se(r >= 0);
 
-        close_nointr_nofail(pipe_fds[0]);
-        pipe_fds[0] = -1;
+        pipe_fds[0] = safe_close(pipe_fds[0]);
 
         r = sd_bus_send(b, m, NULL);
         assert_se(r >= 0);
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index db76433..3bda7f3 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -331,20 +331,11 @@ static void event_free(sd_event *e) {
         if (e->default_event_ptr)
                 *(e->default_event_ptr) = NULL;
 
-        if (e->epoll_fd >= 0)
-                close_nointr_nofail(e->epoll_fd);
-
-        if (e->signal_fd >= 0)
-                close_nointr_nofail(e->signal_fd);
-
-        if (e->realtime_fd >= 0)
-                close_nointr_nofail(e->realtime_fd);
-
-        if (e->monotonic_fd >= 0)
-                close_nointr_nofail(e->monotonic_fd);
-
-        if (e->watchdog_fd >= 0)
-                close_nointr_nofail(e->watchdog_fd);
+        safe_close(e->epoll_fd);
+        safe_close(e->signal_fd);
+        safe_close(e->realtime_fd);
+        safe_close(e->monotonic_fd);
+        safe_close(e->watchdog_fd);
 
         prioq_free(e->pending);
         prioq_free(e->prepare);
@@ -673,7 +664,7 @@ static int event_setup_timer_fd(
 
         r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
         if (r < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -809,9 +800,7 @@ static int event_update_signal_fd(sd_event *e) {
 
         r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->signal_fd, &ev);
         if (r < 0) {
-                close_nointr_nofail(e->signal_fd);
-                e->signal_fd = -1;
-
+                e->signal_fd = safe_close(e->signal_fd);
                 return -errno;
         }
 
@@ -2272,8 +2261,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
         } else {
                 if (e->watchdog_fd >= 0) {
                         epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL);
-                        close_nointr_nofail(e->watchdog_fd);
-                        e->watchdog_fd = -1;
+                        e->watchdog_fd = safe_close(e->watchdog_fd);
                 }
         }
 
@@ -2281,8 +2269,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
         return e->watchdog;
 
 fail:
-        close_nointr_nofail(e->watchdog_fd);
-        e->watchdog_fd = -1;
+        e->watchdog_fd = safe_close(e->watchdog_fd);
         return r;
 }
 
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index d24b2ed..39445a1 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -775,7 +775,7 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
         if (!category || streq(category, "seat")) {
                 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
                 if (k < 0) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -errno;
                 }
 
@@ -785,7 +785,7 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
         if (!category || streq(category, "session")) {
                 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
                 if (k < 0) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -errno;
                 }
 
@@ -795,7 +795,7 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
         if (!category || streq(category, "uid")) {
                 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
                 if (k < 0) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -errno;
                 }
 
@@ -805,7 +805,7 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
         if (!category || streq(category, "machine")) {
                 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
                 if (k < 0) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -errno;
                 }
 
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index f05fe10..d810124 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -593,8 +593,7 @@ _public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
 
         /* Close all communication channels */
         for (i = 0; i < _FD_MAX; i++)
-                if (resolve->fds[i] >= 0)
-                        close_nointr_nofail(resolve->fds[i]);
+                safe_close(resolve->fds[i]);
 
         for (i = 0; i < QUERIES_MAX && resolve->n_queries > 0; i++)
                 if (resolve->queries[i])
diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 1c2c890..e5610b4 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -132,9 +132,7 @@ sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) {
                         free(f);
                 }
 
-                if (rtnl->fd >= 0)
-                        close_nointr_nofail(rtnl->fd);
-
+                safe_close(rtnl->fd);
                 free(rtnl);
         }
 
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index 060978d..2561d13 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -72,7 +72,7 @@ void button_free(Button *b) {
         if (b->fd >= 0) {
                 /* If the device has been unplugged close() returns
                  * ENODEV, let's ignore this, hence we don't use
-                 * close_nointr_nofail() */
+                 * safe_close() */
                 close(b->fd);
         }
 
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index d19d648..8b329ab 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -253,8 +253,7 @@ int inhibitor_load(Inhibitor *i) {
                 int fd;
 
                 fd = inhibitor_create_fifo(i);
-                if (fd >= 0)
-                        close_nointr_nofail(fd);
+                safe_close(fd);
         }
 
         return 0;
@@ -320,13 +319,8 @@ int inhibitor_create_fifo(Inhibitor *i) {
 void inhibitor_remove_fifo(Inhibitor *i) {
         assert(i);
 
-        if (i->event_source)
-                i->event_source = sd_event_source_unref(i->event_source);
-
-        if (i->fifo_fd >= 0) {
-                close_nointr_nofail(i->fifo_fd);
-                i->fifo_fd = -1;
-        }
+        i->event_source = sd_event_source_unref(i->event_source);
+        i->fifo_fd = safe_close(i->fifo_fd);
 
         if (i->fifo_path) {
                 unlink(i->fifo_path);
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 33ab09e..8c517f4 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -407,8 +407,7 @@ int session_load(Session *s) {
                    trigger the EOF. */
 
                 fd = session_create_fifo(s);
-                if (fd >= 0)
-                        close_nointr_nofail(fd);
+                safe_close(fd);
         }
 
         if (realtime) {
@@ -864,13 +863,8 @@ int session_create_fifo(Session *s) {
 static void session_remove_fifo(Session *s) {
         assert(s);
 
-        if (s->fifo_event_source)
-                s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
-
-        if (s->fifo_fd >= 0) {
-                close_nointr_nofail(s->fifo_fd);
-                s->fifo_fd = -1;
-        }
+        s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
+        s->fifo_fd = safe_close(s->fifo_fd);
 
         if (s->fifo_path) {
                 unlink(s->fifo_path);
@@ -950,7 +944,7 @@ static int session_open_vt(Session *s) {
         s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
         if (s->vtfd < 0) {
                 log_error("cannot open VT %s of session %s: %m", path, s->id);
-                return -1;
+                return -errno;
         }
 
         return s->vtfd;
@@ -1022,13 +1016,13 @@ void session_restore_vt(Session *s) {
 
         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
                 kb = K_UNICODE;
+
         ioctl(vt, KDSKBMODE, kb);
 
         mode.mode = VT_AUTO;
         ioctl(vt, VT_SETMODE, &mode);
 
-        close_nointr_nofail(vt);
-        s->vtfd = -1;
+        s->vtfd = safe_close(s->vtfd);
 }
 
 bool session_is_controller(Session *s, const char *sender) {
diff --git a/src/login/logind.c b/src/login/logind.c
index 8ba8a91..db98823 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -149,8 +149,7 @@ void manager_free(Manager *m) {
         sd_event_source_unref(m->udev_button_event_source);
         sd_event_source_unref(m->lid_switch_ignore_event_source);
 
-        if (m->console_active_fd >= 0)
-                close_nointr_nofail(m->console_active_fd);
+        safe_close(m->console_active_fd);
 
         if (m->udev_seat_monitor)
                 udev_monitor_unref(m->udev_seat_monitor);
@@ -169,8 +168,7 @@ void manager_free(Manager *m) {
         sd_bus_unref(m->bus);
         sd_event_unref(m->event);
 
-        if (m->reserve_vt_fd >= 0)
-                close_nointr_nofail(m->reserve_vt_fd);
+        safe_close(m->reserve_vt_fd);
 
         strv_free(m->kill_only_users);
         strv_free(m->kill_exclude_users);
diff --git a/src/login/pam-module.c b/src/login/pam-module.c
index 195d4d5..9873dd5 100644
--- a/src/login/pam-module.c
+++ b/src/login/pam-module.c
@@ -484,7 +484,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                 r = pam_set_data(handle, "systemd.session-fd", INT_TO_PTR(session_fd+1), NULL);
                 if (r != PAM_SUCCESS) {
                         pam_syslog(handle, LOG_ERR, "Failed to install session fd.");
-                        close_nointr_nofail(session_fd);
+                        safe_close(session_fd);
                         return r;
                 }
         }
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index 70b8314..70780c3 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -101,11 +101,11 @@ int main(int argc, char*argv[]) {
         assert(fd2 >= 0);
         print_inhibitors(bus);
 
-        close_nointr_nofail(fd1);
+        safe_close(fd1);
         sleep(1);
         print_inhibitors(bus);
 
-        close_nointr_nofail(fd2);
+        safe_close(fd2);
         sleep(1);
         print_inhibitors(bus);
 
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 2183d5c..d812ef2 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -439,8 +439,7 @@ static int openpt_in_namespace(pid_t pid, int flags) {
                 return -errno;
 
         if (child == 0) {
-                close_nointr_nofail(pair[0]);
-                pair[0] = -1;
+                pair[0] = safe_close(pair[0]);
 
                 r = namespace_enter(pidnsfd, mntnsfd, rootfd);
                 if (r < 0)
@@ -464,8 +463,7 @@ static int openpt_in_namespace(pid_t pid, int flags) {
                 _exit(EXIT_SUCCESS);
         }
 
-        close_nointr_nofail(pair[1]);
-        pair[1] = -1;
+        pair[1] = safe_close(pair[1]);
 
         r = wait_for_terminate(child, &si);
         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) {
diff --git a/src/network/sd-network.c b/src/network/sd-network.c
index 23af940..3b541a2 100644
--- a/src/network/sd-network.c
+++ b/src/network/sd-network.c
@@ -169,7 +169,7 @@ _public_ int sd_network_monitor_new(const char *category, sd_network_monitor **m
         if (!category || streq(category, "netif")) {
                 k = inotify_add_watch(fd, "/run/systemd/network/links/", IN_MOVED_TO|IN_DELETE);
                 if (k < 0) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -errno;
                 }
 
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index bb33de3..2d627db 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -986,7 +986,7 @@ static int setup_kmsg(const char *dest, int kmsg_socket) {
         /* Store away the fd in the socket, so that it stays open as
          * long as we run the child */
         k = sendmsg(kmsg_socket, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         if (k < 0) {
                 log_error("Failed to send FIFO fd: %m");
@@ -2304,8 +2304,7 @@ static void loop_remove(int nr, int *image_fd) {
 
         if (image_fd && *image_fd >= 0) {
                 ioctl(*image_fd, LOOP_CLR_FD);
-                close_nointr_nofail(*image_fd);
-                *image_fd = -1;
+                *image_fd = safe_close(*image_fd);
         }
 
         control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
@@ -2340,9 +2339,9 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
                         _exit(EXIT_FAILURE);
 
                 if (pipe_fds[0] > 2)
-                        close_nointr_nofail(pipe_fds[0]);
+                        safe_close(pipe_fds[0]);
                 if (pipe_fds[1] > 2)
-                        close_nointr_nofail(pipe_fds[1]);
+                        safe_close(pipe_fds[1]);
 
                 nullfd = open("/dev/null", O_RDWR);
                 if (nullfd < 0)
@@ -2355,7 +2354,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
                         _exit(EXIT_FAILURE);
 
                 if (nullfd > 2)
-                        close_nointr_nofail(nullfd);
+                        safe_close(nullfd);
 
                 reset_all_signal_handlers();
                 close_all_fds(NULL, 0);
@@ -2365,8 +2364,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
                 _exit(EXIT_FAILURE);
         }
 
-        close_nointr_nofail(pipe_fds[1]);
-        pipe_fds[1] = -1;
+        pipe_fds[1] = safe_close(pipe_fds[1]);
 
         *rpid = pid;
 
@@ -2808,15 +2806,13 @@ int main(int argc, char *argv[]) {
                         if (envp[n_env])
                                 n_env ++;
 
-                        close_nointr_nofail(master);
-                        master = -1;
+                        master = safe_close(master);
 
                         close_nointr(STDIN_FILENO);
                         close_nointr(STDOUT_FILENO);
                         close_nointr(STDERR_FILENO);
 
-                        close_nointr_nofail(kmsg_socket_pair[0]);
-                        kmsg_socket_pair[0] = -1;
+                        kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]);
 
                         reset_all_signal_handlers();
 
@@ -2826,7 +2822,7 @@ int main(int argc, char *argv[]) {
                         k = open_terminal(console, O_RDWR);
                         if (k != STDIN_FILENO) {
                                 if (k >= 0) {
-                                        close_nointr_nofail(k);
+                                        safe_close(k);
                                         k = -EINVAL;
                                 }
 
@@ -2899,8 +2895,7 @@ int main(int argc, char *argv[]) {
                         if (setup_kmsg(arg_directory, kmsg_socket_pair[1]) < 0)
                                 goto child_fail;
 
-                        close_nointr_nofail(kmsg_socket_pair[1]);
-                        kmsg_socket_pair[1] = -1;
+                        kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]);
 
                         if (setup_boot_id(arg_directory) < 0)
                                 goto child_fail;
@@ -2927,8 +2922,7 @@ int main(int argc, char *argv[]) {
                          * it can cgroupify us to that we lack access
                          * to certain devices and resources. */
                         eventfd_write(child_ready_fd, 1);
-                        close_nointr_nofail(child_ready_fd);
-                        child_ready_fd = -1;
+                        child_ready_fd = safe_close(child_ready_fd);
 
                         if (chdir(arg_directory) < 0) {
                                 log_error("chdir(%s) failed: %m", arg_directory);
@@ -3029,8 +3023,7 @@ int main(int argc, char *argv[]) {
 
                         /* Wait until the parent is ready with the setup, too... */
                         eventfd_read(parent_ready_fd, &x);
-                        close_nointr_nofail(parent_ready_fd);
-                        parent_ready_fd = -1;
+                        parent_ready_fd = safe_close(parent_ready_fd);
 
                         if (arg_boot) {
                                 char **a;
diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c
index be92006..c1afd0d 100644
--- a/src/readahead/readahead-collect.c
+++ b/src/readahead/readahead-collect.c
@@ -176,8 +176,7 @@ finish:
         if (start != MAP_FAILED)
                 munmap(start, l);
 
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -493,16 +492,12 @@ static int collect(const char *root) {
                                 log_warning("readlink(%s) failed: %s", fn, strerror(-k));
 
                 next_iteration:
-                        if (m->fd >= 0)
-                                close_nointr_nofail(m->fd);
+                        safe_close(m->fd);
                 }
         }
 
 done:
-        if (fanotify_fd >= 0) {
-                close_nointr_nofail(fanotify_fd);
-                fanotify_fd = -1;
-        }
+        fanotify_fd = safe_close(fanotify_fd);
 
         log_debug("Writing Pack File...");
 
@@ -592,14 +587,9 @@ done:
         log_debug("Done.");
 
 finish:
-        if (fanotify_fd >= 0)
-                close_nointr_nofail(fanotify_fd);
-
-        if (signal_fd >= 0)
-                close_nointr_nofail(signal_fd);
-
-        if (inotify_fd >= 0)
-                close_nointr_nofail(inotify_fd);
+        safe_close(fanotify_fd);
+        safe_close(signal_fd);
+        safe_close(inotify_fd);
 
         if (pack) {
                 fclose(pack);
diff --git a/src/readahead/readahead-common.c b/src/readahead/readahead-common.c
index aea1fbe..5ffa88b 100644
--- a/src/readahead/readahead-common.c
+++ b/src/readahead/readahead-common.c
@@ -220,7 +220,7 @@ int open_inotify(void) {
 
         if (inotify_add_watch(fd, "/run/systemd/readahead", IN_CREATE) < 0) {
                 log_error("Failed to watch /run/systemd/readahead: %m");
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c
index cb04e5f..8dc1942 100644
--- a/src/readahead/readahead-replay.c
+++ b/src/readahead/readahead-replay.c
@@ -67,10 +67,8 @@ static int unpack_file(FILE *pack) {
                 if (errno != ENOENT && errno != EPERM && errno != EACCES && errno != ELOOP)
                         log_warning("open(%s) failed: %m", fn);
 
-        } else if (file_verify(fd, fn, arg_file_size_max, &st) <= 0) {
-                close_nointr_nofail(fd);
-                fd = -1;
-        }
+        } else if (file_verify(fd, fn, arg_file_size_max, &st) <= 0)
+                fd = safe_close(fd);
 
         if (fread(&inode, sizeof(inode), 1, pack) != 1) {
                 log_error("Premature end of pack file.");
@@ -81,10 +79,8 @@ static int unpack_file(FILE *pack) {
         if (fd >= 0) {
                 /* If the inode changed the file got deleted, so just
                  * ignore this entry */
-                if (st.st_ino != (uint64_t) inode) {
-                        close_nointr_nofail(fd);
-                        fd = -1;
-                }
+                if (st.st_ino != (uint64_t) inode)
+                        fd = safe_close(fd);
         }
 
         for (;;) {
@@ -129,8 +125,7 @@ static int unpack_file(FILE *pack) {
         }
 
 finish:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -279,8 +274,7 @@ finish:
         if (pack)
                 fclose(pack);
 
-        if (inotify_fd >= 0)
-                close_nointr_nofail(inotify_fd);
+        safe_close(inotify_fd);
 
         free(pack_fn);
 
diff --git a/src/reply-password/reply-password.c b/src/reply-password/reply-password.c
index 2f16898..c730216 100644
--- a/src/reply-password/reply-password.c
+++ b/src/reply-password/reply-password.c
@@ -91,7 +91,8 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
+        fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0) {
                 log_error("socket() failed: %m");
                 goto finish;
         }
@@ -102,8 +103,7 @@ int main(int argc, char *argv[]) {
         r = EXIT_SUCCESS;
 
 finish:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index a328f14..117f0c6 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -226,8 +226,7 @@ int ask_password_tty(
         r = 0;
 
 finish:
-        if (notify >= 0)
-                close_nointr_nofail(notify);
+        safe_close(notify);
 
         if (ttyfd >= 0) {
 
@@ -236,7 +235,7 @@ finish:
                         tcsetattr(ttyfd, TCSADRAIN, &old_termios);
                 }
 
-                close_nointr_nofail(ttyfd);
+                safe_close(ttyfd);
         }
 
         return r;
@@ -290,7 +289,7 @@ static int create_socket(char **name) {
         return fd;
 
 fail:
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -521,19 +520,15 @@ int ask_password_agent(
         r = 0;
 
 finish:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         if (socket_name) {
                 unlink(socket_name);
                 free(socket_name);
         }
 
-        if (socket_fd >= 0)
-                close_nointr_nofail(socket_fd);
-
-        if (signal_fd >= 0)
-                close_nointr_nofail(signal_fd);
+        safe_close(socket_fd);
+        safe_close(signal_fd);
 
         if (f)
                 fclose(f);
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
index fd27398..a2c861d 100644
--- a/src/shared/fdset.c
+++ b/src/shared/fdset.c
@@ -82,7 +82,7 @@ int fdset_put_dup(FDSet *s, int fd) {
 
         r = fdset_put(s, copy);
         if (r < 0) {
-                close_nointr_nofail(copy);
+                safe_close(copy);
                 return r;
         }
 
diff --git a/src/shared/install.c b/src/shared/install.c
index f57b94d..7409046 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -204,7 +204,7 @@ static int remove_marked_symlinks_fd(
 
         d = fdopendir(fd);
         if (!d) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -244,7 +244,7 @@ static int remove_marked_symlinks_fd(
 
                         p = path_make_absolute(de->d_name, path);
                         if (!p) {
-                                close_nointr_nofail(nfd);
+                                safe_close(nfd);
                                 return -ENOMEM;
                         }
 
@@ -344,7 +344,7 @@ static int remove_marked_symlinks(
                         r = q;
         } while (deleted);
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -367,7 +367,7 @@ static int find_symlinks_fd(
 
         d = fdopendir(fd);
         if (!d) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -403,7 +403,7 @@ static int find_symlinks_fd(
 
                         p = path_make_absolute(de->d_name, path);
                         if (!p) {
-                                close_nointr_nofail(nfd);
+                                safe_close(nfd);
                                 return -ENOMEM;
                         }
 
@@ -1008,7 +1008,7 @@ static int unit_file_load(
 
         f = fdopen(fd, "re");
         if (!f) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOMEM;
         }
 
diff --git a/src/shared/log.c b/src/shared/log.c
index 5ea1e3a..a4b3b68 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -62,7 +62,7 @@ void log_close_console(void) {
 
         if (getpid() == 1) {
                 if (console_fd >= 3)
-                        close_nointr_nofail(console_fd);
+                        safe_close(console_fd);
 
                 console_fd = -1;
         }
@@ -84,12 +84,7 @@ static int log_open_console(void) {
 }
 
 void log_close_kmsg(void) {
-
-        if (kmsg_fd < 0)
-                return;
-
-        close_nointr_nofail(kmsg_fd);
-        kmsg_fd = -1;
+        kmsg_fd = safe_close(kmsg_fd);
 }
 
 static int log_open_kmsg(void) {
@@ -105,12 +100,7 @@ static int log_open_kmsg(void) {
 }
 
 void log_close_syslog(void) {
-
-        if (syslog_fd < 0)
-                return;
-
-        close_nointr_nofail(syslog_fd);
-        syslog_fd = -1;
+        syslog_fd = safe_close(syslog_fd);
 }
 
 static int create_log_socket(int type) {
@@ -152,7 +142,7 @@ static int log_open_syslog(void) {
         }
 
         if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
-                close_nointr_nofail(syslog_fd);
+                safe_close(syslog_fd);
 
                 /* Some legacy syslog systems still use stream
                  * sockets. They really shouldn't. But what can we
@@ -180,12 +170,7 @@ fail:
 }
 
 void log_close_journal(void) {
-
-        if (journal_fd < 0)
-                return;
-
-        close_nointr_nofail(journal_fd);
-        journal_fd = -1;
+        journal_fd = safe_close(journal_fd);
 }
 
 static int log_open_journal(void) {
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index f7d84fc..df49375 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -1171,8 +1171,7 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
         if (child == 0) {
                 int fd;
 
-                close_nointr_nofail(pair[0]);
-                pair[0] = -1;
+                pair[0] = safe_close(pair[0]);
 
                 r = namespace_enter(pidnsfd, mntnsfd, rootfd);
                 if (r < 0)
@@ -1183,7 +1182,7 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
                         _exit(EXIT_FAILURE);
 
                 k = loop_read(fd, buf, 36, false);
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 if (k != 36)
                         _exit(EXIT_FAILURE);
 
@@ -1194,8 +1193,7 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
                 _exit(EXIT_SUCCESS);
         }
 
-        close_nointr_nofail(pair[1]);
-        pair[1] = -1;
+        pair[1] = safe_close(pair[1]);
 
         r = wait_for_terminate(child, &si);
         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index f9e52cd..fccf1e9 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -61,7 +61,7 @@ int polkit_agent_open(void) {
                        POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL);
 
         /* Close the writing side, because that's the one for the agent */
-        close_nointr_nofail(pipe_fd[1]);
+        safe_close(pipe_fd[1]);
 
         if (r < 0)
                 log_error("Failed to fork TTY ask password agent: %s", strerror(-r));
@@ -69,7 +69,7 @@ int polkit_agent_open(void) {
                 /* Wait until the agent closes the fd */
                 fd_wait_for_event(pipe_fd[0], POLLHUP, (usec_t) -1);
 
-        close_nointr_nofail(pipe_fd[0]);
+        safe_close(pipe_fd[0]);
 
         return r;
 }
diff --git a/src/shared/util.c b/src/shared/util.c
index 75870fc..a8c4523 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -183,13 +183,22 @@ int close_nointr(int fd) {
                 return -errno;
 }
 
-void close_nointr_nofail(int fd) {
-        PROTECT_ERRNO;
+int safe_close(int fd) {
+
+        /*
+         * Like close_nointr() but cannot fail. Guarantees errno is
+         * unchanged. Is a NOP with negative fds passed, and returns
+         * -1, so that it can be used in this syntax:
+         *
+         * fd = safe_close(fd);
+         */
 
-        /* like close_nointr() but cannot fail, and guarantees errno
-         * is unchanged */
+        if (fd >= 0) {
+                PROTECT_ERRNO;
+                assert_se(close_nointr(fd) == 0);
+        }
 
-        assert_se(close_nointr(fd) == 0);
+        return -1;
 }
 
 void close_many(const int fds[], unsigned n_fd) {
@@ -198,7 +207,7 @@ void close_many(const int fds[], unsigned n_fd) {
         assert(fds || n_fd <= 0);
 
         for (i = 0; i < n_fd; i++)
-                close_nointr_nofail(fds[i]);
+                safe_close(fds[i]);
 }
 
 int unlink_noerrno(const char *path) {
@@ -1693,16 +1702,13 @@ finish:
 }
 
 int reset_terminal(const char *name) {
-        int fd, r;
+        _cleanup_close_ int fd = -1;
 
         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
                 return fd;
 
-        r = reset_terminal_fd(fd, true);
-        close_nointr_nofail(fd);
-
-        return r;
+        return reset_terminal_fd(fd, true);
 }
 
 int open_terminal(const char *name, int mode) {
@@ -1741,12 +1747,12 @@ int open_terminal(const char *name, int mode) {
 
         r = isatty(fd);
         if (r < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         if (!r) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOTTY;
         }
 
@@ -1935,11 +1941,10 @@ int acquire_terminal(
                  * ended our handle will be dead. It's important that
                  * we do this after sleeping, so that we don't enter
                  * an endless loop. */
-                close_nointr_nofail(fd);
+                safe_close(fd);
         }
 
-        if (notify >= 0)
-                close_nointr_nofail(notify);
+        safe_close(notify);
 
         r = reset_terminal_fd(fd, true);
         if (r < 0)
@@ -1948,11 +1953,8 @@ int acquire_terminal(
         return fd;
 
 fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
-
-        if (notify >= 0)
-                close_nointr_nofail(notify);
+        safe_close(fd);
+        safe_close(notify);
 
         return r;
 }
@@ -2262,7 +2264,7 @@ int make_stdio(int fd) {
         t = dup3(fd, STDERR_FILENO, 0);
 
         if (fd >= 3)
-                close_nointr_nofail(fd);
+                safe_close(fd);
 
         if (r < 0 || s < 0 || t < 0)
                 return -errno;
@@ -2640,7 +2642,7 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
 
         d = fdopendir(fd);
         if (!d) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
 
                 return errno == ENOENT ? 0 : -errno;
         }
@@ -2736,7 +2738,7 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root
         assert(fd >= 0);
 
         if (fstatfs(fd, &s) < 0) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -2745,7 +2747,7 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root
          * non-state data */
         if (!is_temporary_fs(&s)) {
                 log_error("Attempted to remove disk file system, and we can't allow that.");
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -EPERM;
         }
 
@@ -2791,13 +2793,13 @@ static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bo
 
         if (!dangerous) {
                 if (fstatfs(fd, &s) < 0) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -errno;
                 }
 
                 if (!is_temporary_fs(&s)) {
                         log_error("Attempted to remove disk file system, and we can't allow that.");
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return -EPERM;
                 }
         }
@@ -3318,7 +3320,7 @@ char *ellipsize(const char *s, size_t length, unsigned percent) {
 }
 
 int touch(const char *path) {
-        int fd;
+        _cleanup_close_ int fd;
 
         assert(path);
 
@@ -3330,7 +3332,6 @@ int touch(const char *path) {
         if (fd < 0)
                 return -errno;
 
-        close_nointr_nofail(fd);
         return 0;
 }
 
@@ -3493,7 +3494,7 @@ DIR *xopendirat(int fd, const char *name, int flags) {
 
         d = fdopendir(nfd);
         if (!d) {
-                close_nointr_nofail(nfd);
+                safe_close(nfd);
                 return NULL;
         }
 
@@ -3987,16 +3988,13 @@ int terminal_vhangup_fd(int fd) {
 }
 
 int terminal_vhangup(const char *name) {
-        int fd, r;
+        _cleanup_close_ int fd;
 
         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
                 return fd;
 
-        r = terminal_vhangup_fd(fd);
-        close_nointr_nofail(fd);
-
-        return r;
+        return terminal_vhangup_fd(fd);
 }
 
 int vt_disallocate(const char *name) {
@@ -4023,7 +4021,7 @@ int vt_disallocate(const char *name) {
                            "\033[H"    /* move home */
                            "\033[2J",  /* clear screen */
                            10, false);
-                close_nointr_nofail(fd);
+                safe_close(fd);
 
                 return 0;
         }
@@ -4044,7 +4042,7 @@ int vt_disallocate(const char *name) {
                 return fd;
 
         r = ioctl(fd, VT_DISALLOCATE, u);
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         if (r >= 0)
                 return 0;
@@ -4063,7 +4061,7 @@ int vt_disallocate(const char *name) {
                    "\033[H"   /* move home */
                    "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
                    10, false);
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         return 0;
 }
@@ -5640,7 +5638,7 @@ int on_ac_power(void) {
                 if (n != 6 || memcmp(contents, "Mains\n", 6))
                         continue;
 
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
                 if (fd < 0) {
                         if (errno == ENOENT)
diff --git a/src/shared/util.h b/src/shared/util.h
index 7752b1e..70c20fd 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -149,7 +149,8 @@ char *endswith(const char *s, const char *postfix) _pure_;
 bool first_word(const char *s, const char *word) _pure_;
 
 int close_nointr(int fd);
-void close_nointr_nofail(int fd);
+int safe_close(int fd);
+
 void close_many(const int fds[], unsigned n_fd);
 
 int parse_size(const char *t, off_t base, off_t *size);
@@ -620,8 +621,7 @@ static inline void freep(void *p) {
         struct __useless_struct_to_allow_trailing_semicolon__
 
 static inline void closep(int *fd) {
-        if (*fd >= 0)
-                close_nointr_nofail(*fd);
+        safe_close(*fd);
 }
 
 static inline void umaskp(mode_t *u) {
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
index ddbe7af..ba9ad9b 100644
--- a/src/shared/watchdog.c
+++ b/src/shared/watchdog.c
@@ -164,6 +164,5 @@ void watchdog_close(bool disarm) {
                 }
         }
 
-        close_nointr_nofail(watchdog_fd);
-        watchdog_fd = -1;
+        watchdog_fd = safe_close(watchdog_fd);
 }
diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c
index fafd9ce..578920c 100644
--- a/src/shutdownd/shutdownd.c
+++ b/src/shutdownd/shutdownd.c
@@ -430,8 +430,7 @@ int main(int argc, char *argv[]) {
 finish:
 
         for (i = 0; i < _FD_MAX; i++)
-                if (pollfd[i].fd >= 0)
-                        close_nointr_nofail(pollfd[i].fd);
+                safe_close(pollfd[i].fd);
 
         if (unlink_nologin)
                 unlink("/run/nologin");
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index a42e5ae..c172beb 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -76,10 +76,8 @@ static void connection_free(Connection *c) {
         sd_event_source_unref(c->server_event_source);
         sd_event_source_unref(c->client_event_source);
 
-        if (c->server_fd >= 0)
-                close_nointr_nofail(c->server_fd);
-        if (c->client_fd >= 0)
-                close_nointr_nofail(c->client_fd);
+        safe_close(c->server_fd);
+        safe_close(c->client_fd);
 
         close_pipe(c->server_to_client_buffer);
         close_pipe(c->client_to_server_buffer);
@@ -224,8 +222,7 @@ static int connection_shovel(
                                 shoveled = true;
                         } else if (z == 0 || errno == EPIPE || errno == ECONNRESET) {
                                 *from_source = sd_event_source_unref(*from_source);
-                                close_nointr_nofail(*from);
-                                *from = -1;
+                                *from = safe_close(*from);
                         } else if (errno != EAGAIN && errno != EINTR) {
                                 log_error("Failed to splice: %m");
                                 return -errno;
@@ -239,8 +236,7 @@ static int connection_shovel(
                                 shoveled = true;
                         } else if (z == 0 || errno == EPIPE || errno == ECONNRESET) {
                                 *to_source = sd_event_source_unref(*to_source);
-                                close_nointr_nofail(*to);
-                                *to = -1;
+                                *to = safe_close(*to);
                         } else if (errno != EAGAIN && errno != EINTR) {
                                 log_error("Failed to splice: %m");
                                 return -errno;
@@ -396,7 +392,7 @@ static int add_connection_socket(Context *context, sd_event *event, int fd) {
 
         if (set_size(context->connections) > CONNECTIONS_MAX) {
                 log_warning("Hit connection limit, refusing connection.");
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return 0;
         }
 
@@ -482,7 +478,7 @@ static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdat
                 r = add_connection_socket(context, sd_event_source_get_event(s), nfd);
                 if (r < 0) {
                         log_error("Failed to accept connection, ignoring: %s", strerror(-r));
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                 }
         }
 
diff --git a/src/test/test-util.c b/src/test/test-util.c
index a624772..1d952eb 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -67,7 +67,7 @@ static void test_close_many(void) {
         assert_se(fcntl(fds[1], F_GETFD) == -1);
         assert_se(fcntl(fds[2], F_GETFD) >= 0);
 
-        close_nointr_nofail(fds[2]);
+        safe_close(fds[2]);
 
         unlink(name0);
         unlink(name1);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 74a0127..33e7cbc 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -496,7 +496,7 @@ static int write_one_file(Item *i, const char *path) {
 
                 unescaped = cunescape(i->argument);
                 if (unescaped == NULL) {
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return log_oom();
                 }
 
@@ -505,12 +505,12 @@ static int write_one_file(Item *i, const char *path) {
 
                 if (n < 0 || (size_t) n < l) {
                         log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
-                        close_nointr_nofail(fd);
+                        safe_close(fd);
                         return n < 0 ? n : -EIO;
                 }
         }
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         if (stat(path, &st) < 0) {
                 log_error("stat(%s) failed: %m", path);
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index fa4d660..1d067af 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -234,11 +234,8 @@ static int ask_password_plymouth(
         r = 0;
 
 finish:
-        if (notify >= 0)
-                close_nointr_nofail(notify);
-
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(notify);
+        safe_close(fd);
 
         free(packet);
 
@@ -372,7 +369,7 @@ static int parse_password(const char *filename, char **wall) {
                         r = ask_password_tty(message, not_after, filename, &password);
 
                         if (arg_console) {
-                                close_nointr_nofail(tty_fd);
+                                safe_close(tty_fd);
                                 release_terminal();
                         }
 
@@ -419,8 +416,7 @@ static int parse_password(const char *filename, char **wall) {
 finish:
         fclose(f);
 
-        if (socket_fd >= 0)
-                close_nointr_nofail(socket_fd);
+        safe_close(socket_fd);
 
         free(packet);
         free(socket_name);
@@ -492,7 +488,7 @@ static bool wall_tty_match(const char *path) {
                 return true;
 
         /* What, we managed to open the pipe? Then this tty is filtered. */
-        close_nointr_nofail(fd);
+        safe_close(fd);
         return false;
 }
 
@@ -614,14 +610,9 @@ static int watch_passwords(void) {
         r = 0;
 
 finish:
-        if (notify >= 0)
-                close_nointr_nofail(notify);
-
-        if (signal_fd >= 0)
-                close_nointr_nofail(signal_fd);
-
-        if (tty_block_fd >= 0)
-                close_nointr_nofail(tty_block_fd);
+        safe_close(notify);
+        safe_close(signal_fd);
+        safe_close(tty_block_fd);
 
         return r;
 }
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index d3f1aff..62439c0 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -127,8 +127,7 @@ void link_config_ctx_free(link_config_ctx *ctx) {
         if (!ctx)
                 return;
 
-        if (ctx->ethtool_fd >= 0)
-                close_nointr_nofail(ctx->ethtool_fd);
+        safe_close(ctx->ethtool_fd);
 
         sd_rtnl_unref(ctx->rtnl);
 
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index 1bbf737..0f2b706 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -301,8 +301,7 @@ finish:
         free(vc_font_map);
         free(vc_font_unimap);
 
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }

commit 9459781ee66eb57709c8b8701701365ba60a9f1c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 17:59:11 2014 +0100

    udate TODO

diff --git a/TODO b/TODO
index 99cbb9f..9ffe6b0 100644
--- a/TODO
+++ b/TODO
@@ -47,7 +47,8 @@ Features:
 
 * support transient mount units
 
-* Imply DevicePolicy=closed and CapabilityBoundingSet=~CAP_SYS_MKNOD when PrivateDevices= is used
+* Imply DevicePolicy=closed when PrivateDevices= is used. Mount
+  pts+kdbus+shm+mqueue into /dev namespace
 
 * add an "input" group to udev logic and add all input devices to it
 

commit f1660f96f59dad860d39f148c3a747050d112763
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 18 17:58:19 2014 +0100

    core: drop CAP_MKNOD when PrivateDevices= is set

diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index f1bcf9b..90d36f9 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -908,8 +908,11 @@
                                 <filename>/dev/sda</filename>. This is
                                 useful to securely turn off physical
                                 device access by the executed
-                                process. Defaults to
-                                false.</para></listitem>
+                                process. Defaults to false. Note that
+                                enabling this option implies that
+                                <constant>CAP_MKNOD</constant> is
+                                removed from the capability bounding
+                                set for the unit.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
diff --git a/src/core/unit.c b/src/core/unit.c
index 4fb0d9c..20b139d 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2830,6 +2830,9 @@ int unit_exec_context_patch_defaults(Unit *u, ExecContext *c) {
              !set_isempty(c->address_families)))
                 c->no_new_privileges = true;
 
+        if (c->private_devices)
+                c->capability_bounding_set_drop |= (uint64_t) 1ULL << (uint64_t) CAP_MKNOD;
+
         return 0;
 }
 



More information about the systemd-commits mailing list