summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 02:21:11 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 02:21:11 +0000
commit7a0051878bc44176aae8f9ca8743f234e6df1d72 (patch)
tree1e33fbce443dfaf2f246fe133925c059eb707854
parentAdding upstream version 252.25. (diff)
downloadsystemd-7a0051878bc44176aae8f9ca8743f234e6df1d72.tar.xz
systemd-7a0051878bc44176aae8f9ca8743f234e6df1d72.zip
Adding upstream version 252.26.upstream/252.26upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rwxr-xr-x.semaphore/semaphore-runner.sh3
-rw-r--r--man/systemd-run.xml21
-rw-r--r--src/basic/linux/netfilter.h76
-rw-r--r--src/core/execute.c28
-rw-r--r--src/core/import-creds.c2
-rw-r--r--src/import/curl-util.c7
-rw-r--r--src/libsystemd-network/icmp6-util.c4
-rw-r--r--src/libsystemd-network/test-dhcp-client.c2
-rw-r--r--src/libsystemd-network/test-dhcp-server.c4
-rw-r--r--src/libsystemd-network/test-dhcp6-client.c2
-rw-r--r--src/libsystemd-network/test-ndisc-ra.c2
-rw-r--r--src/machine/image-dbus.c79
-rw-r--r--src/machine/image-dbus.h2
-rw-r--r--src/machine/machined-dbus.c5
-rw-r--r--src/run/run.c25
-rw-r--r--src/shared/blockdev-util.c60
-rw-r--r--src/shared/conf-parser.c6
-rw-r--r--src/shared/discover-image.c62
-rw-r--r--src/shared/journal-importer.c14
-rw-r--r--src/shared/libcrypt-util.c2
-rw-r--r--src/shared/ptyfwd.c3
-rw-r--r--src/test/test-namespace.c34
-rw-r--r--src/tmpfiles/tmpfiles.c2
-rwxr-xr-xtest/networkd-test.py15
-rw-r--r--test/test-functions1
-rwxr-xr-xtest/test-network/systemd-networkd-tests.py60
-rwxr-xr-xtest/test-rpm-macros.sh2
-rwxr-xr-xtest/units/testsuite-38.sh2
-rwxr-xr-xtest/units/testsuite-46.sh2
-rwxr-xr-xtest/units/testsuite-58.sh2
-rwxr-xr-xtest/units/testsuite-64.sh7
-rw-r--r--tmpfiles.d/systemd.conf.in9
32 files changed, 410 insertions, 135 deletions
diff --git a/.semaphore/semaphore-runner.sh b/.semaphore/semaphore-runner.sh
index eb10ee6..4a37ee2 100755
--- a/.semaphore/semaphore-runner.sh
+++ b/.semaphore/semaphore-runner.sh
@@ -7,6 +7,7 @@ set -o pipefail
# default to Debian testing
DISTRO="${DISTRO:-debian}"
RELEASE="${RELEASE:-bookworm}"
+SALSA_URL="${SALSA_URL:-https://salsa.debian.org/systemd-team/systemd.git}"
BRANCH="${BRANCH:-upstream-ci}"
ARCH="${ARCH:-amd64}"
CONTAINER="${RELEASE}-${ARCH}"
@@ -69,7 +70,7 @@ for phase in "${PHASES[@]}"; do
;;
RUN)
# add current debian/ packaging
- git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git "$BRANCH"
+ git fetch --depth=1 "$SALSA_URL" "$BRANCH"
git checkout FETCH_HEAD debian
# craft changelog
diff --git a/man/systemd-run.xml b/man/systemd-run.xml
index 0c91d61..d57eda1 100644
--- a/man/systemd-run.xml
+++ b/man/systemd-run.xml
@@ -64,8 +64,8 @@
other service, and thus shows up in the output of <command>systemctl list-units</command> like any other unit. It
will run in a clean and detached execution environment, with the service manager as its parent process. In this
mode, <command>systemd-run</command> will start the service asynchronously in the background and return after the
- command has begun execution (unless <option>--no-block</option> or <option>--wait</option> are specified, see
- below).</para>
+ command has begun execution (unless <option>--no-block</option>, <option>--wait</option>, <option>--pipe</option>,
+ or <option>--pty</option> are specified, see below).</para>
<para>If a command is run as transient scope unit, it will be executed by <command>systemd-run</command>
itself as parent process and will thus inherit the execution environment of the caller. However, the
@@ -262,6 +262,11 @@
to the terminal <command>systemd-run</command> is invoked on, via a pseudo TTY device. This allows running
programs that expect interactive user input/output as services, such as interactive command shells.</para>
+ <para>This option will result in <command>systemd-run</command> synchronously waiting for
+ the transient service to terminate, similar to specifying <option>--wait</option>. If specified
+ along with <option>--wait</option>, <command>systemd-run</command> won't exit when manually disconnecting
+ from the pseudo TTY device.</para>
+
<para>Note that
<citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<command>shell</command> command is usually a better alternative for requesting a new, interactive login
@@ -276,15 +281,19 @@
<listitem><para>If specified, standard input, output, and error of the transient service are inherited from the
<command>systemd-run</command> command itself. This allows <command>systemd-run</command>
- to be used within shell pipelines.
- Note that this mode is not suitable for interactive command shells and similar, as the
- service process will not become a TTY controller when invoked on a terminal. Use <option>--pty</option> instead
- in that case.</para>
+ to be used within shell pipelines.</para>
+
+ <para>Note that this mode is not suitable for interactive command shells and similar, as the
+ service process will not become a TTY controller when invoked on a terminal. Use <option>--pty</option>
+ instead in that case.</para>
<para>When both <option>--pipe</option> and <option>--pty</option> are used in combination the more appropriate
option is automatically determined and used. Specifically, when invoked with standard input, output and error
connected to a TTY <option>--pty</option> is used, and otherwise <option>--pipe</option>.</para>
+ <para>This option will result in <command>systemd-run</command> synchronously waiting for
+ the transient service to terminate, similar to specifying <option>--wait</option>.</para>
+
<para>When this option is used the original file descriptors <command>systemd-run</command> receives are passed
to the service processes as-is. If the service runs with different privileges than
<command>systemd-run</command>, this means the service might not be able to re-open the passed file
diff --git a/src/basic/linux/netfilter.h b/src/basic/linux/netfilter.h
new file mode 100644
index 0000000..30c045b
--- /dev/null
+++ b/src/basic/linux/netfilter.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_NETFILTER_H
+#define __LINUX_NETFILTER_H
+
+#include <linux/types.h>
+
+#include <linux/in.h>
+#include <linux/in6.h>
+
+/* Responses from hook functions. */
+#define NF_DROP 0
+#define NF_ACCEPT 1
+#define NF_STOLEN 2
+#define NF_QUEUE 3
+#define NF_REPEAT 4
+#define NF_STOP 5 /* Deprecated, for userspace nf_queue compatibility. */
+#define NF_MAX_VERDICT NF_STOP
+
+/* we overload the higher bits for encoding auxiliary data such as the queue
+ * number or errno values. Not nice, but better than additional function
+ * arguments. */
+#define NF_VERDICT_MASK 0x000000ff
+
+/* extra verdict flags have mask 0x0000ff00 */
+#define NF_VERDICT_FLAG_QUEUE_BYPASS 0x00008000
+
+/* queue number (NF_QUEUE) or errno (NF_DROP) */
+#define NF_VERDICT_QMASK 0xffff0000
+#define NF_VERDICT_QBITS 16
+
+#define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE)
+
+#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP)
+
+/* only for userspace compatibility */
+
+/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */
+#define NF_VERDICT_BITS 16
+
+enum nf_inet_hooks {
+ NF_INET_PRE_ROUTING,
+ NF_INET_LOCAL_IN,
+ NF_INET_FORWARD,
+ NF_INET_LOCAL_OUT,
+ NF_INET_POST_ROUTING,
+ NF_INET_NUMHOOKS,
+ NF_INET_INGRESS = NF_INET_NUMHOOKS,
+};
+
+enum nf_dev_hooks {
+ NF_NETDEV_INGRESS,
+ NF_NETDEV_EGRESS,
+ NF_NETDEV_NUMHOOKS
+};
+
+enum {
+ NFPROTO_UNSPEC = 0,
+ NFPROTO_INET = 1,
+ NFPROTO_IPV4 = 2,
+ NFPROTO_ARP = 3,
+ NFPROTO_NETDEV = 5,
+ NFPROTO_BRIDGE = 7,
+ NFPROTO_IPV6 = 10,
+ NFPROTO_DECNET = 12,
+ NFPROTO_NUMPROTO,
+};
+
+union nf_inet_addr {
+ __u32 all[4];
+ __be32 ip;
+ __be32 ip6[4];
+ struct in_addr in;
+ struct in6_addr in6;
+};
+
+#endif /* __LINUX_NETFILTER_H */
diff --git a/src/core/execute.c b/src/core/execute.c
index 2c1dda1..fc3d2ce 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -4710,12 +4710,14 @@ static int exec_child(
if (ns_type_supported(NAMESPACE_NET)) {
r = setup_shareable_ns(runtime->netns_storage_socket, CLONE_NEWNET);
- if (r == -EPERM)
- log_unit_warning_errno(unit, r,
- "PrivateNetwork=yes is configured, but network namespace setup failed, ignoring: %m");
- else if (r < 0) {
- *exit_status = EXIT_NETWORK;
- return log_unit_error_errno(unit, r, "Failed to set up network namespacing: %m");
+ if (r < 0) {
+ if (ERRNO_IS_PRIVILEGE(r))
+ log_unit_warning_errno(unit, r,
+ "PrivateNetwork=yes is configured, but network namespace setup failed, ignoring: %m");
+ else {
+ *exit_status = EXIT_NETWORK;
+ return log_unit_error_errno(unit, r, "Failed to set up network namespacing: %m");
+ }
}
} else if (context->network_namespace_path) {
*exit_status = EXIT_NETWORK;
@@ -4729,12 +4731,14 @@ static int exec_child(
if (ns_type_supported(NAMESPACE_IPC)) {
r = setup_shareable_ns(runtime->ipcns_storage_socket, CLONE_NEWIPC);
- if (r == -EPERM)
- log_unit_warning_errno(unit, r,
- "PrivateIPC=yes is configured, but IPC namespace setup failed, ignoring: %m");
- else if (r < 0) {
- *exit_status = EXIT_NAMESPACE;
- return log_unit_error_errno(unit, r, "Failed to set up IPC namespacing: %m");
+ if (r < 0) {
+ if (ERRNO_IS_PRIVILEGE(r))
+ log_unit_warning_errno(unit, r,
+ "PrivateIPC=yes is configured, but IPC namespace setup failed, ignoring: %m");
+ else {
+ *exit_status = EXIT_NAMESPACE;
+ return log_unit_error_errno(unit, r, "Failed to set up IPC namespacing: %m");
+ }
}
} else if (context->ipc_namespace_path) {
*exit_status = EXIT_NAMESPACE;
diff --git a/src/core/import-creds.c b/src/core/import-creds.c
index dab7d36..91922ab 100644
--- a/src/core/import-creds.c
+++ b/src/core/import-creds.c
@@ -512,7 +512,7 @@ static int parse_smbios_strings(ImportCredentialContext *c, const char *data, si
return log_oom();
if (!credential_name_valid(cn)) {
- log_warning("SMBIOS credential name '%s' is not valid, ignoring: %m", cn);
+ log_warning("SMBIOS credential name '%s' is not valid, ignoring.", cn);
continue;
}
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 94f718d..b631f4b 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -126,6 +126,13 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata
assert(curl);
+ /* Don't configure timer anymore when the event loop is dead already. */
+ if (g->timer) {
+ sd_event *event_loop = sd_event_source_get_event(g->timer);
+ if (event_loop && sd_event_get_state(event_loop) == SD_EVENT_FINISHED)
+ return 0;
+ }
+
if (timeout_ms < 0) {
if (g->timer) {
if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0)
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
index d3ee7c4..8ea09fd 100644
--- a/src/libsystemd-network/icmp6-util.c
+++ b/src/libsystemd-network/icmp6-util.c
@@ -154,7 +154,7 @@ int icmp6_receive(
/* This needs to be initialized with zero. See #20741. */
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int)) + /* ttl */
CMSG_SPACE_TIMEVAL) control = {};
- struct iovec iov = {};
+ struct iovec iov = { buffer, size };
union sockaddr_union sa = {};
struct msghdr msg = {
.msg_name = &sa.sa,
@@ -169,8 +169,6 @@ int icmp6_receive(
triple_timestamp t = {};
ssize_t len;
- iov = IOVEC_MAKE(buffer, size);
-
len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
if (len < 0)
return (int) len;
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 787dcf1..bf17e51 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -513,7 +513,7 @@ static void test_addr_acq(sd_event *e) {
callback_recv = test_addr_acq_recv_discover;
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
- 2 * USEC_PER_SEC, 0,
+ 30 * USEC_PER_SEC, 0,
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
res = sd_dhcp_client_start(client);
diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c
index f8a4c2c..763ecb9 100644
--- a/src/libsystemd-network/test-dhcp-server.c
+++ b/src/libsystemd-network/test-dhcp-server.c
@@ -62,7 +62,9 @@ static int test_basic(bool bind_to_interface) {
test_pool(&address_lo, 1, 0);
r = sd_dhcp_server_start(server);
- if (r == -EPERM)
+ /* skip test if running in an environment with no full networking support, CONFIG_PACKET not
+ * compiled in kernel, nor af_packet module available. */
+ if (r == -EPERM || r == -EAFNOSUPPORT)
return r;
assert_se(r >= 0);
diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
index 10233f5..a3a22e9 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -1003,7 +1003,7 @@ TEST(dhcp6_client) {
assert_se(sd_event_new(&e) >= 0);
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
- 2 * USEC_PER_SEC, 0,
+ 30 * USEC_PER_SEC, 0,
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
assert_se(sd_dhcp6_client_new(&client) >= 0);
diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c
index d3d96e7..16a934c 100644
--- a/src/libsystemd-network/test-ndisc-ra.c
+++ b/src/libsystemd-network/test-ndisc-ra.c
@@ -332,7 +332,7 @@ TEST(ra) {
assert_se(sd_event_source_set_io_fd_own(recv_router_advertisement, true) >= 0);
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
- 2 * USEC_PER_SEC, 0,
+ 30 * USEC_PER_SEC, 0,
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
assert_se(sd_radv_start(ra) >= 0);
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index 84dc95e..6acbe8d 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -133,9 +133,17 @@ int bus_image_method_rename(
if (r == 0)
return 1; /* Will call us back */
+ /* The image is cached with its name, hence it is necessary to remove from the cache before renaming. */
+ assert_se(hashmap_remove_value(m->image_cache, image->name, image));
+
r = image_rename(image, new_name);
- if (r < 0)
+ if (r < 0) {
+ image_unref(image);
return r;
+ }
+
+ /* Then save the object again in the cache. */
+ assert_se(hashmap_put(m->image_cache, image->name, image) > 0);
return sd_bus_reply_method_return(message, NULL);
}
@@ -393,30 +401,17 @@ static int image_flush_cache(sd_event_source *s, void *userdata) {
return 0;
}
-static int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
- _cleanup_free_ char *e = NULL;
- Manager *m = userdata;
- Image *image = NULL;
- const char *p;
+int manager_acquire_image(Manager *m, const char *name, Image **ret) {
int r;
- assert(bus);
- assert(path);
- assert(interface);
- assert(found);
+ assert(m);
+ assert(name);
- p = startswith(path, "/org/freedesktop/machine1/image/");
- if (!p)
+ Image *existing = hashmap_get(m->image_cache, name);
+ if (existing) {
+ if (ret)
+ *ret = existing;
return 0;
-
- e = bus_label_unescape(p);
- if (!e)
- return -ENOMEM;
-
- image = hashmap_get(m->image_cache, e);
- if (image) {
- *found = image;
- return 1;
}
if (!m->image_cache_defer_event) {
@@ -433,19 +428,49 @@ static int image_object_find(sd_bus *bus, const char *path, const char *interfac
if (r < 0)
return r;
- r = image_find(IMAGE_MACHINE, e, NULL, &image);
- if (r == -ENOENT)
- return 0;
+ _cleanup_(image_unrefp) Image *image = NULL;
+ r = image_find(IMAGE_MACHINE, name, NULL, &image);
if (r < 0)
return r;
image->userdata = m;
r = hashmap_ensure_put(&m->image_cache, &image_hash_ops, image->name, image);
- if (r < 0) {
- image_unref(image);
+ if (r < 0)
+ return r;
+
+ if (ret)
+ *ret = image;
+
+ TAKE_PTR(image);
+ return 0;
+}
+
+static int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+ _cleanup_free_ char *e = NULL;
+ Manager *m = userdata;
+ Image *image;
+ const char *p;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(interface);
+ assert(found);
+
+ p = startswith(path, "/org/freedesktop/machine1/image/");
+ if (!p)
+ return 0;
+
+ e = bus_label_unescape(p);
+ if (!e)
+ return -ENOMEM;
+
+ r = manager_acquire_image(m, e, &image);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
return r;
- }
*found = image;
return 1;
diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h
index 4b00203..0c4fab1 100644
--- a/src/machine/image-dbus.h
+++ b/src/machine/image-dbus.h
@@ -2,10 +2,12 @@
#pragma once
#include "bus-object.h"
+#include "discover-image.h"
#include "machined.h"
extern const BusObjectImplementation image_object;
+int manager_acquire_image(Manager *m, const char *name, Image **ret);
char *image_bus_path(const char *name);
int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 56dd22d..1e16046 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -541,8 +541,8 @@ static int method_get_machine_uid_shift(sd_bus_message *message, void *userdata,
}
static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) {
- _cleanup_(image_unrefp) Image* i = NULL;
const char *name;
+ Image *i;
int r;
assert(message);
@@ -556,13 +556,12 @@ static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_
if (!image_name_is_valid(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
- r = image_find(IMAGE_MACHINE, name, NULL, &i);
+ r = manager_acquire_image(m, name, &i);
if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
if (r < 0)
return r;
- i->userdata = m;
return method(message, i, error);
}
diff --git a/src/run/run.c b/src/run/run.c
index 8e4b0ec..c792807 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -772,11 +772,17 @@ static int transient_service_set_properties(sd_bus_message *m, const char *pty_p
}
if (pty_path) {
+ _cleanup_close_ int pty_slave = -EBADF;
+
+ pty_slave = open_terminal(pty_path, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (pty_slave < 0)
+ return pty_slave;
+
r = sd_bus_message_append(m,
"(sv)(sv)(sv)(sv)",
- "StandardInput", "s", "tty",
- "StandardOutput", "s", "tty",
- "StandardError", "s", "tty",
+ "StandardInputFileDescriptor", "h", pty_slave,
+ "StandardOutputFileDescriptor", "h", pty_slave,
+ "StandardErrorFileDescriptor", "h", pty_slave,
"TTYPath", "s", pty_path);
if (r < 0)
return bus_log_create_error(r);
@@ -1027,7 +1033,7 @@ static void run_context_check_done(RunContext *c) {
else
done = true;
- if (c->forward && done) /* If the service is gone, it's time to drain the output */
+ if (c->forward && !pty_forward_is_done(c->forward) && done) /* If the service is gone, it's time to drain the output */
done = pty_forward_drain(c->forward);
if (done)
@@ -1095,11 +1101,18 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error
}
static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) {
- RunContext *c = userdata;
+ RunContext *c = ASSERT_PTR(userdata);
assert(f);
- if (rcode < 0) {
+ if (rcode == -ECANCELED) {
+ log_debug_errno(rcode, "PTY forwarder disconnected.");
+ if (!arg_wait)
+ return sd_event_exit(c->event, EXIT_SUCCESS);
+
+ /* If --wait is specified, we'll only exit the pty forwarding, but will continue to wait
+ * for the service to end. If the user hits ^C we'll exit too. */
+ } else if (rcode < 0) {
sd_event_exit(c->event, EXIT_FAILURE);
return log_error_errno(rcode, "Error on PTY forwarding logic: %m");
}
diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c
index 99e37fd..3be617b 100644
--- a/src/shared/blockdev-util.c
+++ b/src/shared/blockdev-util.c
@@ -410,15 +410,43 @@ int blockdev_partscan_enabled(int fd) {
* is 1, which can be check with 'ext_range' sysfs attribute. Explicit flag ('GENHD_FL_NO_PART_SCAN')
* can be obtained from 'capability' sysattr.
*
- * With https://github.com/torvalds/linux/commit/1ebe2e5f9d68e94c524aba876f27b945669a7879 (v5.17), we
- * can check the flag from 'ext_range' sysfs attribute directly.
+ * With https://github.com/torvalds/linux/commit/46e7eac647b34ed4106a8262f8bedbb90801fadd (v5.17),
+ * the flag is renamed to GENHD_FL_NO_PART.
+ *
+ * With https://github.com/torvalds/linux/commit/1ebe2e5f9d68e94c524aba876f27b945669a7879 (v5.17),
+ * we can check the flag from 'ext_range' sysfs attribute directly.
+ *
+ * With https://github.com/torvalds/linux/commit/430cc5d3ab4d0ba0bd011cfbb0035e46ba92920c (v5.17),
+ * the value of GENHD_FL_NO_PART is changed from 0x0200 to 0x0004. 💣💣💣
+ * Note, the new value was used by the GENHD_FL_MEDIA_CHANGE_NOTIFY flag, which was introduced by
+ * 86ce18d7b7925bfd6b64c061828ca2a857ee83b8 (v2.6.22), and removed by
+ * 9243c6f3e012a92dd900d97ef45efaf8a8edc448 (v5.7). If we believe the commit message of
+ * e81cd5a983bb35dabd38ee472cf3fea1c63e0f23, the flag was never used. So, fortunately, we can use
+ * both the new and old values safely.
+ *
+ * With https://github.com/torvalds/linux/commit/b9684a71fca793213378dd410cd11675d973eaa1 (v5.19),
+ * another flag GD_SUPPRESS_PART_SCAN is introduced for loopback block device, and partition scanning
+ * is done only when both GENHD_FL_NO_PART and GD_SUPPRESS_PART_SCAN are not set. Before the commit,
+ * LO_FLAGS_PARTSCAN flag was directly tied with GENHD_FL_NO_PART. But with this change now it is
+ * tied with GD_SUPPRESS_PART_SCAN. So, LO_FLAGS_PARTSCAN cannot be obtained from 'ext_range'
+ * sysattr, which corresponds to GENHD_FL_NO_PART, and we need to read 'loop/partscan'. 💣💣💣
+ *
+ * With https://github.com/torvalds/linux/commit/73a166d9749230d598320fdae3b687cdc0e2e205 (v6.3),
+ * the GD_SUPPRESS_PART_SCAN flag is also introduced for userspace block device (ublk). Though, not
+ * sure if we should support the device...
*
* With https://github.com/torvalds/linux/commit/e81cd5a983bb35dabd38ee472cf3fea1c63e0f23 (v6.3),
- * the 'capability' sysfs attribute is deprecated, hence we cannot check the flag from it.
+ * the 'capability' sysfs attribute is deprecated, hence we cannot check flags from it. 💣💣💣
+ *
+ * With https://github.com/torvalds/linux/commit/a4217c6740dc64a3eb6815868a9260825e8c68c6 (v6.10,
+ * backported to v6.9), the partscan status is directly exposed as 'partscan' sysattr.
*
- * To support both old and new kernels, we need to do the following: first check 'ext_range' sysfs
- * attribute, and if '1' we can conclude partition scanning is disabled, otherwise check 'capability'
- * sysattr for older version. */
+ * To support both old and new kernels, we need to do the following:
+ * 1) check 'partscan' sysfs attribute where the information is made directly available,
+ * 2) check 'loop/partscan' sysfs attribute for loopback block devices, and if '0' we can conclude
+ * partition scanning is disabled,
+ * 3) check 'ext_range' sysfs attribute, and if '1' we can conclude partition scanning is disabled,
+ * 4) otherwise check 'capability' sysfs attribute for ancient version. */
assert(fd >= 0);
@@ -426,6 +454,16 @@ int blockdev_partscan_enabled(int fd) {
if (r < 0)
return r;
+ /* For v6.10 or newer. */
+ r = device_get_sysattr_bool(dev, "partscan");
+ if (r != -ENOENT)
+ return r;
+
+ /* For loopback block device, especially for v5.19 or newer. Even if this is enabled, we also need to
+ * check GENHD_FL_NO_PART flag through 'ext_range' and 'capability' sysfs attributes below. */
+ if (device_get_sysattr_bool(dev, "loop/partscan") == 0)
+ return false;
+
r = device_get_sysattr_int(dev, "ext_range", &ext_range);
if (r == -ENOENT) /* If the ext_range file doesn't exist then we are most likely looking at a
* partition block device, not the whole block device. And that means we have no
@@ -445,12 +483,10 @@ int blockdev_partscan_enabled(int fd) {
if (r < 0)
return r;
-#ifndef GENHD_FL_NO_PART_SCAN
-#define GENHD_FL_NO_PART_SCAN (0x0200)
-#endif
-
- /* If 0x200 is set, part scanning is definitely off. */
- if (FLAGS_SET(capability, GENHD_FL_NO_PART_SCAN))
+#define GENHD_FL_NO_PART_OLD 0x0200
+#define GENHD_FL_NO_PART_NEW 0x0004
+ /* If one of the NO_PART flags is set, part scanning is definitely off. */
+ if ((capability & (GENHD_FL_NO_PART_OLD | GENHD_FL_NO_PART_NEW)) != 0)
return false;
/* Otherwise, assume part scanning is on, we have no further checks available. Assume the best. */
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 327dc38..55301af 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -155,7 +155,11 @@ static int next_assignment(
/* Warn about unknown non-extension fields. */
if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-"))
log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Unknown key name '%s' in section '%s', ignoring.", lvalue, section);
+ "Unknown key '%s'%s%s%s, ignoring.",
+ lvalue,
+ section ? " in section [" : "",
+ strempty(section),
+ section ? "]" : "");
return 0;
}
diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c
index 0350dd1..11729d0 100644
--- a/src/shared/discover-image.c
+++ b/src/shared/discover-image.c
@@ -202,6 +202,44 @@ static int extract_pretty(const char *path, const char *suffix, char **ret) {
return 0;
}
+static int image_update_quota(Image *i, int fd) {
+ _cleanup_close_ int fd_close = -EBADF;
+ int r;
+
+ assert(i);
+
+ if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
+ return -EROFS;
+
+ if (i->type != IMAGE_SUBVOLUME)
+ return -EOPNOTSUPP;
+
+ if (fd < 0) {
+ fd_close = open(i->path, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
+ if (fd_close < 0)
+ return -errno;
+ fd = fd_close;
+ }
+
+ r = btrfs_quota_scan_ongoing(fd);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return 0;
+
+ BtrfsQuotaInfo quota;
+ r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
+ if (r < 0)
+ return r;
+
+ i->usage = quota.referenced;
+ i->usage_exclusive = quota.exclusive;
+ i->limit = quota.referenced_max;
+ i->limit_exclusive = quota.exclusive_max;
+
+ return 1;
+}
+
static int image_make(
const char *pretty,
int dfd,
@@ -288,19 +326,7 @@ static int image_make(
if (r < 0)
return r;
- if (btrfs_quota_scan_ongoing(fd) == 0) {
- BtrfsQuotaInfo quota;
-
- r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
- if (r >= 0) {
- (*ret)->usage = quota.referenced;
- (*ret)->usage_exclusive = quota.exclusive;
-
- (*ret)->limit = quota.referenced_max;
- (*ret)->limit_exclusive = quota.exclusive_max;
- }
- }
-
+ (void) image_update_quota(*ret, fd);
return 0;
}
}
@@ -1002,6 +1028,7 @@ int image_read_only(Image *i, bool b) {
return -EOPNOTSUPP;
}
+ i->read_only = b;
return 0;
}
@@ -1100,6 +1127,8 @@ int image_path_lock(const char *path, int operation, LockFile *global, LockFile
}
int image_set_limit(Image *i, uint64_t referenced_max) {
+ int r;
+
assert(i);
if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
@@ -1115,7 +1144,12 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
(void) btrfs_qgroup_set_limit(i->path, 0, referenced_max);
(void) btrfs_subvol_auto_qgroup(i->path, 0, true);
- return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
+ r = btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
+ if (r < 0)
+ return r;
+
+ (void) image_update_quota(i, -EBADF);
+ return 0;
}
int image_read_metadata(Image *i) {
diff --git a/src/shared/journal-importer.c b/src/shared/journal-importer.c
index d9eabec..1914e74 100644
--- a/src/shared/journal-importer.c
+++ b/src/shared/journal-importer.c
@@ -92,7 +92,12 @@ static int get_line(JournalImporter *imp, char **line, size_t *size) {
imp->buf + imp->filled,
MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled);
if (n < 0) {
- if (errno != EAGAIN)
+ if (ERRNO_IS_DISCONNECT(errno)) {
+ log_debug_errno(errno, "Got disconnect for importer %s.", strna(imp->name));
+ return 0;
+ }
+
+ if (!ERRNO_IS_TRANSIENT(errno))
log_error_errno(errno, "read(%d, ..., %zu): %m",
imp->fd,
MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled);
@@ -133,7 +138,12 @@ static int fill_fixed_size(JournalImporter *imp, void **data, size_t size) {
n = read(imp->fd, imp->buf + imp->filled,
MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled);
if (n < 0) {
- if (errno != EAGAIN)
+ if (ERRNO_IS_DISCONNECT(errno)) {
+ log_debug_errno(errno, "Got disconnect for importer %s.", strna(imp->name));
+ return 0;
+ }
+
+ if (!ERRNO_IS_TRANSIENT(errno))
log_error_errno(errno, "read(%d, ..., %zu): %m", imp->fd,
MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled);
return -errno;
diff --git a/src/shared/libcrypt-util.c b/src/shared/libcrypt-util.c
index 81e6f17..5ccf75a 100644
--- a/src/shared/libcrypt-util.c
+++ b/src/shared/libcrypt-util.c
@@ -114,7 +114,7 @@ static char* systemd_crypt_ra(const char *phrase, const char *setting, void **da
if (!*data) {
*data = new0(struct crypt_data, 1);
if (!*data) {
- errno = -ENOMEM;
+ errno = ENOMEM;
return NULL;
}
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 6ffe86e..21cfe1d 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -406,6 +406,9 @@ int pty_forward_new(
struct winsize ws;
int r;
+ assert(master >= 0);
+ assert(ret);
+
f = new(PTYForward, 1);
if (!f)
return -ENOMEM;
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index 7084e70..6974ad8 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fcntl.h>
+#include <sysexits.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -85,6 +86,7 @@ TEST(tmpdir) {
static void test_shareable_ns(unsigned long nsflag) {
_cleanup_close_pair_ int s[2] = { -1, -1 };
+ bool permission_denied = false;
pid_t pid1, pid2, pid3;
int r, n = 0;
siginfo_t si;
@@ -101,8 +103,8 @@ static void test_shareable_ns(unsigned long nsflag) {
if (pid1 == 0) {
r = setup_shareable_ns(s, nsflag);
- assert_se(r >= 0);
- _exit(r);
+ assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
+ _exit(r >= 0 ? r : EX_NOPERM);
}
pid2 = fork();
@@ -110,8 +112,8 @@ static void test_shareable_ns(unsigned long nsflag) {
if (pid2 == 0) {
r = setup_shareable_ns(s, nsflag);
- assert_se(r >= 0);
- exit(r);
+ assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
+ _exit(r >= 0 ? r : EX_NOPERM);
}
pid3 = fork();
@@ -119,24 +121,38 @@ static void test_shareable_ns(unsigned long nsflag) {
if (pid3 == 0) {
r = setup_shareable_ns(s, nsflag);
- assert_se(r >= 0);
- exit(r);
+ assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
+ _exit(r >= 0 ? r : EX_NOPERM);
}
r = wait_for_terminate(pid1, &si);
assert_se(r >= 0);
assert_se(si.si_code == CLD_EXITED);
- n += si.si_status;
+ if (si.si_status == EX_NOPERM)
+ permission_denied = true;
+ else
+ n += si.si_status;
r = wait_for_terminate(pid2, &si);
assert_se(r >= 0);
assert_se(si.si_code == CLD_EXITED);
- n += si.si_status;
+ if (si.si_status == EX_NOPERM)
+ permission_denied = true;
+ else
+ n += si.si_status;
r = wait_for_terminate(pid3, &si);
assert_se(r >= 0);
assert_se(si.si_code == CLD_EXITED);
- n += si.si_status;
+ if (si.si_status == EX_NOPERM)
+ permission_denied = true;
+ else
+ n += si.si_status;
+
+ /* LSMs can cause setup_shareable_ns() to fail with permission denied, do not fail the test in that
+ * case (e.g.: LXC with AppArmor on kernel < v6.2). */
+ if (permission_denied)
+ return (void) log_tests_skipped("insufficient privileges");
assert_se(n == 1);
}
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index a186246..b44e572 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -2169,7 +2169,7 @@ static int item_do(
de_fd = openat(fd, de->d_name, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (de_fd < 0) {
- if (errno != -ENOENT)
+ if (errno != ENOENT)
q = log_error_errno(errno, "Failed to open file '%s': %m", de->d_name);
} else {
_cleanup_free_ char *de_path = NULL;
diff --git a/test/networkd-test.py b/test/networkd-test.py
index 84013e7..ebb5553 100755
--- a/test/networkd-test.py
+++ b/test/networkd-test.py
@@ -1037,13 +1037,16 @@ DNS=127.0.0.1
self.create_iface(dhcpserver_opts='EmitTimezone=yes\nTimezone=Pacific/Honolulu')
self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=false\n[DHCP]\nUseTimezone=true', dhcp_mode='ipv4')
- # should have applied the received timezone
- try:
- self.assertEqual(get_tz(), 'Pacific/Honolulu')
- except AssertionError:
+ # Should have applied the received timezone. This is asynchronous, so we need to wait for a while:
+ for _ in range(20):
+ tz = get_tz()
+ if tz == 'Pacific/Honolulu':
+ break
+ time.sleep(0.5)
+ else:
self.show_journal('systemd-networkd.service')
- self.show_journal('systemd-hostnamed.service')
- raise
+ self.show_journal('systemd-timedated.service')
+ self.fail(f'Timezone: {tz}, expected: Pacific/Honolulu')
class MatchClientTest(unittest.TestCase, NetworkdTestingUtilities):
diff --git a/test/test-functions b/test/test-functions
index 097babf..976b172 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -183,6 +183,7 @@ BASICTOOLS=(
lz4cat
mkfifo
mktemp
+ modinfo
modprobe
mount
mountpoint
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index a9286e9..d84350b 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -59,6 +59,7 @@ asan_options = None
lsan_options = None
ubsan_options = None
with_coverage = False
+show_journal = True # When true, show journal on stopping networkd.
active_units = []
protected_links = {
@@ -166,8 +167,10 @@ def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
def f(func):
- rc = call_quiet('ip rule add not from 192.168.100.19 ipproto tcp table 7')
- call_quiet('ip rule del not from 192.168.100.19 ipproto tcp table 7')
+ # IP protocol name is parsed by getprotobyname(), and it requires /etc/protocols.
+ # Hence. here we use explicit number: 6 == tcp.
+ rc = call_quiet('ip rule add not from 192.168.100.19 ipproto 6 table 7')
+ call_quiet('ip rule del not from 192.168.100.19 ipproto 6 table 7')
return func if rc == 0 else unittest.expectedFailure(func)
return f
@@ -247,6 +250,22 @@ def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable():
return f
+def expectedFailureIfKernelReturnsInvalidFlags():
+ '''
+ This checks the kernel bug caused by 3ddc2231c8108302a8229d3c5849ee792a63230d.
+ It will be fixed by the following patch:
+ https://patchwork.kernel.org/project/netdevbpf/patch/20240510072932.2678952-1-edumazet@google.com/
+ '''
+ def f(func):
+ call_quiet('ip link add dummy98 type dummy')
+ call_quiet('ip link set up dev dummy98')
+ call_quiet('ip address add 192.0.2.1/24 dev dummy98 noprefixroute')
+ output = check_output('ip address show dev dummy98')
+ remove_link('dummy98')
+ return func if 'noprefixroute' in output else unittest.expectedFailure(func)
+
+ return f
+
# pylint: disable=C0415
def compare_kernel_version(min_kernel_version):
try:
@@ -636,6 +655,8 @@ def read_networkd_log(invocation_id=None):
return check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)
def stop_networkd(show_logs=True):
+ global show_journal
+ show_logs = show_logs and show_journal
if show_logs:
invocation_id = networkd_invocation_id()
check_output('systemctl stop systemd-networkd.socket')
@@ -647,6 +668,8 @@ def start_networkd():
check_output('systemctl start systemd-networkd')
def restart_networkd(show_logs=True):
+ global show_journal
+ show_logs = show_logs and show_journal
if show_logs:
invocation_id = networkd_invocation_id()
check_output('systemctl restart systemd-networkd.service')
@@ -1319,6 +1342,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'macvtap mode ' + mode + ' ')
+ @expectedFailureIfModuleIsNotAvailable('macvlan')
def test_macvlan(self):
first = True
for mode in ['private', 'vepa', 'bridge', 'passthru']:
@@ -2610,12 +2634,12 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('ip rule')
print(output)
- self.assertRegex(output, '111')
- self.assertRegex(output, 'from 192.168.100.18')
- self.assertRegex(output, '1123-1150')
- self.assertRegex(output, '3224-3290')
- self.assertRegex(output, 'tcp')
- self.assertRegex(output, 'lookup 7')
+ self.assertIn('111:', output)
+ self.assertIn('from 192.168.100.18 ', output)
+ self.assertIn('sport 1123-1150 ', output)
+ self.assertIn('dport 3224-3290 ', output)
+ self.assertRegex(output, 'ipproto (tcp|ipproto-6) ')
+ self.assertIn('lookup 7 ', output)
@expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
def test_routing_policy_rule_invert(self):
@@ -2625,10 +2649,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('ip rule')
print(output)
- self.assertRegex(output, '111')
- self.assertRegex(output, 'not.*?from.*?192.168.100.18')
- self.assertRegex(output, 'tcp')
- self.assertRegex(output, 'lookup 7')
+ self.assertIn('111:', output)
+ self.assertIn('not ', output)
+ self.assertIn('from 192.168.100.18 ', output)
+ self.assertRegex(output, 'ipproto (tcp|ipproto-6) ')
+ self.assertIn('lookup 7 ', output)
@expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
def test_routing_policy_rule_uidrange(self):
@@ -2638,10 +2663,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('ip rule')
print(output)
- self.assertRegex(output, '111')
- self.assertRegex(output, 'from 192.168.100.18')
- self.assertRegex(output, 'lookup 7')
- self.assertRegex(output, 'uidrange 100-200')
+ self.assertIn('111:', output)
+ self.assertIn('from 192.168.100.18 ', output)
+ self.assertIn('lookup 7 ', output)
+ self.assertIn('uidrange 100-200 ', output)
def _test_route_static(self, manage_foreign_routes):
if not manage_foreign_routes:
@@ -4572,6 +4597,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
self.assertIn('DHCPREPLY(veth-peer)', output)
self.assertNotIn('rapid-commit', output)
+ @expectedFailureIfKernelReturnsInvalidFlags()
def test_dhcp_client_ipv4_only(self):
copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')
@@ -5658,6 +5684,7 @@ if __name__ == '__main__':
parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
parser.add_argument('--with-coverage', help='Loosen certain sandbox restrictions to make gcov happy', dest='with_coverage', type=bool, nargs='?', const=True, default=with_coverage)
+ parser.add_argument('--no-journal', help='Do not show journal of systemd-networkd on stop', dest='show_journal', action='store_false')
ns, unknown_args = parser.parse_known_args(namespace=unittest)
if ns.build_dir:
@@ -5707,6 +5734,7 @@ if __name__ == '__main__':
lsan_options = ns.lsan_options
ubsan_options = ns.ubsan_options
with_coverage = ns.with_coverage
+ show_journal = ns.show_journal
if use_valgrind:
# Do not forget the trailing space.
diff --git a/test/test-rpm-macros.sh b/test/test-rpm-macros.sh
index c7107de..c9a45dc 100755
--- a/test/test-rpm-macros.sh
+++ b/test/test-rpm-macros.sh
@@ -137,7 +137,7 @@ for i in sysusers tmpfiles; do
PKG_DATA_FILE="$(mktemp "$WORK_DIR/pkg-data-XXX")"
EXP_OUT="$(mktemp "$WORK_DIR/exp-out-XXX.log")"
- CONF_DIR="$(pkg-config --variable="${i}dir" systemd)"
+ CONF_DIR="$(PKG_CONFIG_PATH="${BUILD_DIR}/src/core" pkg-config --variable="${i}dir" systemd)"
EXTRA_ARGS=()
if [[ "$i" == tmpfiles ]]; then
diff --git a/test/units/testsuite-38.sh b/test/units/testsuite-38.sh
index c5f9bcc..35c4f1c 100755
--- a/test/units/testsuite-38.sh
+++ b/test/units/testsuite-38.sh
@@ -91,7 +91,7 @@ check_freezer_state() {
# Ignore the intermediate freezing & thawing states in case we check
# the unit state too quickly
- [[ "$state" =~ ^(freezing|thawing)$ ]] || break
+ [[ "$state" =~ ^(freezing|thawing) ]] || break
sleep .5
done
diff --git a/test/units/testsuite-46.sh b/test/units/testsuite-46.sh
index ec80b71..e41ca4c 100755
--- a/test/units/testsuite-46.sh
+++ b/test/units/testsuite-46.sh
@@ -20,7 +20,7 @@ inspect() {
userdbctl user "$USERNAME" | tee /tmp/b
# diff uses the grep BREs for pattern matching
- diff -I '^\s*Disk \(Size\|Free\|Floor\|Ceiling\):' /tmp/{a,b}
+ diff -I '^\s*Disk \(Size\|Free\|Floor\|Ceiling\|Usage\):' /tmp/{a,b}
rm /tmp/{a,b}
homectl inspect --json=pretty "$USERNAME"
diff --git a/test/units/testsuite-58.sh b/test/units/testsuite-58.sh
index e369e58..5b72a49 100755
--- a/test/units/testsuite-58.sh
+++ b/test/units/testsuite-58.sh
@@ -283,7 +283,7 @@ $imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79
$imgs/zzz7 : start= 6291416, size= 98304, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\""
loop="$(losetup -P --show --find "$imgs/zzz")"
- udevadm wait --timeout 60 --settle "${loop:?}"
+ udevadm wait --timeout 60 --settle "${loop:?}p7"
volume="test-repart-$RANDOM"
diff --git a/test/units/testsuite-64.sh b/test/units/testsuite-64.sh
index e9f352c..f0cfce3 100755
--- a/test/units/testsuite-64.sh
+++ b/test/units/testsuite-64.sh
@@ -577,9 +577,10 @@ EOF
for ((i = 0; i < ${#devices[@]}; i++)); do
# Intentionally use weaker cipher-related settings, since we don't care
# about security here as it's a throwaway LUKS partition
- cryptsetup luksFormat -q \
- --use-urandom --pbkdf pbkdf2 --pbkdf-force-iterations 1000 \
- --uuid "deadbeef-dead-dead-beef-11111111111$i" --label "encdisk$i" "${devices[$i]}" /etc/btrfs_keyfile
+ udevadm lock --device="${devices[$i]}" \
+ cryptsetup luksFormat -q \
+ --use-urandom --pbkdf pbkdf2 --pbkdf-force-iterations 1000 \
+ --uuid "deadbeef-dead-dead-beef-11111111111$i" --label "encdisk$i" "${devices[$i]}" /etc/btrfs_keyfile
udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/deadbeef-dead-dead-beef-11111111111$i" "/dev/disk/by-label/encdisk$i"
# Add the device into /etc/crypttab, reload systemd, and then activate
# the device so we can create a filesystem on it later
diff --git a/tmpfiles.d/systemd.conf.in b/tmpfiles.d/systemd.conf.in
index 74f35cc..01cd7d8 100644
--- a/tmpfiles.d/systemd.conf.in
+++ b/tmpfiles.d/systemd.conf.in
@@ -26,13 +26,16 @@ Z /run/log/journal/%m ~2750 root systemd-journal - -
{% if HAVE_ACL %}
{% if ENABLE_ADM_GROUP and ENABLE_WHEEL_GROUP %}
a+ /run/log/journal - - - - d:group::r-x,d:group:adm:r-x,d:group:wheel:r-x,group::r-x,group:adm:r-x,group:wheel:r-x
-A+ /run/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x,group:adm:r-X,group:wheel:r-X
+a+ /run/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x,group:adm:r-x,group:wheel:r-x
+a+ /run/log/journal/%m/*.journal* - - - - group:adm:r--,group:wheel:r--
{% elif ENABLE_ADM_GROUP %}
a+ /run/log/journal - - - - d:group::r-x,d:group:adm:r-x,group::r-x,group:adm:r-x
-A+ /run/log/journal/%m - - - - d:group:adm:r-x,group:adm:r-X
+a+ /run/log/journal/%m - - - - d:group:adm:r-x,group:adm:r-x
+a+ /run/log/journal/%m/*.journal* - - - - group:adm:r--
{% elif ENABLE_WHEEL_GROUP %}
a+ /run/log/journal - - - - d:group::r-x,d:group:wheel:r-x,group::r-x,group:wheel:r-x
-A+ /run/log/journal/%m - - - - d:group:wheel:r-x,group:wheel:r-X
+a+ /run/log/journal/%m - - - - d:group:wheel:r-x,group:wheel:r-x
+a+ /run/log/journal/%m/*.journal* - - - - group:wheel:r--
{% endif %}
{% endif %}