]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #9614 from poettering/negative-sec
authorLennart Poettering <lennart@poettering.net>
Fri, 20 Jul 2018 11:22:01 +0000 (13:22 +0200)
committerGitHub <noreply@github.com>
Fri, 20 Jul 2018 11:22:01 +0000 (13:22 +0200)
parse-util: make sure "-0.-0s" is not considered a valid time specifi…

37 files changed:
.gitignore
README
hwdb/60-evdev.hwdb
hwdb/60-keyboard.hwdb
hwdb/60-sensor.hwdb
man/resolvectl.xml
man/systemctl.xml
man/systemd.exec.xml
man/systemd.journal-fields.xml
man/systemd.resource-control.xml
man/systemd.service.xml
meson.build
src/analyze/analyze.c
src/basic/macro.h
src/basic/missing.h
src/hostname/hostnamed.c
src/journal/journald-syslog.c
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/bus-slot.c
src/libsystemd/sd-bus/bus-slot.h
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-bus/sd-bus.c
src/locale/localed.c
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd.c
src/network/test-network.c
src/resolve/resolvectl.c
src/resolve/resolved-bus.c
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/sleep/sleep.c
src/systemctl/systemctl.c
src/timedate/timedated.c
src/timesync/timesyncd-manager.c
test/test-functions

index 197000235041a032cefb680988d9951d88b4a49c..4e651f4762702d50b27983a9b02c16e70c11cbec 100644 (file)
@@ -10,6 +10,7 @@
 *.trs
 *~
 .config.args
