*.trs
*~
.config.args
+.gdb_history
.deps/
/*.gcda
/*.gcno
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)
# 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
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
###########################################################
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
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
#########################################
<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>
<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.
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
<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>
<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>
<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>
#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'],
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;
(__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. */
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)) \
#include <uchar.h>
#include <unistd.h>
-#if !HAVE_STRUCT_STATX_IN_SYS_STAT_H
+#if WANT_LINUX_STAT_H
#include <linux/stat.h>
#endif
#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
#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"
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)
return e;
}
-static void syslog_skip_date(char **buf) {
+static int syslog_skip_timestamp(const char **buf) {
enum {
LETTER,
SPACE,
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:
_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);
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);
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");
}
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);
}
const char *interface,
char **names) {
- BUS_DONT_DESTROY(bus);
bool found_interface = false;
char *prefix;
int r;
if (names && names[0] == NULL)
return 0;
+ BUS_DONT_DESTROY(bus);
+
do {
bus->nodes_modified = false;
}
_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;
if (r == 0)
return -ESRCH;
+ BUS_DONT_DESTROY(bus);
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
}
_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;
if (r == 0)
return -ESRCH;
+ BUS_DONT_DESTROY(bus);
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
}
_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;
if (r == 0)
return -ESRCH;
+ BUS_DONT_DESTROY(bus);
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
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);
(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);
}
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) {
return NULL;
}
- bus_slot_disconnect(slot);
+ bus_slot_disconnect(slot, false);
if (slot->destroy_callback)
slot->destroy_callback(slot->userdata);
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);
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) {
* 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)
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);
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);
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);
}
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
/* 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) {
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);
#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"
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)
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)) {
.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;
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)
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);
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);
#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;
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;
"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;
"STOPPING=1\n"
"STATUS=Shutting down...");
- sd_event_unref(event);
-
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
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;
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)
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);
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);
sd_bus *bus = userdata;
char **p;
int r;
+ bool clear;
assert(bus);
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,
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);
r = sd_bus_match_signal_async(
m->bus,
- &m->prepare_for_sleep_slot,
+ NULL,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
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)
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);
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;
#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"
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);
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;
}
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;
}
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);
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;
}
r = execute_s2h(delay);
else
r = execute(modes, states);
+
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
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);
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
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;
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;
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)
* 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) {
_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)
}
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;
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;
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;
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;
#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"
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)
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)
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"
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
root=/dev/sda1 \
raid=noautodetect \
loglevel=2 \
-init=$ROOTLIBDIR/systemd \
+init=$PATH_TO_INIT \
console=ttyS0 \
selinux=0 \
printk.devkmsg=on \
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
strip_binaries
install_depmod_files
generate_module_dependencies
+ if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
+ create_asan_wrapper
+ fi
}
setup_selinux() {