summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mkosi/mkosi.fedora4
-rw-r--r--Makefile.am3
-rw-r--r--TODO37
-rw-r--r--man/sd_journal_print.xml19
-rw-r--r--man/systemctl.xml26
-rw-r--r--man/systemd.mount.xml13
-rwxr-xr-xmkosi.build10
-rw-r--r--rules/60-cdrom_id.rules4
-rw-r--r--rules/78-sound-card.rules7
-rw-r--r--src/basic/log.c52
-rw-r--r--src/basic/mount-util.c26
-rw-r--r--src/basic/mount-util.h2
-rw-r--r--src/basic/process-util.c102
-rw-r--r--src/basic/process-util.h2
-rw-r--r--src/basic/virt.c81
-rw-r--r--src/boot/bootctl.c2
-rw-r--r--src/core/dbus-execute.c2
-rw-r--r--src/core/device.c46
-rw-r--r--src/core/device.h3
-rw-r--r--src/core/load-fragment.c16
-rw-r--r--src/core/main.c1
-rw-r--r--src/core/manager.c2
-rw-r--r--src/core/mount.c20
-rw-r--r--src/core/socket.c3
-rw-r--r--src/core/unit.c3
-rw-r--r--src/coredump/coredumpctl.c5
-rw-r--r--src/debug-generator/debug-generator.c12
-rw-r--r--src/journal/journalctl.c2
-rw-r--r--src/journal/test-compress.c4
-rw-r--r--src/machine/machinectl.c2
-rw-r--r--src/nspawn/nspawn-stub-pid1.c29
-rw-r--r--src/nspawn/nspawn-stub-pid1.h4
-rw-r--r--src/nspawn/nspawn.c2
-rw-r--r--src/shared/bus-unit-util.c12
-rw-r--r--src/system-update-generator/system-update-generator.c6
-rw-r--r--src/sysv-generator/sysv-generator.c10
-rw-r--r--src/test/test-install-root.c3
-rw-r--r--src/test/test-mount-util.c32
-rw-r--r--src/test/test-process-util.c61
39 files changed, 492 insertions, 178 deletions
diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora
index 478703c41a..4f5f084f93 100644
--- a/.mkosi/mkosi.fedora
+++ b/.mkosi/mkosi.fedora
@@ -27,7 +27,7 @@ Format=raw_btrfs
Bootable=yes
[Partitions]
-RootSize=2G
+RootSize=3G
[Packages]
BuildPackages=
@@ -37,6 +37,7 @@ BuildPackages=
bzip2-devel
cryptsetup-devel
dbus-devel
+ diffutils
docbook-style-xsl
elfutils-devel
gcc
@@ -69,4 +70,5 @@ BuildPackages=
python3-devel
python3-lxml
qrencode-devel
+ tree
xz-devel
diff --git a/Makefile.am b/Makefile.am
index 8f7b83f0ab..d75807a9f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -149,7 +149,8 @@ TESTS =
endif
AM_TESTS_ENVIRONMENT = \
export SYSTEMD_KBD_MODEL_MAP=$(abs_top_srcdir)/src/locale/kbd-model-map; \
- export SYSTEMD_LANGUAGE_FALLBACK_MAP=$(abs_top_srcdir)/src/locale/language-fallback-map;
+ export SYSTEMD_LANGUAGE_FALLBACK_MAP=$(abs_top_srcdir)/src/locale/language-fallback-map; \
+ export PATH=$(abs_top_builddir):$$PATH;
if ENABLE_BASH_COMPLETION
dist_bashcompletion_DATA = $(dist_bashcompletion_data)
diff --git a/TODO b/TODO
index f3f6cb18bb..89e0874903 100644
--- a/TODO
+++ b/TODO
@@ -12,9 +12,6 @@ Bugfixes:
Environment=ONE='one' "TWO='two two' too" THREE=
ExecStart=/bin/python3 -c 'import sys;print(sys.argv)' $ONE $TWO $THREE
-* When systemctl --host is used, underlying ssh connection can remain open.
- bus_close does not kill children?
-
External:
* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.
@@ -34,6 +31,38 @@ Features:
* replace all canonicalize_file_name() invocations by chase_symlinks(), in
particulr those where a rootdir is relevant.
+* maybe introduce gpt auto discovery for /var/tmp?
+
+* set ProtectSystem=strict for all our usual services.
+
+* maybe add gpt-partition-based user management: each user gets his own
+ LUKS-encrypted GPT partition with a new GPT type. A small nss module
+ enumerates users via udev partition enumeration. UIDs are assigned in a fixed
+ way: the partition index is added as offset to some fixed base uid. User name
+ is stored in GPT partition name. A PAM module authenticates the user via the
+ LUKS partition password. Benefits: strong per-user security, compatibility
+ with stateless/read-only/verity-enabled root. (other idea: do this based on
+ loopback files in /home, without GPT involvement)
+
+* gpt-auto logic: introduce support for discovering /var matching an image. For
+ that, use a partition type UUID that is hashed from the OS name (as encoded
+ in /etc/os-release), the architecture, and 4 new bits from the gpt flags
+ field of the root partition. This way can easily support multiple OS
+ installations on the same GPT partition table, without problems with
+ unmatched /var partitions.
+
+* gpt-auto logic: related to the above, maybe support a "secondary" root
+ partition, that is mounted to / and is writable, and where the actual root's
+ /usr is mounted into.
+
+* add dm-verity boots, and in nspawn (libcryptsetup knows this, should be relatively straight-forward)
+
+* machined: add apis to query /etc/machine-info data of a container
+
+* .mount and .swap units: add Format=yes|no option that formats the partition before mounting/enabling it, implicitly
+
+* gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file
+
* drop nss-myhostname in favour of nss-resolve?
* drop internal dlopen() based nss-dns fallback in nss-resolve, and rely on the
@@ -279,8 +308,6 @@ Features:
* For timer units: add some mechanisms so that timer units that trigger immediately on boot do not have the services
they run added to the initial transaction and thus confuse Type=idle.
-* Run most system services with cgroupfs read-only and procfs with a more secure mode (doesn't work, since the hidepid= option is per-pid-namespace, not per-mount)
-
* add bus api to query unit file's X fields.
* gpt-auto-generator:
diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml
index 5538805e65..ff3638c909 100644
--- a/man/sd_journal_print.xml
+++ b/man/sd_journal_print.xml
@@ -189,10 +189,9 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
<refsect1>
<title>Return Value</title>
- <para>The four calls return 0 on success or a negative errno-style
- error code. The
- <citerefentry project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- variable itself is not altered.</para>
+ <para>The five calls return 0 on success or a negative errno-style error code. The <citerefentry
+ project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> variable itself is
+ not altered.</para>
<para>If
<citerefentry><refentrytitle>systemd-journald</refentrytitle><manvolnum>8</manvolnum></citerefentry>
@@ -218,13 +217,11 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
<refsect1>
<title>Notes</title>
- <para>The <function>sd_journal_print()</function>,
- <function>sd_journal_printv()</function>,
- <function>sd_journal_send()</function> and
- <function>sd_journal_sendv()</function> interfaces are available
- as a shared library, which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <para>The <function>sd_journal_print()</function>, <function>sd_journal_printv()</function>,
+ <function>sd_journal_send()</function>, <function>sd_journal_sendv()</function> and
+ <function>sd_journal_perror()</function> interfaces are available as a shared library, which can be compiled and
+ linked to with the <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
</refsect1>
<refsect1>
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 68c8546189..acf975138a 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -882,17 +882,21 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>show</command> <optional><replaceable>PATTERN</replaceable>…|<replaceable>JOB</replaceable>…</optional></term>
<listitem>
- <para>Show properties of one or more units, jobs, or the
- manager itself. If no argument is specified, properties of
- the manager will be shown. If a unit name is specified,
- properties of the unit are shown, and if a job ID is
- specified, properties of the job are shown. By default, empty
- properties are suppressed. Use <option>--all</option> to
- show those too. To select specific properties to show, use
- <option>--property=</option>. This command is intended to be
- used whenever computer-parsable output is required. Use
- <command>status</command> if you are looking for formatted
- human-readable output.</para>
+ <para>Show properties of one or more units, jobs, or the manager itself. If no argument is specified,
+ properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and
+ if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use
+ <option>--all</option> to show those too. To select specific properties to show, use
+ <option>--property=</option>. This command is intended to be used whenever computer-parsable output is
+ required. Use <command>status</command> if you are looking for formatted human-readable output.</para>
+
+ <para>Many properties shown by <command>systemctl show</command> map directly to configuration settings of
+ the system and service manager and its unit files. Note that the properties shown by the command are
+ generally more low-level, normalized versions of the original configuration settings and expose runtime
+ state in addition to configuration. For example, properties shown for service units include the service's
+ current main process identifier as <literal>MainPID</literal> (which is runtime state), and time settings
+ are always exposed as properties ending in the <literal>…USec</literal> suffix even if a matching
+ configuration options end in <literal>…Sec</literal>, because microseconds is the normalized time unit used
+ by the system and service manager.</para>
</listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
index 68ff6f8f1c..2117433bf0 100644
--- a/man/systemd.mount.xml
+++ b/man/systemd.mount.xml
@@ -206,6 +206,19 @@
</varlistentry>
<varlistentry>
+ <term><option>x-systemd.device-bound</option></term>
+
+ <listitem><para>The block device backed file system will be upgraded
+ to <varname>BindsTo=</varname> dependency. This option is only useful
+ when mounting file systems manually with
+ <citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ as the default dependency in this case is <varname>Requires=</varname>.
+ This option is already implied by entries in <filename>/etc/fstab</filename>
+ or by mount units.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>x-systemd.automount</option></term>
<listitem><para>An automount unit will be created for the file
diff --git a/mkosi.build b/mkosi.build
index 94a6667e42..872841eb63 100755
--- a/mkosi.build
+++ b/mkosi.build
@@ -22,4 +22,14 @@
./autogen.sh c
make -j `nproc`
+
+make check
make install
+
+mkdir -p $DESTDIR/etc
+
+cat > $DESTDIR/etc/issue <<EOF
+\S (built from systemd tree)
+Kernel \r on an \m (\l)
+
+EOF
diff --git a/rules/60-cdrom_id.rules b/rules/60-cdrom_id.rules
index 5c3b52ebb9..f91d8cb456 100644
--- a/rules/60-cdrom_id.rules
+++ b/rules/60-cdrom_id.rules
@@ -8,6 +8,10 @@ ENV{DEVTYPE}!="disk", GOTO="cdrom_end"
# unconditionally tag device as CDROM
KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1"
+# stop automatically any mount units bound to the device if the media eject
+# button is pressed.
+ENV{ID_CDROM}=="1", ENV{SYSTEMD_MOUNT_DEVICE_BOUND}="1"
+
# media eject button pressed
ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end"
diff --git a/rules/78-sound-card.rules b/rules/78-sound-card.rules
index 04740e8b97..f2fc277396 100644
--- a/rules/78-sound-card.rules
+++ b/rules/78-sound-card.rules
@@ -48,6 +48,13 @@ SUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \
SUBSYSTEMS=="firewire", GOTO="skip_pci"
SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
+SUBSYSTEMS=="pci", GOTO="skip_pci"
+
+# If we reach here, the device nor any of its parents are USB/PCI/firewire bus devices.
+# If we now find a parent that is a platform device, assume that we're working with
+# an internal sound card.
+SUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end"
+
LABEL="skip_pci"
# Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both
diff --git a/src/basic/log.c b/src/basic/log.c
index 71d5a0baa2..557212c022 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -243,13 +243,13 @@ int log_open(void) {
return 0;
}
- if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
+ if (!IN_SET(log_target, LOG_TARGET_AUTO, LOG_TARGET_SAFE) ||
getpid() == 1 ||
isatty(STDERR_FILENO) <= 0) {
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) {
+ if (IN_SET(log_target, LOG_TARGET_AUTO,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_JOURNAL)) {
r = log_open_journal();
if (r >= 0) {
log_close_syslog();
@@ -258,8 +258,8 @@ int log_open(void) {
}
}
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
+ if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
+ LOG_TARGET_SYSLOG)) {
r = log_open_syslog();
if (r >= 0) {
log_close_journal();
@@ -268,11 +268,11 @@ int log_open(void) {
}
}
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_SAFE ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_KMSG) {
+ if (IN_SET(log_target, LOG_TARGET_AUTO,
+ LOG_TARGET_SAFE,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_SYSLOG_OR_KMSG,
+ LOG_TARGET_KMSG)) {
r = log_open_kmsg();
if (r >= 0) {
log_close_journal();
@@ -588,9 +588,9 @@ static int log_dispatch(
if ((e = strpbrk(buffer, NEWLINE)))
*(e++) = 0;
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) {
+ if (IN_SET(log_target, LOG_TARGET_AUTO,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_JOURNAL)) {
k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
if (k < 0) {
@@ -600,8 +600,8 @@ static int log_dispatch(
}
}
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
+ if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
+ LOG_TARGET_SYSLOG)) {
k = write_to_syslog(level, error, file, line, func, buffer);
if (k < 0) {
@@ -612,11 +612,11 @@ static int log_dispatch(
}
if (k <= 0 &&
- (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_SAFE ||
- log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_KMSG)) {
+ IN_SET(log_target, LOG_TARGET_AUTO,
+ LOG_TARGET_SAFE,
+ LOG_TARGET_SYSLOG_OR_KMSG,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_KMSG)) {
k = write_to_kmsg(level, error, file, line, func, buffer);
if (k < 0) {
@@ -881,9 +881,9 @@ int log_struct_internal(
if ((level & LOG_FACMASK) == 0)
level = log_facility | LOG_PRI(level);
- if ((log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) &&
+ if (IN_SET(log_target, LOG_TARGET_AUTO,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_JOURNAL) &&
journal_fd >= 0) {
char header[LINE_MAX];
struct iovec iovec[17] = {};
@@ -1078,8 +1078,8 @@ int log_show_location_from_string(const char *e) {
}
bool log_on_console(void) {
- if (log_target == LOG_TARGET_CONSOLE ||
- log_target == LOG_TARGET_CONSOLE_PREFIXED)
+ if (IN_SET(log_target, LOG_TARGET_CONSOLE,
+ LOG_TARGET_CONSOLE_PREFIXED))
return true;
return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 8970050408..840e94a553 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -693,13 +693,12 @@ int umount_verbose(const char *what) {
const char *mount_propagation_flags_to_string(unsigned long flags) {
switch (flags & (MS_SHARED|MS_SLAVE|MS_PRIVATE)) {
-
+ case 0:
+ return "";
case MS_SHARED:
return "shared";
-
case MS_SLAVE:
return "slave";
-
case MS_PRIVATE:
return "private";
}
@@ -707,17 +706,18 @@ const char *mount_propagation_flags_to_string(unsigned long flags) {
return NULL;
}
-unsigned long mount_propagation_flags_from_string(const char *name) {
- if (isempty(name))
- return 0;
-
- if (streq(name, "shared"))
- return MS_SHARED;
- if (streq(name, "slave"))
- return MS_SLAVE;
- if (streq(name, "private"))
- return MS_PRIVATE;
+int mount_propagation_flags_from_string(const char *name, unsigned long *ret) {
+ if (isempty(name))
+ *ret = 0;
+ else if (streq(name, "shared"))
+ *ret = MS_SHARED;
+ else if (streq(name, "slave"))
+ *ret = MS_SLAVE;
+ else if (streq(name, "private"))
+ *ret = MS_PRIVATE;
+ else
+ return -EINVAL;
return 0;
}
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
index c8049198d4..1615c94e9a 100644
--- a/src/basic/mount-util.h
+++ b/src/basic/mount-util.h
@@ -63,4 +63,4 @@ int mount_verbose(
int umount_verbose(const char *where);
const char *mount_propagation_flags_to_string(unsigned long flags);
-unsigned long mount_propagation_flags_from_string(const char *name);
+int mount_propagation_flags_from_string(const char *name, unsigned long *ret);
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 1f4c2e4e43..d5e7edb589 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
@@ -274,27 +275,100 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
return 0;
}
-void rename_process(const char name[8]) {
- assert(name);
+int rename_process(const char name[]) {
+ static size_t mm_size = 0;
+ static char *mm = NULL;
+ bool truncated = false;
+ size_t l;
+
+ /* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
+ * internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
+ * many cases one of 10 (i.e. length of "/sbin/init") — however if we have CAP_SYS_RESOURCES it is unbounded;
+ * to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
+ * truncated.
+ *
+ * Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
+
+ if (isempty(name))
+ return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
- /* This is a like a poor man's setproctitle(). It changes the
- * comm field, argv[0], and also the glibc's internally used
- * name of the process. For the first one a limit of 16 chars
- * applies, to the second one usually one of 10 (i.e. length
- * of "/sbin/init"), to the third one one of 7 (i.e. length of
- * "systemd"). If you pass a longer string it will be
- * truncated */
+ l = strlen(name);
+ /* First step, change the comm field. */
(void) prctl(PR_SET_NAME, name);
+ if (l > 15) /* Linux process names can be 15 chars at max */
+ truncated = true;
+
+ /* Second step, change glibc's ID of the process name. */
+ if (program_invocation_name) {
+ size_t k;
+
+ k = strlen(program_invocation_name);
+ strncpy(program_invocation_name, name, k);
+ if (l > k)
+ truncated = true;
+ }
+
+ /* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
+ * has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
+ * the end. This is the best option for changing /proc/self/cmdline.*/
+ if (mm_size < l+1) {
+ size_t nn_size;
+ char *nn;
+
+ /* Let's not bother with this if we don't have euid == 0. Strictly speaking if people do weird stuff
+ * with capabilities this could work even for euid != 0, but our own code generally doesn't do that,
+ * hence let's use this as quick bypass check, to avoid calling mmap() if PR_SET_MM_ARG_START fails
+ * with EPERM later on anyway. After all geteuid() is dead cheap to call, but mmap() is not. */
+ if (geteuid() != 0) {
+ log_debug("Skipping PR_SET_MM_ARG_START, as we don't have privileges.");
+ goto use_saved_argv;
+ }
+
+ nn_size = PAGE_ALIGN(l+1);
+ nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (nn == MAP_FAILED) {
+ log_debug_errno(errno, "mmap() failed: %m");
+ goto use_saved_argv;
+ }
+
+ strncpy(nn, name, nn_size);
+
+ /* Now, let's tell the kernel about this new memory */
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
+ log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m");
+ (void) munmap(nn, nn_size);
+ goto use_saved_argv;
+ }
+
+ /* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's
+ * pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
+ log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
- if (program_invocation_name)
- strncpy(program_invocation_name, name, strlen(program_invocation_name));
+ if (mm)
+ (void) munmap(mm, mm_size);
+
+ mm = nn;
+ mm_size = nn_size;
+ } else
+ strncpy(mm, name, mm_size);
+
+use_saved_argv:
+ /* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
+ * it still looks here */
if (saved_argc > 0) {
int i;
- if (saved_argv[0])
- strncpy(saved_argv[0], name, strlen(saved_argv[0]));
+ if (saved_argv[0]) {
+ size_t k;
+
+ k = strlen(saved_argv[0]);
+ strncpy(saved_argv[0], name, k);
+ if (l > k)
+ truncated = true;
+ }
for (i = 1; i < saved_argc; i++) {
if (!saved_argv[i])
@@ -303,6 +377,8 @@ void rename_process(const char name[8]) {
memzero(saved_argv[i], strlen(saved_argv[i]));
}
}
+
+ return !truncated;
}
int is_kernel_thread(pid_t pid) {
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 89dfeb4d6a..d378901399 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -64,7 +64,7 @@ void sigkill_waitp(pid_t *pid);
int kill_and_sigcont(pid_t pid, int sig);
-void rename_process(const char name[8]);
+int rename_process(const char name[]);
int is_kernel_thread(pid_t pid);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 9b7eb71319..33641e6886 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -409,8 +409,7 @@ int detect_container(void) {
if (cached_found >= 0)
return cached_found;
- /* /proc/vz exists in container and outside of the container,
- * /proc/bc only outside of the container. */
+ /* /proc/vz exists in container and outside of the container, /proc/bc only outside of the container. */
if (access("/proc/vz", F_OK) >= 0 &&
access("/proc/bc", F_OK) < 0) {
r = VIRTUALIZATION_OPENVZ;
@@ -418,50 +417,58 @@ int detect_container(void) {
}
if (getpid() == 1) {
- /* If we are PID 1 we can just check our own
- * environment variable */
+ /* If we are PID 1 we can just check our own environment variable, and that's authoritative. */
e = getenv("container");
if (isempty(e)) {
r = VIRTUALIZATION_NONE;
goto finish;
}
- } else {
-
- /* Otherwise, PID 1 dropped this information into a
- * file in /run. This is better than accessing
- * /proc/1/environ, since we don't need CAP_SYS_PTRACE
- * for that. */
-
- r = read_one_line_file("/run/systemd/container", &m);
- if (r == -ENOENT) {
-
- /* Fallback for cases where PID 1 was not
- * systemd (for example, cases where
- * init=/bin/sh is used. */
-
- r = getenv_for_pid(1, "container", &m);
- if (r <= 0) {
-
- /* If that didn't work, give up,
- * assume no container manager.
- *
- * Note: This means we still cannot
- * detect containers if init=/bin/sh
- * is passed but privileges dropped,
- * as /proc/1/environ is only readable
- * with privileges. */
-
- r = VIRTUALIZATION_NONE;
- goto finish;
- }
- }
- if (r < 0)
- return r;
+ goto translate_name;
+ }
+
+ /* Otherwise, PID 1 might have dropped this information into a file in /run. This is better than accessing
+ * /proc/1/environ, since we don't need CAP_SYS_PTRACE for that. */
+ r = read_one_line_file("/run/systemd/container", &m);
+ if (r >= 0) {
+ e = m;
+ goto translate_name;
+ }
+ if (r != -ENOENT)
+ return log_debug_errno(r, "Failed to read /run/systemd/container: %m");
+
+ /* Fallback for cases where PID 1 was not systemd (for example, cases where init=/bin/sh is used. */
+ r = getenv_for_pid(1, "container", &m);
+ if (r > 0) {
e = m;
+ goto translate_name;
}
+ if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
+ log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
+
+ /* Interestingly /proc/1/sched actually shows the host's PID for what we see as PID 1. Hence, if the PID shown
+ * there is not 1, we know we are in a PID namespace. and hence a container. */
+ r = read_one_line_file("/proc/1/sched", &m);
+ if (r >= 0) {
+ const char *t;
+
+ t = strrchr(m, '(');
+ if (!t)
+ return -EIO;
+
+ if (!startswith(t, "(1,")) {
+ r = VIRTUALIZATION_CONTAINER_OTHER;
+ goto finish;
+ }
+ } else if (r != -ENOENT)
+ return r;
+
+ /* If that didn't work, give up, assume no container manager. */
+ r = VIRTUALIZATION_NONE;
+ goto finish;
+translate_name:
for (j = 0; j < ELEMENTSOF(value_table); j++)
if (streq(e, value_table[j].value)) {
r = value_table[j].id;
@@ -471,7 +478,7 @@ int detect_container(void) {
r = VIRTUALIZATION_CONTAINER_OTHER;
finish:
- log_debug("Found container virtualization %s", virtualization_to_string(r));
+ log_debug("Found container virtualization %s.", virtualization_to_string(r));
cached_found = r;
return r;
}
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index dc11b0d9db..b747a95133 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -255,7 +255,7 @@ static int find_esp(uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_
if (!arg_path)
return log_oom();
- log_info("Using EFI System Parition at %s.", path);
+ log_info("Using EFI System Partition at %s.", path);
return 0;
}
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index b3fc0ff5c3..9960b7a811 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -1671,7 +1671,7 @@ int bus_exec_context_set_transient_property(
if (mode != UNIT_CHECK) {
c->mount_flags = flags;
- unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, strempty(mount_propagation_flags_to_string(flags)));
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, mount_propagation_flags_to_string(flags));
}
return 1;
diff --git a/src/core/device.c b/src/core/device.c
index e345552f24..bd481c8050 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -285,6 +285,37 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
}
}
+static bool device_is_bound_by_mounts(Unit *d, struct udev_device *dev) {
+ const char *bound_by;
+ int r = false;
+
+ assert(d);
+ assert(dev);
+
+ bound_by = udev_device_get_property_value(dev, "SYSTEMD_MOUNT_DEVICE_BOUND");
+ if (bound_by)
+ r = parse_boolean(bound_by) > 0;
+
+ DEVICE(d)->bind_mounts = r;
+ return r;
+}
+
+static int device_upgrade_mount_deps(Unit *u) {
+ Unit *other;
+ Iterator i;
+ int r;
+
+ SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) {
+ if (other->type != UNIT_MOUNT)
+ continue;
+
+ r = unit_add_dependency(other, UNIT_BINDS_TO, u, true);
+ if (r < 0)
+ return r;
+ }
+ return 0;
+}
+
static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
_cleanup_free_ char *e = NULL;
const char *sysfs = NULL;
@@ -349,6 +380,13 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
(void) device_add_udev_wants(u, dev);
}
+ /* So the user wants the mount units to be bound to the device but a
+ * mount unit might has been seen by systemd before the device appears
+ * on its radar. In this case the device unit is partially initialized
+ * and includes the deps on the mount unit but at that time the "bind
+ * mounts" flag wasn't not present. Fix this up now. */
+ if (device_is_bound_by_mounts(u, dev))
+ device_upgrade_mount_deps(u);
/* Note that this won't dispatch the load queue, the caller
* has to do that if needed and appropriate */
@@ -824,6 +862,14 @@ int device_found_node(Manager *m, const char *node, bool add, DeviceFound found,
return device_update_found_by_name(m, node, add, found, now);
}
+bool device_shall_be_bound_by(Unit *device, Unit *u) {
+
+ if (u->type != UNIT_MOUNT)
+ return false;
+
+ return DEVICE(device)->bind_mounts;
+}
+
const UnitVTable device_vtable = {
.object_size = sizeof(Device),
.sections =
diff --git a/src/core/device.h b/src/core/device.h
index 184a1a349b..dd372fb695 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -40,8 +40,11 @@ struct Device {
LIST_FIELDS(struct Device, same_sysfs);
DeviceState state, deserialized_state;
+
+ bool bind_mounts;
};
extern const UnitVTable device_vtable;
int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now);
+bool device_shall_be_bound_by(Unit *device, Unit *u);
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index f325d853c6..bc0cf73d39 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1278,25 +1278,17 @@ int config_parse_exec_mount_flags(
void *userdata) {
- unsigned long flags;
ExecContext *c = data;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (isempty(rvalue))
- flags = 0;
- else {
- flags = mount_propagation_flags_from_string(rvalue);
- if (flags == 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue);
- return 0;
- }
- }
-
- c->mount_flags = flags;
+ r = mount_propagation_flags_from_string(rvalue, &c->mount_flags);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue);
return 0;
}
diff --git a/src/core/main.c b/src/core/main.c
index 5f9b1acad3..02992c7324 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -904,7 +904,6 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_UNIT:
-
r = free_and_strdup(&arg_default_unit, optarg);
if (r < 0)
return log_error_errno(r, "Failed to set default unit %s: %m", optarg);
diff --git a/src/core/manager.c b/src/core/manager.c
index 1192b20b74..d83c5ef5e2 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2165,7 +2165,7 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint
assert(m);
assert(m->time_change_fd == fd);
- log_struct(LOG_INFO,
+ log_struct(LOG_DEBUG,
LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
LOG_MESSAGE("Time has been changed"),
NULL);
diff --git a/src/core/mount.c b/src/core/mount.c
index 997dbe3837..daf7f5697b 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -135,6 +135,16 @@ static bool mount_state_active(MountState state) {
MOUNT_REMOUNTING_SIGKILL);
}
+static bool mount_is_bound_to_device(const Mount *m) {
+ const MountParameters *p;
+
+ if (m->from_fragment)
+ return true;
+
+ p = &m->parameters_proc_self_mountinfo;
+ return fstab_test_option(p->options, "x-systemd.device-bound\0");
+}
+
static bool needs_quota(const MountParameters *p) {
assert(p);
@@ -324,6 +334,7 @@ static int mount_add_mount_links(Mount *m) {
static int mount_add_device_links(Mount *m) {
MountParameters *p;
bool device_wants_mount = false;
+ UnitDependency dep;
int r;
assert(m);
@@ -353,7 +364,14 @@ static int mount_add_device_links(Mount *m) {
if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager))
device_wants_mount = true;
- r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
+ /* Mount units from /proc/self/mountinfo are not bound to devices
+ * by default since they're subject to races when devices are
+ * unplugged. But the user can still force this dep with an
+ * appropriate option (or udev property) so the mount units are
+ * automatically stopped when the device disappears suddenly. */
+ dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
+
+ r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, dep);
if (r < 0)
return r;
diff --git a/src/core/socket.c b/src/core/socket.c
index fee9b702e6..0960a30039 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -423,8 +423,7 @@ static const char *socket_find_symlink_target(Socket *s) {
break;
case SOCKET_SOCKET:
- if (p->address.sockaddr.un.sun_path[0] != 0)
- f = p->address.sockaddr.un.sun_path;
+ f = socket_address_get_path(&p->address);
break;
default:
diff --git a/src/core/unit.c b/src/core/unit.c
index ab40135736..5d0b17425b 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -3048,6 +3048,9 @@ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep
if (r < 0)
return r;
+ if (dep == UNIT_REQUIRES && device_shall_be_bound_by(device, u))
+ dep = UNIT_BINDS_TO;
+
r = unit_add_two_dependencies(u, UNIT_AFTER,
MANAGER_IS_SYSTEM(u->manager) ? dep : UNIT_WANTS,
device, true);
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index 877bbb34fc..646757f9d9 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -821,6 +821,9 @@ static int run_gdb(sd_journal *j) {
if (r < 0)
return r;
+ /* Don't interfere with gdb and its handling of SIGINT. */
+ (void) ignore_signals(SIGINT, -1);
+
pid = fork();
if (pid < 0) {
r = log_error_errno(errno, "Failed to fork(): %m");
@@ -845,6 +848,8 @@ static int run_gdb(sd_journal *j) {
r = st.si_code == CLD_EXITED ? st.si_status : 255;
finish:
+ (void) default_signals(SIGINT, -1);
+
if (unlink_path) {
log_debug("Removed temporary file %s", path);
unlink(path);
diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c
index 1ee3471355..28ebe36b38 100644
--- a/src/debug-generator/debug-generator.c
+++ b/src/debug-generator/debug-generator.c
@@ -135,8 +135,9 @@ static int generate_wants_symlinks(void) {
STRV_FOREACH(u, arg_wants) {
_cleanup_free_ char *p = NULL, *f = NULL;
+ const char *target = arg_default_unit ?: SPECIAL_DEFAULT_TARGET;
- p = strjoin(arg_dest, "/", arg_default_unit, ".wants/", *u);
+ p = strjoin(arg_dest, "/", target, ".wants/", *u);
if (!p)
return log_oom();
@@ -172,12 +173,6 @@ int main(int argc, char *argv[]) {
umask(0022);
- r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
- if (r < 0) {
- log_error_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
- goto finish;
- }
-
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
@@ -197,6 +192,7 @@ int main(int argc, char *argv[]) {
r = q;
finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ arg_default_unit = mfree(arg_default_unit);
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 10d3ff3b45..ecd1e94a33 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -2318,7 +2318,7 @@ int main(int argc, char *argv[]) {
if (arg_boot_offset != 0 &&
sd_journal_has_runtime_files(j) > 0 &&
sd_journal_has_persistent_files(j) == 0) {
- log_info("Specifying boot ID has no effect, no persistent journal was found");
+ log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
r = 0;
goto finish;
}
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
index 72cadf1771..0469393f3b 100644
--- a/src/journal/test-compress.c
+++ b/src/journal/test-compress.c
@@ -216,7 +216,11 @@ static void test_lz4_decompress_partial(void) {
memset(huge, 'x', HUGE_SIZE);
memcpy(huge, "HUGE=", 5);
+#if LZ4_VERSION_NUMBER >= 10700
+ r = LZ4_compress_default(huge, buf, HUGE_SIZE, buf_size);
+#else
r = LZ4_compress_limitedOutput(huge, buf, HUGE_SIZE, buf_size);
+#endif
assert_se(r >= 0);
compressed = r;
log_info("Compressed %i → %zu", HUGE_SIZE, compressed);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 3294ea7821..36c2607ba9 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -2769,7 +2769,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argv);
for (;;) {
- static const char option_string[] = "-hp:als:H:M:qn:o:";
+ static const char option_string[] = "-hp:als:H:M:qn:o:E:";
c = getopt_long(argc, argv, option_string + reorder, options, NULL);
if (c < 0)
diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c
index 2de87e3c63..38ab37367e 100644
--- a/src/nspawn/nspawn-stub-pid1.c
+++ b/src/nspawn/nspawn-stub-pid1.c
@@ -20,6 +20,7 @@
#include <sys/reboot.h>
#include <sys/unistd.h>
#include <sys/wait.h>
+#include <sys/prctl.h>
#include "fd-util.h"
#include "log.h"
@@ -29,7 +30,22 @@
#include "time-util.h"
#include "def.h"
-int stub_pid1(void) {
+static int reset_environ(const char *new_environment, size_t length) {
+ unsigned long start, end;
+
+ start = (unsigned long) new_environment;
+ end = start + length;
+
+ if (prctl(PR_SET_MM, PR_SET_MM_ENV_START, start, 0, 0) < 0)
+ return -errno;
+
+ if (prctl(PR_SET_MM, PR_SET_MM_ENV_END, end, 0, 0) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int stub_pid1(sd_id128_t uuid) {
enum {
STATE_RUNNING,
STATE_REBOOT,
@@ -41,6 +57,11 @@ int stub_pid1(void) {
pid_t pid;
int r;
+ /* The new environment we set up, on the stack. */
+ char new_environment[] =
+ "container=systemd-nspawn\0"
+ "container_uuid=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+
/* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful
* for allowing arbitrary processes run in a container, and still have all zombies reaped. */
@@ -64,6 +85,12 @@ int stub_pid1(void) {
close_all_fds(NULL, 0);
log_open();
+ /* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
+ * set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
+ * find them set set. */
+ sd_id128_to_string(uuid, new_environment + sizeof(new_environment) - SD_ID128_STRING_MAX);
+ reset_environ(new_environment, sizeof(new_environment));
+
rename_process("STUBINIT");
assert_se(sigemptyset(&waitmask) >= 0);
diff --git a/src/nspawn/nspawn-stub-pid1.h b/src/nspawn/nspawn-stub-pid1.h
index 36c1aaf5dd..7ca83078c0 100644
--- a/src/nspawn/nspawn-stub-pid1.h
+++ b/src/nspawn/nspawn-stub-pid1.h
@@ -19,4 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int stub_pid1(void);
+#include "sd-id128.h"
+
+int stub_pid1(sd_id128_t uuid);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 080bd7c31e..dcc639f15c 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2278,7 +2278,7 @@ static int inner_child(
return log_error_errno(errno, "Failed to change to specified working directory %s: %m", arg_chdir);
if (arg_start_mode == START_PID2) {
- r = stub_pid1();
+ r = stub_pid1(arg_uuid);
if (r < 0)
return r;
}
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index b030b3b9d1..829be2c6da 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -579,15 +579,9 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
else if (streq(field, "MountFlags")) {
unsigned long f;
- if (isempty(eq))
- f = 0;
- else {
- f = mount_propagation_flags_from_string(eq);
- if (f == 0) {
- log_error("Failed to parse mount propagation type: %s", eq);
- return -EINVAL;
- }
- }
+ r = mount_propagation_flags_from_string(eq, &f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse mount propagation flags: %s", eq);
r = sd_bus_message_append(m, "v", "t", f);
} else if (STR_IN_SET(field, "BindPaths", "BindReadOnlyPaths")) {
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index a3d677f068..6ffb169b21 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -22,12 +22,12 @@
#include "fs-util.h"
#include "log.h"
+#include "special.h"
#include "string-util.h"
#include "util.h"
/*
- * Implements the logic described in
- * http://freedesktop.org/wiki/Software/systemd/SystemUpdates
+ * Implements the logic described in systemd.offline-updates(7).
*/
static const char *arg_dest = "/tmp";
@@ -43,7 +43,7 @@ static int generate_symlink(void) {
return -EINVAL;
}
- p = strjoina(arg_dest, "/default.target");
+ p = strjoina(arg_dest, "/" SPECIAL_DEFAULT_TARGET);
if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0)
return log_error_errno(errno, "Failed to create symlink %s: %m", p);
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 921fd478d0..9fde9b1884 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -292,8 +292,10 @@ static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name,
if (!streq(table[i], n))
continue;
- if (!table[i+1])
+ if (!table[i+1]) {
+ *ret = NULL;
return 0;
+ }
m = strdup(table[i+1]);
if (!m)
@@ -312,7 +314,7 @@ static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name,
if (r < 0)
return log_error_errno(r, "[%s:%u] Could not build name for facility %s: %m", s->path, line, name);
- return r;
+ return 1;
}
/* Strip ".sh" suffix from file name for comparison */
@@ -324,8 +326,10 @@ static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name,
}
/* Names equaling the file name of the services are redundant */
- if (streq_ptr(n, filename))
+ if (streq_ptr(n, filename)) {
+ *ret = NULL;
return 0;
+ }
/* Everything else we assume to be normal service names */
m = sysv_translate_name(n);
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index a98de76b43..d0bc8004f3 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -22,6 +22,7 @@
#include "install.h"
#include "mkdir.h"
#include "rm-rf.h"
+#include "special.h"
#include "string-util.h"
static void test_basic_mask_and_enable(const char *root) {
@@ -338,7 +339,7 @@ static void test_default(const char *root) {
assert_se(n_changes == 1);
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
- p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target");
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH "/" SPECIAL_DEFAULT_TARGET);
assert_se(streq(changes[0].path, p));
unit_file_changes_free(changes, n_changes);
changes = NULL; n_changes = 0;
diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c
index da7f35623b..7c5929d009 100644
--- a/src/test/test-mount-util.c
+++ b/src/test/test-mount-util.c
@@ -23,23 +23,35 @@
#include "mount-util.h"
#include "string-util.h"
-static void test_mount_propagation_flags(const char *name, unsigned long f) {
- assert(mount_propagation_flags_from_string(name) == f);
+static void test_mount_propagation_flags(const char *name, int ret, unsigned long expected) {
+ long unsigned flags;
- if (f != 0)
- assert_se(streq_ptr(mount_propagation_flags_to_string(f), name));
+ assert(mount_propagation_flags_from_string(name, &flags) == ret);
+
+ if (ret >= 0) {
+ const char *c;
+
+ assert_se(flags == expected);
+
+ c = mount_propagation_flags_to_string(flags);
+ if (isempty(name))
+ assert_se(isempty(c));
+ else
+ assert_se(streq(c, name));
+ }
}
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
- test_mount_propagation_flags("shared", MS_SHARED);
- test_mount_propagation_flags("slave", MS_SLAVE);
- test_mount_propagation_flags("private", MS_PRIVATE);
- test_mount_propagation_flags(NULL, 0);
- test_mount_propagation_flags("", 0);
- test_mount_propagation_flags("xxxx", 0);
+ test_mount_propagation_flags("shared", 0, MS_SHARED);
+ test_mount_propagation_flags("slave", 0, MS_SLAVE);
+ test_mount_propagation_flags("private", 0, MS_PRIVATE);
+ test_mount_propagation_flags(NULL, 0, 0);
+ test_mount_propagation_flags("", 0, 0);
+ test_mount_propagation_flags("xxxx", -EINVAL, 0);
+ test_mount_propagation_flags(" ", -EINVAL, 0);
return 0;
}
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 7242b2c8b5..c5edbcc5d2 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -355,10 +355,70 @@ static void test_get_process_cmdline_harder(void) {
_exit(0);
}
+static void test_rename_process_one(const char *p, int ret) {
+ _cleanup_free_ char *comm = NULL, *cmdline = NULL;
+ pid_t pid;
+ int r;
+
+ pid = fork();
+ assert_se(pid >= 0);
+
+ if (pid > 0) {
+ siginfo_t si;
+
+ assert_se(wait_for_terminate(pid, &si) >= 0);
+ assert_se(si.si_code == CLD_EXITED);
+ assert_se(si.si_status == EXIT_SUCCESS);
+
+ return;
+ }
+
+ /* child */
+ r = rename_process(p);
+
+ assert_se(r == ret ||
+ (ret == 0 && r >= 0) ||
+ (ret > 0 && r > 0));
+
+ if (r < 0)
+ goto finish;
+
+#ifdef HAVE_VALGRIND_VALGRIND_H
+ /* see above, valgrind is weird, we can't verify what we are doing here */
+ if (RUNNING_ON_VALGRIND)
+ goto finish;
+#endif
+
+ assert_se(get_process_comm(0, &comm) >= 0);
+ log_info("comm = <%s>", comm);
+ assert_se(strneq(comm, p, 15));
+
+ assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
+ log_info("cmdline = <%s>", cmdline);
+ assert_se(strneq(p, cmdline, strlen("test-process-util")));
+ assert_se(startswith(p, cmdline));
+
+finish:
+ _exit(EXIT_SUCCESS);
+}
+
+static void test_rename_process(void) {
+ test_rename_process_one(NULL, -EINVAL);
+ test_rename_process_one("", -EINVAL);
+ test_rename_process_one("foo", 1); /* should always fit */
+ test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
+ test_rename_process_one("1234567", 1); /* should always fit */
+}
+
int main(int argc, char *argv[]) {
+
+ log_set_max_level(LOG_DEBUG);
log_parse_environment();
log_open();
+ saved_argc = argc;
+ saved_argv = argv;
+
if (argc > 1) {
pid_t pid = 0;
@@ -373,6 +433,7 @@ int main(int argc, char *argv[]) {
test_pid_is_alive();
test_personality();
test_get_process_cmdline_harder();
+ test_rename_process();
return 0;
}