+.gdb_history
 .deps/
 /*.gcda
 /*.gcno
diff --git a/README b/README
index 61a1fd45bfe1c3536eb841ff4e74d50755ade6ad..82f47a59ab6cfbcf40bbab58ca1e87568e3d4b04 100644 (file)
--- a/README
+++ b/README
@@ -205,10 +205,12 @@ REQUIREMENTS:
         make use of DynamicUser= now, hence enabling nss-systemd is not
         optional.
 
-        Note that the build prefix for systemd must be /usr. -Dsplit-usr=false
-        (which is the default and does not need to be specified) is the
-        recommended setting, and -Dsplit-usr=true should be used on systems
-        which have /usr on a separate partition.
+        Note that the build prefix for systemd must be /usr. (Moreover,
+        packages systemd relies on — such as D-Bus — really should use the same
+        prefix, otherwise you are on your own.) -Dsplit-usr=false (which is the
+        default and does not need to be specified) is the recommended setting,
+        and -Dsplit-usr=true should be used on systems which have /usr on a
+        separate partition.
 
         Additional packages are necessary to run some tests:
         - busybox            (used by test/TEST-13-NSPAWN-SMOKE)
index cc223d6545742cc456d74ce3b4f2abd0aa08450a..7a9c4c6337bca993c9e8b09a6134e81b9ba835f2 100644 (file)
@@ -243,6 +243,13 @@ evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus*
 # HP
 #########################################
 
+# HP Chromebook 14 (Falco)
+evdev:name:Cypress APA Trackpad ?cyapa?:dmi:*:svnHewlett-Packard*:pnFalco*:
+ EVDEV_ABS_00=:::8
+ EVDEV_ABS_01=:::8
+ EVDEV_ABS_35=:::8
+ EVDEV_ABS_36=:::8
+
 # HP Pavilion dm4
 evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4*
  EVDEV_ABS_00=1360:5563:47
index dd7cc6636041524c6f9059297b355480c0c62ae8..b608e7b074381f0d984f87ba36aa7d19d11766cd 100644 (file)
@@ -219,6 +219,16 @@ evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:pvr*
  KEYBOARD_KEY_6e=wlan
 
+###########################################################
+# Clevo
+###########################################################
+
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnNotebook:pnW65_67SZ:pvr*
+ KEYBOARD_KEY_a0=!mute
+ KEYBOARD_KEY_a2=!playpause
+ KEYBOARD_KEY_ae=!volumedown
+ KEYBOARD_KEY_b0=!volumeup
+
 ###########################################################
 # Compal
 ###########################################################
@@ -746,9 +756,9 @@ evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
  KEYBOARD_KEY_f1=f21
 
-# Lenovo Thinkcentre M800z AIO machine
+# Lenovo ThinkCentre M800z/M820z/M920z AIO machines
 # key_scancode 00 is KEY_MICMUTE
-keyboard:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+evdev:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
  KEYBOARD_KEY_00=f20
 
 # enhanced USB keyboard
index eebe85a947a51fa46aa4a65d407b038f6c867a6a..4b165537a7ae14757555adefd6fa27e458ef2d39 100644 (file)
@@ -281,6 +281,10 @@ sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XE:*
 sensor:modalias:acpi:BOSC0200*:dmi:*:svnLINX*:pnLINX1010B:*
  ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, -1
 
+# Linx 12X64
+sensor:modalias:acpi:KIOX000A*:dmi:*:svnLINX*:pnLINX12X64:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
 #########################################
 # MSI
 #########################################
index ff5b8ad1018c394c43e18fc9b6eb911ea40aac45..cf97628f86be2c8064d1a51d87d7f76793a6f4a6 100644 (file)
         <literal>~</literal>, and configures a per-interface search or route-only domain. The <option>llmnr</option>,
         <option>mdns</option>, <option>dnssec</option> and <option>dnsovertls</option> commands may be used to configure
         the per-interface LLMNR, MulticastDNS, DNSSEC and DNSOverTLS settings. Finally, <option>nta</option> command
-        may be used to configure additional per-interface DNSSEC NTA domains. For details about these settings, their
-        possible values and their effect, see the corresponding options in
+        may be used to configure additional per-interface DNSSEC NTA domains.</para></listitem>
+
+        <listitem><para>Options <option>dns</option>, <option>domain</option> and <option>nta</option> can take
+        a single empty string argument to clear their respective value lists.</para></listitem>
+
+        <listitem><para>For details about these settings, their possible values and their effect, see the corresponding options in
         <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
         </listitem>
       </varlistentry>
index a70bdb40d7f99ddd9a4b3c79640e0b48beb5e7de..3cde402a1b6a31ae47555ee78556151c2ca58f1f 100644 (file)
         <term><option>--ignore-inhibitors</option></term>
 
         <listitem>
-          <para>When system shutdown or a sleep state is requested,
-          ignore inhibitor locks. Applications can establish inhibitor
-          locks to avoid that certain important operations (such as CD
-          burning or suchlike) are interrupted by system shutdown or a
-          sleep state. Any user may take these locks and privileged
-          users may override these locks. If any locks are taken,
-          shutdown and sleep state requests will normally fail
-          (regardless of whether privileged or not) and a list of active locks
-          is printed. However, if <option>--ignore-inhibitors</option>
-          is specified, the locks are ignored and not printed, and the
-          operation attempted anyway, possibly requiring additional
-          privileges.</para>
+          <para>When system shutdown or a sleep state is requested, ignore inhibitor locks. Applications can establish
+          inhibitor locks to avoid that certain important operations (such as CD burning or suchlike) are interrupted
+          by system shutdown or a sleep state. Any user may take these locks and privileged users may override these
+          locks. If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged) and a
+          list of active locks is printed. However, if <option>--ignore-inhibitors</option> is specified, the
+          established locks are ignored and not shown, and the operation attempted anyway, possibly requiring
+          additional privileges.</para>
         </listitem>
       </varlistentry>
 
   boot-efi.mount               loaded active mounted /boot/efi
   systemd-journald.service     loaded active running Journal Service
   systemd-logind.service       loaded active running Login Service
-● user@1000.service            loaded active running User Manager for UID 1000
-…
+● user@1000.service            loaded failed failed  User Manager for UID 1000
+  
   systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories
 
 LOAD   = Reflects whether the unit definition was properly loaded.
index 23c9f5a4582dd381a2939a5d43e8fbda17033a62..ccf79b21d6e6448f8a31caeb026560f1c96cdb28 100644 (file)
@@ -1046,9 +1046,13 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
         Defaults to false. It is possible to run two or more units within the same private network namespace by using
         the <varname>JoinsNamespaceOf=</varname> directive, see
         <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
-        details. Note that this option will disconnect all socket families from the host, this includes AF_NETLINK and
-        AF_UNIX.  The latter has the effect that AF_UNIX sockets in the abstract socket namespace will become
-        unavailable to the processes (however, those located in the file system will continue to be accessible).</para>
+        details. Note that this option will disconnect all socket families from the host, including
+        <constant>AF_NETLINK</constant> and <constant>AF_UNIX</constant>. Effectively, for
+        <constant>AF_NETLINK</constant> this means that device configuration events received from
+        <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> are
+        not delivered to the unit's processes. And for <constant>AF_UNIX</constant> this has the effect that
+        <constant>AF_UNIX</constant> sockets in the abstract socket namespace of the host will become unavailable to
+        the unit's processes (however, those located in the file system will continue to be accessible).</para>
 
         <para>Note that the implementation of this setting might be impossible (for example if network namespaces are
         not available), and the unit should be written in a way that does not solely rely on this setting for
index c079274c324d0409cba16c960f33113845555d57..942c6ba91a3582ae62d07415138d6d32425ddd69 100644 (file)
         <term><varname>SYSLOG_FACILITY=</varname></term>
         <term><varname>SYSLOG_IDENTIFIER=</varname></term>
         <term><varname>SYSLOG_PID=</varname></term>
+        <term><varname>SYSLOG_TIMESTAMP=</varname></term>
         <listitem>
-          <para>Syslog compatibility fields containing the facility
-          (formatted as decimal string), the identifier string (i.e.
-          "tag"), and the client PID. (Note that the tag is usually
-          derived from glibc's
-          <varname>program_invocation_short_name</varname> variable,
-          see
+          <para>Syslog compatibility fields containing the facility (formatted as
+          decimal string), the identifier string (i.e.  "tag"), the client PID, and
+          the timestamp as specified in the original datagram. (Note that the tag is
+          usually derived from glibc's
+          <varname>program_invocation_short_name</varname> variable, see
           <citerefentry project='die-net'><refentrytitle>program_invocation_short_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.)</para>
         </listitem>
+      </varlistentry>
 
+      <varlistentry>
+        <term><varname>SYSLOG_RAW=</varname></term>
+        <listitem>
+          <para>The original contents of the syslog line as received in the syslog
+          datagram. This field is only included if the <varname>MESSAGE=</varname>
+          field was modified compared to the original payload or the timestamp could
+          not be located properly and is not included in
+          <varname>SYSLOG_TIMESTAMP=</varname>. Message truncation occurs when when
+          the message contains leading or trailing whitespace (trailing and leading
+          whitespace is stripped), or it contains an embedded
+          <constant>NUL</constant> byte (the <constant>NUL</constant> byte and
+          anything after it is not included). Thus, the original syslog line is
+          either stored as <varname>SYSLOG_RAW=</varname> or it can be recreated
+          based on the stored priority and facility, timestamp, identifier, and the
+          message payload in <varname>MESSAGE=</varname>.
+          </para>
+        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
index 8ebd162be799602b5a1703cfa0adb8aaef97a5aa..dffadb39bc08a627ad0d5fc5674f7a96765fa21b 100644 (file)
           <literal>cpu.max</literal> attribute on the unified control group hierarchy and
           <literal>cpu.cfs_quota_us</literal> on legacy. For details about these control group attributes, see <ulink
           url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink> and <ulink
-          url="https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt">sched-design-CFS.txt</ulink>.</para>
+          url="https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt">sched-bwc.txt</ulink>.</para>
 
           <para>Example: <varname>CPUQuota=20%</varname> ensures that the executed processes will never get more than
           20% CPU time on one CPU.</para>
       <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt">cpuacct.txt</ulink>,
       <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt">memory.txt</ulink>,
       <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt">blkio-controller.txt</ulink>.
+      <ulink url="https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt">sched-bwc.txt</ulink>.
     </para>
   </refsect1>
 </refentry>
index 9d0651f5b00407332afbdf2d9097568087dedc3e..f14a0572803c6c67598fce54d454a5d4bf31b37d 100644 (file)
 
               <row>
                 <entry><literal>-</literal></entry>
-                <entry>If the executable path is prefixed with <literal>-</literal>, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is ignored and considered success.</entry>
+                <entry>If the executable path is prefixed with <literal>-</literal>, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is recorded, but has no further effect and is considered equivalent to success.</entry>
               </row>
 
               <row>
index 68423bdfa5ef4ead8099d973cf823a0ab8e76198..84656cdc7e836441169066b8019395c8e7579a7c 100644 (file)
@@ -421,28 +421,34 @@ decl_headers = '''
 #include <uchar.h>
 #include <linux/ethtool.h>
 #include <linux/fib_rules.h>
-#include <linux/stat.h>
 #include <sys/stat.h>
 '''
-# FIXME: key_serial_t is only defined in keyutils.h, this is bound to fail
-# FIXME: these should use -D_GNU_SOURCE, since that is defined at build time
 
 foreach decl : ['char16_t',
                 'char32_t',
-                'key_serial_t',
                 'struct ethtool_link_settings',
                 'struct fib_rule_uid_range',
                 'struct statx',
                ]
 
         # We get -1 if the size cannot be determined
-        have = cc.sizeof(decl, prefix : decl_headers) > 0
+        have = cc.sizeof(decl, prefix : decl_headers, args : '-D_GNU_SOURCE') > 0
+
+        if decl == 'struct statx'
+                if have
+                        want_linux_stat_h = false
+                else
+                        have = cc.sizeof(decl,
+                                         prefix : decl_headers + '#include <linux/stat.h>',
+                                         args : '-D_GNU_SOURCE') > 0
+                        want_linux_stat_h = have
+                endif
+        endif
+
         conf.set10('HAVE_' + decl.underscorify().to_upper(), have)
 endforeach
 
-conf.set10('HAVE_STRUCT_STATX_IN_SYS_STAT_H', cc.sizeof('struct statx', prefix : '''
-#include <sys/stat.h>
-''', args : '-D_GNU_SOURCE') > 0)
+conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h)
 
 foreach decl : [['IFLA_INET6_ADDR_GEN_MODE',         'linux/if_link.h'],
                 ['IN6_ADDR_GEN_MODE_STABLE_PRIVACY', 'linux/if_link.h'],
index 6ea4de1f293cfcda9e6d7e93e11d6aa511229556..ac5c05dd871ea09986eebafb0fcc87f672705615 100644 (file)
@@ -653,12 +653,13 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
                 if (text_width > text_start && text_width + text_start > width)
                         width = text_width + text_start;
 
-                if (u->deactivated > u->activating && u->deactivated <= boot->finish_time
-                                && u->activated == 0 && u->deactivating == 0)
+                if (u->deactivated > u->activating &&
+                    u->deactivated <= boot->finish_time &&
+                    u->activated == 0 && u->deactivating == 0)
                         u->activated = u->deactivating = u->deactivated;
                 if (u->activated < u->activating || u->activated > boot->finish_time)
                         u->activated = boot->finish_time;
-                if (u->deactivating < u->activated || u->activated > boot->finish_time)
+                if (u->deactivating < u->activated || u->deactivating > boot->finish_time)
                         u->deactivating = boot->finish_time;
                 if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time)
                         u->deactivated = boot->finish_time;
index d1365f705803e94894afec9d993e21b9c8c33370..7e0f6b4ab562745caa10288e55e79de93e68fe63 100644 (file)
@@ -247,12 +247,48 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
                 (__x / __y + !!(__x % __y));                            \
         })
 
+#ifdef __COVERITY__
+
+/* Use special definitions of assertion macros in order to prevent
+ * false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer
+ * for uses of assert_se() and assert_return().
+ *
+ * These definitions make expression go through a (trivial) function
+ * call to ensure they are not discarded. Also use ! or !! to ensure
+ * the boolean expressions are seen as such.
+ *
+ * This technique has been described and recommended in:
+ * https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects
+ */
+
+extern void __coverity_panic__(void);
+
+static inline int __coverity_check__(int condition) {
+        return condition;
+}
+
+#define assert_message_se(expr, message)                                \
+        do {                                                            \
+                if (__coverity_check__(!(expr)))                        \
+                        __coverity_panic__();                           \
+        } while (false)
+
+#define assert_log(expr, message) __coverity_check__(!!(expr))
+
+#else  /* ! __COVERITY__ */
+
 #define assert_message_se(expr, message)                                \
         do {                                                            \
                 if (_unlikely_(!(expr)))                                \
                         log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
         } while (false)
 
+#define assert_log(expr, message) ((_likely_(expr))                     \
+        ? (true)                                                        \
+        : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
+
+#endif  /* __COVERITY__ */
+
 #define assert_se(expr) assert_message_se(expr, #expr)
 
 /* We override the glibc assert() here. */
@@ -285,10 +321,6 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
         REENABLE_WARNING
 #endif
 
-#define assert_log(expr, message) ((_likely_(expr))                     \
-        ? (true)                                                        \
-        : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
-
 #define assert_return(expr, r)                                          \
         do {                                                            \
                 if (!assert_log(expr, #expr))                           \
index 14ad3d49140fa1bd348fbd918fdbfdbfad214fe9..477992fbcbad898bd7b4abda3a901ee6c10346e1 100644 (file)
@@ -24,7 +24,7 @@
 #include <uchar.h>
 #include <unistd.h>
 
-#if !HAVE_STRUCT_STATX_IN_SYS_STAT_H
+#if WANT_LINUX_STAT_H
 #include <linux/stat.h>
 #endif
 
@@ -1183,9 +1183,7 @@ struct input_mask {
 #define KEY_ALS_TOGGLE 0x230
 #endif
 
-#if ! HAVE_KEY_SERIAL_T
 typedef int32_t key_serial_t;
-#endif
 
 #ifndef KEYCTL_JOIN_SESSION_KEYRING
 #define KEYCTL_JOIN_SESSION_KEYRING 1
index ee51002ece35e3fe475cb879a7339663ec13fd11..b98f962ad298f0c2b157ba6f5ec06840bd9abf80 100644 (file)
@@ -15,6 +15,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "selinux-util.h"
+#include "signal-util.h"
 #include "strv.h"
 #include "user-util.h"
 #include "util.h"
@@ -670,13 +671,23 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+
         r = sd_event_default(&event);
         if (r < 0) {
                 log_error_errno(r, "Failed to allocate event loop: %m");
                 goto finish;
         }
 
-        sd_event_set_watchdog(event, true);
+        (void) sd_event_set_watchdog(event, true);
+
+        r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+        if (r < 0)
+                return r;
 
         r = connect_bus(&context, event, &bus);
         if (r < 0)
index 01b8bf608da76cd90125fb05bde0178520fe0482..08b4fcb1c2d26963e53ce2a047112207761d969c 100644 (file)
@@ -224,7 +224,7 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
         return e;
 }
 
-static void syslog_skip_date(char **buf) {
+static int syslog_skip_timestamp(const char **buf) {
         enum {
                 LETTER,
                 SPACE,
@@ -244,24 +244,21 @@ static void syslog_skip_date(char **buf) {
                 SPACE
         };
 
-        char *p;
+        const char *p, *t;
         unsigned i;
 
         assert(buf);
         assert(*buf);
 
-        p = *buf;
-
-        for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
-
+        for (i = 0, p = *buf; i < ELEMENTSOF(sequence); i++, p++) {
                 if (!*p)
-                        return;
+                        return 0;
 
                 switch (sequence[i]) {
 
                 case SPACE:
                         if (*p != ' ')
-                                return;
+                                return 0;
                         break;
 
                 case SPACE_OR_NUMBER:
@@ -271,48 +268,56 @@ static void syslog_skip_date(char **buf) {
                         _fallthrough_;
                 case NUMBER:
                         if (*p < '0' || *p > '9')
-                                return;
+                                return 0;
 
                         break;
 
                 case LETTER:
                         if (!(*p >= 'A' && *p <= 'Z') &&
                             !(*p >= 'a' && *p <= 'z'))
-                                return;
+                                return 0;
 
                         break;
 
                 case COLON:
                         if (*p != ':')
-                                return;
+                                return 0;
                         break;
 
                 }
         }
 
+        t = *buf;
         *buf = p;
+        return p - t;
 }
 
 void server_process_syslog_message(
                 Server *s,
                 const char *buf,
-                size_t buf_len,
+                size_t raw_len,
                 const struct ucred *ucred,
                 const struct timeval *tv,
                 const char *label,
                 size_t label_len) {
 
-        char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
-             syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)], *msg;
-        const char *message = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
+        char *t, syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
+                 syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
+        const char *msg, *syslog_ts, *a;
         _cleanup_free_ char *identifier = NULL, *pid = NULL;
         int priority = LOG_USER | LOG_INFO, r;
         ClientContext *context = NULL;
         struct iovec *iovec;
-        size_t n = 0, m, i;
+        size_t n = 0, m, i, leading_ws, syslog_ts_len;
+        bool store_raw;
 
         assert(s);
         assert(buf);
+        /* The message cannot be empty. */
+        assert(raw_len > 0);
+        /* The buffer NUL-terminated and can be used a string. raw_len is the length
+         * without the terminating NUL byte, the buffer is actually one bigger. */
+        assert(buf[raw_len] == '\0');
 
         if (ucred && pid_is_valid(ucred->pid)) {
                 r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context);
@@ -320,26 +325,42 @@ void server_process_syslog_message(
                         log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid);
         }
 
-        /* We are creating copy of the message because we want to forward original message verbatim to the legacy
-           syslog implementation */
-        for (i = buf_len; i > 0; i--)
+        /* We are creating a copy of the message because we want to forward the original message
+           verbatim to the legacy syslog implementation */
+        for (i = raw_len; i > 0; i--)
                 if (!strchr(WHITESPACE, buf[i-1]))
                         break;
 
-        msg = newa(char, i + 1);
-        *((char *) mempcpy(msg, buf, i)) = 0;
-        msg = skip_leading_chars(msg, WHITESPACE);
+        leading_ws = strspn(buf, WHITESPACE);
 
-        syslog_parse_priority((const char **)&msg, &priority, true);
+        if (i == raw_len)
+                /* Nice! No need to strip anything on the end, let's optimize this a bit */
+                msg = buf + leading_ws;
+        else {
+                msg = t = newa(char, i - leading_ws + 1);
+                memcpy(t, buf + leading_ws, i - leading_ws);
+                t[i - leading_ws] = 0;
+        }
+
+        /* We will add the SYSLOG_RAW= field when we stripped anything
+         * _or_ if the input message contained NUL bytes. */
+        store_raw = msg != buf || strlen(msg) != raw_len;
+
+        syslog_parse_priority(&msg, &priority, true);
 
         if (!client_context_test_priority(context, priority))
                 return;
 
-        if (s->forward_to_syslog)
-                forward_syslog_raw(s, priority, buf, buf_len, ucred, tv);
+        syslog_ts = msg;
+        syslog_ts_len = syslog_skip_timestamp(&msg);
+        if (syslog_ts_len == 0)
+                /* We failed to parse the full timestamp, store the raw message too */
+                store_raw = true;
+
+        syslog_parse_identifier(&msg, &identifier, &pid);
 
-        syslog_skip_date(&msg);
-        syslog_parse_identifier((const char**)&msg, &identifier, &pid);
+        if (s->forward_to_syslog)
+                forward_syslog_raw(s, priority, buf, raw_len, ucred, tv);
 
         if (s->forward_to_kmsg)
                 server_forward_kmsg(s, priority, identifier, msg, ucred);
@@ -350,7 +371,7 @@ void server_process_syslog_message(
         if (s->forward_to_wall)
                 server_forward_wall(s, priority, identifier, msg, ucred);
 
-        m = N_IOVEC_META_FIELDS + 6 + client_context_extra_fields_n_iovec(context);
+        m = N_IOVEC_META_FIELDS + 8 + client_context_extra_fields_n_iovec(context);
         iovec = newa(struct iovec, m);
 
         iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=syslog");
@@ -364,18 +385,37 @@ void server_process_syslog_message(
         }
 
         if (identifier) {
-                syslog_identifier = strjoina("SYSLOG_IDENTIFIER=", identifier);
-                iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier);
+                a = strjoina("SYSLOG_IDENTIFIER=", identifier);
+                iovec[n++] = IOVEC_MAKE_STRING(a);
         }
 
         if (pid) {
-                syslog_pid = strjoina("SYSLOG_PID=", pid);
-                iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
+                a = strjoina("SYSLOG_PID=", pid);
+                iovec[n++] = IOVEC_MAKE_STRING(a);
+        }
+
+        if (syslog_ts_len > 0) {
+                const size_t hlen = strlen("SYSLOG_TIMESTAMP=");
+
+                t = newa(char, hlen + raw_len);
+                memcpy(t, "SYSLOG_TIMESTAMP=", hlen);
+                memcpy(t + hlen, syslog_ts, syslog_ts_len);
+
+                iovec[n++] = IOVEC_MAKE(t, hlen + syslog_ts_len);
         }
 
-        message = strjoina("MESSAGE=", msg);
-        if (message)
-                iovec[n++] = IOVEC_MAKE_STRING(message);
+        a = strjoina("MESSAGE=", msg);
+        iovec[n++] = IOVEC_MAKE_STRING(a);
+
+        if (store_raw) {
+                const size_t hlen = strlen("SYSLOG_RAW=");
+
+                t = newa(char, hlen + raw_len);
+                memcpy(t, "SYSLOG_RAW=", hlen);
+                memcpy(t + hlen, buf, raw_len);
+
+                iovec[n++] = IOVEC_MAKE(t, hlen + raw_len);
+        }
 
         server_dispatch_message(s, iovec, n, m, context, tv, priority, 0);
 }
index 0d4e75ccdef5152d92a1e923ab97d176dde41a82..f5f67950c6e5c9e6e2799df224c1315766a5f673 100644 (file)
@@ -2088,7 +2088,6 @@ _public_ int sd_bus_emit_properties_changed_strv(
                 const char *interface,
                 char **names) {
 
-        BUS_DONT_DESTROY(bus);
         bool found_interface = false;
         char *prefix;
         int r;
@@ -2109,6 +2108,8 @@ _public_ int sd_bus_emit_properties_changed_strv(
         if (names && names[0] == NULL)
                 return 0;
 
+        BUS_DONT_DESTROY(bus);
+
         do {
                 bus->nodes_modified = false;
 
@@ -2308,8 +2309,6 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
 }
 
 _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
-        BUS_DONT_DESTROY(bus);
-
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
@@ -2339,6 +2338,8 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
         if (r == 0)
                 return -ESRCH;
 
+        BUS_DONT_DESTROY(bus);
+
         do {
                 bus->nodes_modified = false;
                 m = sd_bus_message_unref(m);
@@ -2479,8 +2480,6 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
 }
 
 _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
-        BUS_DONT_DESTROY(bus);
-
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
@@ -2510,6 +2509,8 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
         if (r == 0)
                 return -ESRCH;
 
+        BUS_DONT_DESTROY(bus);
+
         do {
                 bus->nodes_modified = false;
                 m = sd_bus_message_unref(m);
@@ -2643,8 +2644,6 @@ static int interfaces_added_append_one(
 }
 
 _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
-        BUS_DONT_DESTROY(bus);
-
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         char **i;
@@ -2667,6 +2666,8 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch
         if (r == 0)
                 return -ESRCH;
 
+        BUS_DONT_DESTROY(bus);
+
         do {
                 bus->nodes_modified = false;
                 m = sd_bus_message_unref(m);
index 17ea8f2ed1d17d1d6ca6935a2f6da7915f25b032..19ef692e7fa54bf207069aad2c4b0d7a14159028 100644 (file)
@@ -48,7 +48,7 @@ _public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
         return slot;
 }
 
-void bus_slot_disconnect(sd_bus_slot *slot) {
+void bus_slot_disconnect(sd_bus_slot *slot, bool unref) {
         sd_bus *bus;
 
         assert(slot);
@@ -79,10 +79,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
                         (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
 
                 if (slot->match_callback.install_slot) {
-                        if (slot->match_callback.install_slot->bus) {
-                                bus_slot_disconnect(slot->match_callback.install_slot);
-                                sd_bus_slot_unref(slot->match_callback.install_slot);
-                        }
+                        bus_slot_disconnect(slot->match_callback.install_slot, true);
                         slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
                 }
 
@@ -186,6 +183,8 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
 
         if (!slot->floating)
                 sd_bus_unref(bus);
+        else if (unref)
+                sd_bus_slot_unref(slot);
 }
 
 _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
@@ -200,7 +199,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
                 return NULL;
         }
 
-        bus_slot_disconnect(slot);
+        bus_slot_disconnect(slot, false);
 
         if (slot->destroy_callback)
                 slot->destroy_callback(slot->userdata);
index 555afac9a6aae1358aa2b1b1e0db7439eb0dd252..48eb0453dcb1611854acd61be75671e120772ee7 100644 (file)
@@ -7,4 +7,4 @@
 
 sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata);
 
-void bus_slot_disconnect(sd_bus_slot *slot);
+void bus_slot_disconnect(sd_bus_slot *slot, bool unref);
index be491c957f6912109cf0a9ceb34fa211fc3ca7f2..a785a247c8720843ef8745fa60427734d343f8fd 100644 (file)
@@ -246,10 +246,7 @@ static bool line_begins(const char *s, size_t m, const char *word) {
         const char *p;
 
         p = memory_startswith(s, m, word);
-        if (!p)
-                return false;
-
-        return IN_SET(*p, 0, ' ');
+        return p && (p == (s + m) || *p == ' ');
 }
 
 static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
index deb664540a526def3e7bd083b4d8059e754ab683..a87f4625ecaf2ebe7c617b3ba8502572529b7374 100644 (file)
@@ -178,8 +178,7 @@ static sd_bus* bus_free(sd_bus *b) {
                  * apps, but are dead. */
 
                 assert(s->floating);
-                bus_slot_disconnect(s);
-                sd_bus_slot_unref(s);
+                bus_slot_disconnect(s, true);
         }
 
         if (b->default_bus_ptr)
@@ -2360,10 +2359,8 @@ static int process_timeout(sd_bus *bus) {
         bus->current_slot = NULL;
         bus->current_message = NULL;
 
-        if (slot->floating) {
-                bus_slot_disconnect(slot);
-                sd_bus_slot_unref(slot);
-        }
+        if (slot->floating)
+                bus_slot_disconnect(slot, true);
 
         sd_bus_slot_unref(slot);
 
@@ -2465,10 +2462,8 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
         bus->current_handler = NULL;
         bus->current_slot = NULL;
 
-        if (slot->floating) {
-                bus_slot_disconnect(slot);
-                sd_bus_slot_unref(slot);
-        }
+        if (slot->floating)
+                bus_slot_disconnect(slot, true);
 
         sd_bus_slot_unref(slot);
 
@@ -2810,10 +2805,8 @@ static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c)
         bus->current_slot = NULL;
         bus->current_message = NULL;
 
-        if (slot->floating) {
-                bus_slot_disconnect(slot);
-                sd_bus_slot_unref(slot);
-        }
+        if (slot->floating)
+                bus_slot_disconnect(slot, true);
 
         sd_bus_slot_unref(slot);
 
@@ -2884,7 +2877,6 @@ finish:
 }
 
 static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
-        BUS_DONT_DESTROY(bus);
         int r;
 
         /* Returns 0 when we didn't do anything. This should cause the
@@ -2898,7 +2890,9 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
 
         /* We don't allow recursively invoking sd_bus_process(). */
         assert_return(!bus->current_message, -EBUSY);
-        assert(!bus->current_slot);
+        assert(!bus->current_slot); /* This should be NULL whenever bus->current_message is */
+
+        BUS_DONT_DESTROY(bus);
 
         switch (bus->state) {
 
@@ -3167,10 +3161,8 @@ static int add_match_callback(
                 r = 1;
         }
 
-        if (failed && match_slot->floating) {
-                bus_slot_disconnect(match_slot);
-                sd_bus_slot_unref(match_slot);
-        }
+        if (failed && match_slot->floating)
+                bus_slot_disconnect(match_slot, true);
 
         sd_bus_slot_unref(match_slot);
 
index b8f95b69a62eb053a809bf8f287da5e693c1b409..71115c59d7882598b2d1ba922b6058946c825eea 100644 (file)
@@ -21,6 +21,7 @@
 #include "macro.h"
 #include "path-util.h"
 #include "selinux-util.h"
+#include "signal-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "user-util.h"
@@ -738,13 +739,23 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+
         r = sd_event_default(&event);
         if (r < 0) {
                 log_error_errno(r, "Failed to allocate event loop: %m");
                 goto finish;
         }
 
-        sd_event_set_watchdog(event, true);
+        (void) sd_event_set_watchdog(event, true);
+
+        r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+        if (r < 0)
+                return r;
 
         r = connect_bus(&context, event, &bus);
         if (r < 0)
index b16b13178a2561323859ab633204cec65b31d410..c603f4290ade1323f93eafe5ace8014225ee8096 100644 (file)
@@ -492,19 +492,28 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
 static void link_free(Link *link) {
         Address *address;
         Link *carrier;
+        Route *route;
         Iterator i;
 
         if (!link)
                 return;
 
-        while (!set_isempty(link->addresses))
-                address_free(set_first(link->addresses));
+        while ((route = set_first(link->routes)))
+                route_free(route);
 
-        while (!set_isempty(link->addresses_foreign))
-                address_free(set_first(link->addresses_foreign));
+        while ((route = set_first(link->routes_foreign)))
+                route_free(route);
 
-        link->addresses = set_free(link->addresses);
+        link->routes = set_free(link->routes);
+        link->routes_foreign = set_free(link->routes_foreign);
+
+        while ((address = set_first(link->addresses)))
+                address_free(address);
 
+        while ((address = set_first(link->addresses_foreign)))
+                address_free(address);
+
+        link->addresses = set_free(link->addresses);
         link->addresses_foreign = set_free(link->addresses_foreign);
 
         while ((address = link->pool_addresses)) {
index 8019d4488ccadf37755a4668444bbe33cf813774..e22c2fe5784204a42484575dd7bcc5334f1fac54 100644 (file)
@@ -1370,7 +1370,7 @@ static const struct hash_ops dhcp6_prefixes_hash_ops = {
         .compare = dhcp6_prefixes_compare_func,
 };
 
-int manager_new(Manager **ret, sd_event *event) {
+int manager_new(Manager **ret) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
 
@@ -1382,7 +1382,13 @@ int manager_new(Manager **ret, sd_event *event) {
         if (!m->state_file)
                 return -ENOMEM;
 
-        m->event = sd_event_ref(event);
+        r = sd_event_default(&m->event);
+        if (r < 0)
+                return r;
+
+        (void) sd_event_set_watchdog(m->event, true);
+        (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+        (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
         r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m);
         if (r < 0)
@@ -1468,6 +1474,7 @@ void manager_free(Manager *m) {
         set_free_with_destructor(m->rules_saved, routing_policy_rule_free);
 
         sd_netlink_unref(m->rtnl);
+        sd_netlink_unref(m->genl);
         sd_event_unref(m->event);
 
         sd_resolve_unref(m->resolve);
index 3543e5861d25550f6b065726431a3cd069545bdf..a6cb1e2d44ad08bd832956a78a10eb8a092e982f 100644 (file)
@@ -65,7 +65,7 @@ static inline const DUID* link_duid(const Link *link) {
 
 extern const sd_bus_vtable manager_vtable[];
 
-int manager_new(Manager **ret, sd_event *event);
+int manager_new(Manager **ret);
 void manager_free(Manager *m);
 
 int manager_connect_bus(Manager *m);
index b59b308141338e9fcd2561c79f611d527e650d15..d2467b70cee4949f0bfd86939c13e1a9eb2e02b5 100644 (file)
@@ -10,7 +10,6 @@
 #include "user-util.h"
 
 int main(int argc, char *argv[]) {
-        sd_event *event = NULL;
         _cleanup_(manager_freep) Manager *m = NULL;
         const char *user = "systemd-network";
         uid_t uid;
@@ -71,15 +70,7 @@ int main(int argc, char *argv[]) {
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
-        r = sd_event_default(&event);
-        if (r < 0)
-                goto out;
-
-        sd_event_set_watchdog(event, true);
-        sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
-        sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
-
-        r = manager_new(&m, event);
+        r = manager_new(&m);
         if (r < 0) {
                 log_error_errno(r, "Could not create manager: %m");
                 goto out;
@@ -137,7 +128,7 @@ int main(int argc, char *argv[]) {
                   "READY=1\n"
                   "STATUS=Processing requests...");
 
-        r = sd_event_loop(event);
+        r = sd_event_loop(m->event);
         if (r < 0) {
                 log_error_errno(r, "Event loop failed: %m");
                 goto out;
@@ -147,7 +138,5 @@ out:
                   "STOPPING=1\n"
                   "STATUS=Shutting down...");
 
-        sd_event_unref(event);
-
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
index 5349b668bee85a61c6a7ef35f4284cf10a4e8d54..35c982a91d78fbdfc5ad3bd866e0021adbddca3a 100644 (file)
@@ -219,7 +219,6 @@ static void test_dhcp_hostname_shorten_overlong(void) {
 
 int main(void) {
         _cleanup_(manager_freep) Manager *manager = NULL;
-        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_(udev_unrefp) struct udev *udev = NULL;
         _cleanup_(udev_device_unrefp) struct udev_device *loopback = NULL;
         int r;
@@ -229,9 +228,7 @@ int main(void) {
         test_address_equality();
         test_dhcp_hostname_shorten_overlong();
 
-        assert_se(sd_event_default(&event) >= 0);
-
-        assert_se(manager_new(&manager, event) >= 0);
+        assert_se(manager_new(&manager) >= 0);
 
         r = test_load_config(manager);
         if (r == -EPERM)
index d04c756d73868ded97647567576e61c9aff301fa..7f29546de1aec21eaca5eb1b784dc219ec1bd961 100644 (file)
@@ -1930,28 +1930,32 @@ static int verb_dns(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        STRV_FOREACH(p, argv + 2) {
-                struct in_addr_data data;
+        /* If only argument is the empty string, then call SetLinkDNS() with an
+         * empty list, which will clear the list of domains for an interface. */
+        if (!strv_equal(argv + 2, STRV_MAKE(""))) {
+                STRV_FOREACH(p, argv + 2) {
+                        struct in_addr_data data;
 
-                r = in_addr_from_string_auto(*p, &data.family, &data.address);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse DNS server address: %s", *p);
+                        r = in_addr_from_string_auto(*p, &data.family, &data.address);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse DNS server address: %s", *p);
 
-                r = sd_bus_message_open_container(req, 'r', "iay");
-                if (r < 0)
-                        return bus_log_create_error(r);
+                        r = sd_bus_message_open_container(req, 'r', "iay");
+                        if (r < 0)
+                                return bus_log_create_error(r);
 
-                r = sd_bus_message_append(req, "i", data.family);
-                if (r < 0)
-                        return bus_log_create_error(r);
+                        r = sd_bus_message_append(req, "i", data.family);
+                        if (r < 0)
+                                return bus_log_create_error(r);
 
-                r = sd_bus_message_append_array(req, 'y', &data.address, FAMILY_ADDRESS_SIZE(data.family));
-                if (r < 0)
-                        return bus_log_create_error(r);
+                        r = sd_bus_message_append_array(req, 'y', &data.address, FAMILY_ADDRESS_SIZE(data.family));
+                        if (r < 0)
+                                return bus_log_create_error(r);
 
-                r = sd_bus_message_close_container(req);
-                if (r < 0)
-                        return bus_log_create_error(r);
+                        r = sd_bus_message_close_container(req);
+                        if (r < 0)
+                                return bus_log_create_error(r);
+                }
         }
 
         r = sd_bus_message_close_container(req);
@@ -2010,22 +2014,26 @@ static int verb_domain(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        STRV_FOREACH(p, argv + 2) {
-                const char *n;
+        /* If only argument is the empty string, then call SetLinkDomains() with an
+         * empty list, which will clear the list of domains for an interface. */
+        if (!strv_equal(argv + 2, STRV_MAKE(""))) {
+                STRV_FOREACH(p, argv + 2) {
+                        const char *n;
 
-                n = **p == '~' ? *p + 1 : *p;
+                        n = **p == '~' ? *p + 1 : *p;
 
-                r = dns_name_is_valid(n);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to validate specified domain %s: %m", n);
-                if (r == 0) {
-                        log_error("Domain not valid: %s", n);
-                        return -EINVAL;
-                }
+                        r = dns_name_is_valid(n);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to validate specified domain %s: %m", n);
+                        if (r == 0) {
+                                log_error("Domain not valid: %s", n);
+                                return -EINVAL;
+                        }
 
-                r = sd_bus_message_append(req, "(sb)", n, **p == '~');
-                if (r < 0)
-                        return bus_log_create_error(r);
+                        r = sd_bus_message_append(req, "(sb)", n, **p == '~');
+                        if (r < 0)
+                                return bus_log_create_error(r);
+                }
         }
 
         r = sd_bus_message_close_container(req);
@@ -2209,6 +2217,7 @@ static int verb_nta(int argc, char **argv, void *userdata) {
         sd_bus *bus = userdata;
         char **p;
         int r;
+        bool clear;
 
         assert(bus);
 
@@ -2222,15 +2231,20 @@ static int verb_nta(int argc, char **argv, void *userdata) {
         if (argc == 2)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_NTA, NULL);
 
-        STRV_FOREACH(p, argv + 2) {
-                r = dns_name_is_valid(*p);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to validate specified domain %s: %m", *p);
-                if (r == 0) {
-                        log_error("Domain not valid: %s", *p);
-                        return -EINVAL;
+        /* If only argument is the empty string, then call SetLinkDNSSECNegativeTrustAnchors()
+         * with an empty list, which will clear the list of domains for an interface. */
+        clear = strv_equal(argv + 2, STRV_MAKE(""));
+
+        if (!clear)
+                STRV_FOREACH(p, argv + 2) {
+                        r = dns_name_is_valid(*p);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to validate specified domain %s: %m", *p);
+                        if (r == 0) {
+                                log_error("Domain not valid: %s", *p);
+                                return -EINVAL;
+                        }
                 }
-        }
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -2246,7 +2260,7 @@ static int verb_nta(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_append_strv(req, argv + 2);
+        r = sd_bus_message_append_strv(req, clear ? NULL : argv + 2);
         if (r < 0)
                 return bus_log_create_error(r);
 
index da0a909dd66ca37dedb765d05af77eb5e8db4308..3859d41029129998d945946522b94988ae5e49b3 100644 (file)
@@ -1930,7 +1930,7 @@ int manager_connect_bus(Manager *m) {
 
         r = sd_bus_match_signal_async(
                         m->bus,
-                        &m->prepare_for_sleep_slot,
+                        NULL,
                         "org.freedesktop.login1",
                         "/org/freedesktop/login1",
                         "org.freedesktop.login1.Manager",
index 01372fc66bba24e7f8a1842a3b6313739604b3b2..44a53952d2450b7d3befd2ed43a74bae4a9eea6a 100644 (file)
@@ -594,10 +594,10 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        sd_event_add_signal(m->event, NULL, SIGTERM, NULL,  NULL);
-        sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+        (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL,  NULL);
+        (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
-        sd_event_set_watchdog(m->event, true);
+        (void) sd_event_set_watchdog(m->event, true);
 
         r = manager_watch_hostname(m);
         if (r < 0)
@@ -683,7 +683,6 @@ Manager *manager_free(Manager *m) {
         manager_mdns_stop(m);
         manager_dns_stub_stop(m);
 
-        sd_bus_slot_unref(m->prepare_for_sleep_slot);
         sd_bus_unref(m->bus);
 
         sd_event_source_unref(m->sigusr1_event_source);
index 6bbb15dbfb39826ac45e03e66416ae1a7889c090..be7ad2d10ddb15b1e0cb22d0993df1bb6a5b00e7 100644 (file)
@@ -106,9 +106,6 @@ struct Manager {
         int hostname_fd;
         sd_event_source *hostname_event_source;
 
-        /* Watch for system suspends */
-        sd_bus_slot *prepare_for_sleep_slot;
-
         sd_event_source *sigusr1_event_source;
         sd_event_source *sigusr2_event_source;
         sd_event_source *sigrtmin1_event_source;
index f26aa453c99c1b88f2d87869d82806b2fabdd48f..0584afb95d162edd7d7767786dde67efd69f8dca 100644 (file)
 
 #include "sd-messages.h"
 
-#include "parse-util.h"
 #include "def.h"
 #include "exec-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "log.h"
+#include "parse-util.h"
 #include "sleep-config.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -40,21 +40,27 @@ static int write_hibernate_location_info(void) {
                 return log_debug_errno(r, "Unable to find hibernation location: %m");
 
         /* if it's a swap partition, we just write the disk to /sys/power/resume */
-        if (streq(type, "partition"))
-                return write_string_file("/sys/power/resume", device, 0);
-        else if (!streq(type, "file"))
-                return log_debug_errno(EINVAL, "Invalid hibernate type %s: %m",
-                                       type);
+        if (streq(type, "partition")) {
+                r = write_string_file("/sys/power/resume", device, 0);
+                if (r < 0)
+                        return log_debug_errno(r, "Faileed to write partitoin device to /sys/power/resume: %m");
+
+                return r;
+        }
+        if (!streq(type, "file")) {
+                log_debug("Invalid hibernate type: %s", type);
+                return -EINVAL;
+        }
 
         /* Only available in 4.17+ */
         if (access("/sys/power/resume_offset", F_OK) < 0) {
                 if (errno == ENOENT)
                         return 0;
+
                 return log_debug_errno(errno, "/sys/power/resume_offset unavailable: %m");
         }
 
-        r = access("/sys/power/resume_offset", W_OK);
-        if (r < 0)
+        if (access("/sys/power/resume_offset", W_OK) < 0)
                 return log_debug_errno(errno, "/sys/power/resume_offset not writeable: %m");
 
         fd = open(device, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
@@ -63,26 +69,26 @@ static int write_hibernate_location_info(void) {
         r = fstat(fd, &stb);
         if (r < 0)
                 return log_debug_errno(errno, "Unable to stat %s: %m", device);
+
         r = read_fiemap(fd, &fiemap);
         if (r < 0)
-                return log_debug_errno(r, "Unable to read extent map for '%s': %m",
-                                       device);
+                return log_debug_errno(r, "Unable to read extent map for '%s': %m", device);
         if (fiemap->fm_mapped_extents == 0) {
                 log_debug("No extents found in '%s'", device);
                 return -EINVAL;
         }
+
         offset = fiemap->fm_extents[0].fe_physical / page_size();
         xsprintf(offset_str, "%" PRIu64, offset);
         r = write_string_file("/sys/power/resume_offset", offset_str, 0);
         if (r < 0)
-                return log_debug_errno(r, "Failed to write offset '%s': %m",
-                                       offset_str);
+                return log_debug_errno(r, "Failed to write offset '%s': %m", offset_str);
 
         xsprintf(device_str, "%lx", (unsigned long)stb.st_dev);
         r = write_string_file("/sys/power/resume", device_str, 0);
         if (r < 0)
-                return log_debug_errno(r, "Failed to write device '%s': %m",
-                                       device_str);
+                return log_debug_errno(r, "Failed to write device '%s': %m", device_str);
+
         return 0;
 }
 
@@ -94,12 +100,11 @@ static int write_mode(char **modes) {
                 int k;
 
                 k = write_string_file("/sys/power/disk", *mode, 0);
-                if (k == 0)
+                if (k >= 0)
                         return 0;
 
-                log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m",
-                                *mode);
-                if (r == 0)
+                log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m", *mode);
+                if (r >= 0)
                         r = k;
         }
 
@@ -114,11 +119,10 @@ static int write_state(FILE **f, char **states) {
                 int k;
 
                 k = write_string_stream(*f, *state, 0);
-                if (k == 0)
+                if (k >= 0)
                         return 0;
-                log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
-                                *state);
-                if (r == 0)
+                log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m", *state);
+                if (r >= 0)
                         r = k;
 
                 fclose(*f);
@@ -315,10 +319,7 @@ static int parse_argv(int argc, char *argv[]) {
 
         arg_verb = argv[optind];
 
-        if (!streq(arg_verb, "suspend") &&
-            !streq(arg_verb, "hibernate") &&
-            !streq(arg_verb, "hybrid-sleep") &&
-            !streq(arg_verb, "suspend-then-hibernate")) {
+        if (!STR_IN_SET(arg_verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")) {
                 log_error("Unknown command '%s'.", arg_verb);
                 return -EINVAL;
         }
@@ -347,6 +348,7 @@ int main(int argc, char *argv[]) {
                 r = execute_s2h(delay);
         else
                 r = execute(modes, states);
+
 finish:
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
index 0b5def60f3ac5a2e66510e2e14f714060e058b7d..6f8934eef08b7b6c22765e14fcf37a3bd65a5b26 100644 (file)
@@ -2436,7 +2436,7 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0)
-                        return log_error_errno(r, "Failed to access path '%s': %m", path);
+                        return log_error_errno(r, "Failed to access path \"%s\": %m", path);
 
                 if (unit_path)
                         *unit_path = TAKE_PTR(lpath);
@@ -2544,12 +2544,16 @@ static int unit_find_paths(
                 if (r < 0)
                         return r;
 
-                if (r > 0)
+                if (r > 0) {
+                        if (null_or_empty_path(path))
+                                /* The template is masked. Let's cut the process short. */
+                                return -ERFKILL;
+
                         /* We found the unit file. If we followed symlinks, this name might be
                          * different then the unit_name with started with. Look for dropins matching
                          * that "final" name. */
                         r = set_put(names, basename(path));
-                else if (!template)
+                else if (!template)
                         /* No unit file, let's look for dropins matching the original name.
                          * systemd has fairly complicated rules (based on unit type and provenience),
                          * which units are allowed not to have the main unit file. We err on the
@@ -2623,10 +2627,24 @@ static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *ac
         return 0;
 }
 
-static int unit_is_masked(sd_bus *bus, const char *name) {
+static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) {
         _cleanup_free_ char *load_state = NULL;
         int r;
 
+        if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
+                _cleanup_free_ char *path = NULL;
+
+                /* A template cannot be loaded, but it can be still masked, so
+                 * we need to use a different method. */
+
+                r = unit_file_find_path(lp, name, &path);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return false;
+                return null_or_empty_path(path);
+        }
+
         r = unit_load_state(bus, name, &load_state);
         if (r < 0)
                 return r;
@@ -2636,7 +2654,7 @@ static int unit_is_masked(sd_bus *bus, const char *name) {
 
 static int check_triggering_units(sd_bus *bus, const char *name) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_free_ char *n = NULL, *path = NULL;
+        _cleanup_free_ char *n = NULL, *path = NULL, *load_state = NULL;
         _cleanup_strv_free_ char **triggered_by = NULL;
         bool print_warning_label = true;
         UnitActiveState active_state;
@@ -2647,9 +2665,12 @@ static int check_triggering_units(sd_bus *bus, const char *name) {
         if (r < 0)
                 return log_error_errno(r, "Failed to mangle unit name: %m");
 
-        r = unit_is_masked(bus, n);
-        if (r != 0)
-                return r < 0 ? r : 0;
+        r = unit_load_state(bus, name, &load_state);
+        if (r < 0)
+                return r;
+
+        if (streq(load_state, "masked"))
+                return 0;
 
         path = unit_dbus_path_from_name(n);
         if (!path)
@@ -3125,7 +3146,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
                  * another active unit (socket, path, timer) */
                 if (!arg_quiet && streq(method, "StopUnit"))
                         STRV_FOREACH(name, names)
-                                check_triggering_units(bus, *name);
+                                (void) check_triggering_units(bus, *name);
         }
 
         if (r >= 0 && arg_wait) {
@@ -5355,6 +5376,13 @@ static int cat(int argc, char *argv[], void *userdata) {
                 _cleanup_strv_free_ char **dropin_paths = NULL;
 
                 r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths);
+                if (r == -ERFKILL) {
+                        printf("%s# unit %s is masked%s\n",
+                               ansi_highlight_magenta(),
+                               *name,
+                               ansi_normal());
+                        continue;
+                }
                 if (r < 0)
                         return r;
                 else if (r == 0)
@@ -6921,6 +6949,7 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
 }
 
 static int edit(int argc, char *argv[], void *userdata) {
+        _cleanup_(lookup_paths_free) LookupPaths lp = {};
         _cleanup_strv_free_ char **names = NULL;
         _cleanup_strv_free_ char **paths = NULL;
         char **original, **tmp;
@@ -6937,6 +6966,10 @@ static int edit(int argc, char *argv[], void *userdata) {
                 return -EINVAL;
         }
 
+        r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine unit paths: %m");
+
         r = acquire_bus(BUS_MANAGER, &bus);
         if (r < 0)
                 return r;
@@ -6946,7 +6979,7 @@ static int edit(int argc, char *argv[], void *userdata) {
                 return log_error_errno(r, "Failed to expand names: %m");
 
         STRV_FOREACH(tmp, names) {
-                r = unit_is_masked(bus, *tmp);
+                r = unit_is_masked(bus, &lp, *tmp);
                 if (r < 0)
                         return r;
 
@@ -7838,7 +7871,8 @@ static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
                 tm.tm_min = (int) minute;
                 tm.tm_sec = 0;
 
-                assert_se(s = mktime(&tm));
+                s = mktime(&tm);
+                assert(s >= 0);
 
                 *_u = (usec_t) s * USEC_PER_SEC;
 
index ad662fb1cf2a78353744d0fe1c793f5dff47750b..4beded5de015dbf8a51ec7ea42782113b9183eb5 100644 (file)
@@ -20,6 +20,7 @@
 #include "list.h"
 #include "path-util.h"
 #include "selinux-util.h"
+#include "signal-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "unit-def.h"
@@ -909,13 +910,23 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+
         r = sd_event_default(&event);
         if (r < 0) {
                 log_error_errno(r, "Failed to allocate event loop: %m");
                 goto finish;
         }
 
-        sd_event_set_watchdog(event, true);
+        (void) sd_event_set_watchdog(event, true);
+
+        r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+        if (r < 0)
+                return r;
 
         r = connect_bus(&context, event, &bus);
         if (r < 0)
index ca14253adf31c899d67f72df9132bef8123148cf..5a3d478d73fa0fbb53092cf63ec145afdb6a5615 100644 (file)
@@ -1101,10 +1101,10 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        sd_event_add_signal(m->event, NULL, SIGTERM, NULL,  NULL);
-        sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+        (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL,  NULL);
+        (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
-        sd_event_set_watchdog(m->event, true);
+        (void) sd_event_set_watchdog(m->event, true);
 
         r = sd_resolve_default(&m->resolve);
         if (r < 0)
index 1b3d75210fac64bf99c067beefbc432606b4e733..accaf927c87a54661b22d426d2b0a5354c5c2311 100644 (file)
@@ -21,6 +21,8 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
     ROOTLIBDIR=/usr/lib/systemd
 fi
 
+PATH_TO_INIT=$ROOTLIBDIR/systemd
+
 BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs"
 DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"
 
@@ -28,6 +30,29 @@ STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
 STATEFILE="$STATEDIR/.testdir"
 TESTLOG="$STATEDIR/test.log"
 
+is_built_with_asan() {
+    if ! type -P objdump >/dev/null; then
+        ddebug "Failed to find objdump. Assuming systemd hasn't been built with ASAN."
+        return 1
+    fi
+
+    # Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182
+    local _asan_calls=$(objdump -dC $BUILD_DIR/systemd | egrep "callq\s+[0-9a-f]+\s+<__asan" -c)
+    if (( $_asan_calls < 1000 )); then
+        return 1
+    else
+        return 0
+    fi
+}
+
+IS_BUILT_WITH_ASAN=$(is_built_with_asan && echo yes || echo no)
+
+if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
+    STRIP_BINARIES=no
+    SKIP_INITRD=yes
+    PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan
+fi
+
 function find_qemu_bin() {
     # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm.
     # Either way, only use this version if we aren't running in KVM, because
@@ -121,7 +146,7 @@ KERNEL_APPEND="$PARAMS \
 root=/dev/sda1 \
 raid=noautodetect \
 loglevel=2 \
-init=$ROOTLIBDIR/systemd \
+init=$PATH_TO_INIT \
 console=ttyS0 \
 selinux=0 \
 printk.devkmsg=on \
@@ -165,7 +190,7 @@ $KERNEL_APPEND \
 run_nspawn() {
     [[ -d /run/systemd/system ]] || return 1
 
-    local _nspawn_cmd="$BUILD_DIR/systemd-nspawn --register=no --kill-signal=SIGKILL --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND"
+    local _nspawn_cmd="$BUILD_DIR/systemd-nspawn $NSPAWN_ARGUMENTS --register=no --kill-signal=SIGKILL --directory=$TESTDIR/nspawn-root $PATH_TO_INIT $KERNEL_APPEND"
     if [[ "$NSPAWN_TIMEOUT" != "infinity" ]]; then
         _nspawn_cmd="timeout --foreground $NSPAWN_TIMEOUT $_nspawn_cmd"
     fi
@@ -217,6 +242,9 @@ setup_basic_environment() {
     strip_binaries
     install_depmod_files
     generate_module_dependencies
+    if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
+         create_asan_wrapper
+    fi
 }
 
 setup_selinux() {