diff --git a/man/homectl.xml b/man/homectl.xml
index dacbd17b1..6fd534037 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -686,7 +686,7 @@
CIPHERMODE
- BITS
+ BYTESTYPEALGORITHMSECONDS
@@ -696,7 +696,12 @@
Configures various cryptographic parameters for the LUKS2 storage mechanism. See
cryptsetup8
- for details on the specific attributes.
+ for details on the specific attributes.
+
+ Note that homectl uses bytes for key size, like
+ /proc/crypto, but cryptsetup8
+ uses bits.
diff --git a/man/loader.conf.xml b/man/loader.conf.xml
index d5abb1c04..509412ec9 100644
--- a/man/loader.conf.xml
+++ b/man/loader.conf.xml
@@ -121,7 +121,7 @@
will be stored as an EFI variable in that case, overriding this option.
- If set to menu-hidden or 0 no menu
+ If set to menu-hidden or 0 (the default) no menu
is shown and the default entry will be booted immediately. The menu can be shown
by pressing and holding a key before systemd-boot is launched. Setting this to
menu-force disables the timeout while always showing the menu.
@@ -211,7 +211,7 @@
beep
- Beep n times when the n-th entry in the boot menu is shown (default disabled).
+ Takes a boolean argument. If timeout enabled beep every second, otherwise beep n times when n-th entry in boot menu is selected (default disabled).
Currently, only x86 is supported, where it uses the PC speaker.
diff --git a/man/sd_bus_error-example.c b/man/sd_bus_error-example.c
new file mode 100644
index 000000000..abea13ca4
--- /dev/null
+++ b/man/sd_bus_error-example.c
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+
+#include
+#include
+#include
+#include
+
+int writer_with_negative_errno_return(int fd, sd_bus_error *error) {
+ const char *message = "Hello, World!\n";
+
+ ssize_t n = write(fd, message, strlen(message));
+ if (n >= 0)
+ return n; /* On success, return the number of bytes written, possibly 0. */
+
+ /* On error, initialize the error structure, and also propagate the errno
+ * value that write(2) set for us. */
+ return sd_bus_error_set_errnof(error, errno, "Failed to write to fd %i: %m", fd);
+}
diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml
index 5697ce732..f4d0fea2e 100644
--- a/man/sd_bus_error.xml
+++ b/man/sd_bus_error.xml
@@ -246,10 +246,15 @@
values in e, if e has been set with an error value before.
Otherwise, it will return immediately. If the strings in e were set using
sd_bus_error_set_const(), they will be shared. Otherwise, they will be
- copied. Returns a converted errno-like, negative error code or 0.
- Before this call, dst must be unset, i.e. either freshly initialized with
+ copied. Before this call, dst must be unset, i.e. either freshly initialized with
NULL or reset using sd_bus_error_free().
+ sd_bus_error_copy() generally returns 0 or a negative
+ errno-like value based on the input parameter e:
+ 0 if it was unset and a negative integer if it was set to some error, similarly to
+ sd_bus_error_set(). It may however also return an error generated internally, for
+ example -ENOMEM if a memory allocation fails.
+
sd_bus_error_move() is similar to sd_bus_error_copy(),
but will move any error information from e into dst,
resetting the former. This function cannot fail, as no new memory is allocated. Note that if
@@ -286,6 +291,18 @@
to NULL. The structure may be reused afterwards.
+
+ Reference ownership
+
+ sd_bus_error is not reference-counted. Users should destroy resources held
+ by it by calling sd_bus_error_free(). Usually, error structures are allocated on the
+ stack or passed in as function parameters, but they may also be allocated dynamically, in which case it
+ is the duty of the caller to free3 the memory
+ held by the structure itself after freeing its contents with
+ sd_bus_error_free().
+
+
Return Value
@@ -297,7 +314,8 @@
sd_bus_error_set_errnofv(), return 0 when the specified error
value is 0, and a negative errno-like value corresponding to the
error parameter otherwise. If an error occurs internally, one of the negative
- error values listed below will be returned.
+ error values listed below will be returned. This allows those functions to be conveniently used in a
+ return statement, see the example below.
sd_bus_error_get_errno() returns
false when e is
@@ -305,7 +323,9 @@
e->name otherwise.sd_bus_error_copy() and sd_bus_error_move() return a
- negative error value converted from the source error, and zero if the error has not been set.
+ negative error value converted from the source error, and zero if the error has not been set. This
+ allows those functions to be conveniently used in a return statement, see the
+ example below.
sd_bus_error_is_set() returns a
non-zero value when e and the
@@ -316,32 +336,18 @@
sd_bus_error_has_names_sentinel() return a non-zero value when e is
non-NULL and the name field is equal to one of the given
names, zero otherwise.
-
-
-
- Reference ownership
- sd_bus_error is not reference
- counted. Users should destroy resources held by it by calling
- sd_bus_error_free(). Usually, error structures
- are allocated on the stack or passed in as function parameters,
- but they may also be allocated dynamically, in which case it is
- the duty of the caller to free3
- the memory held by the structure itself after freeing its contents
- with sd_bus_error_free().Errors
- Returned errors may indicate the following problems:
+ Return value may indicate the following problems in the invocation of the function itself:
-
-EINVAL
- Error was already set in sd_bus_error structure when one
- the error-setting functions was called.
+ Error was already set in the sd_bus_error structure when
+ one the error-setting functions was called.
@@ -350,9 +356,29 @@
Memory allocation failed.
+
+ On success, sd_bus_error_set(), sd_bus_error_setf(),
+ sd_bus_error_set_const(), sd_bus_error_set_errno(),
+ sd_bus_error_set_errnof(), sd_bus_error_set_errnofv(),
+ sd_bus_error_copy(), and sd_bus_error_move() will return a
+ negative converted errno-style value, or 0 if the error
+ parameter is NULL or unset. D-Bus errors are converted to the integral
+ errno-style value, and the mapping mechanism is extensible, see the discussion
+ above. This effectively means that almost any negative errno-style value can be
+ returned.
+
+ Examples
+
+
+ Using the negative return value to propagate an error
+
+
+
+
+
diff --git a/man/shutdown.xml b/man/shutdown.xml
index b07736ee6..97f33e802 100644
--- a/man/shutdown.xml
+++ b/man/shutdown.xml
@@ -18,7 +18,7 @@
shutdown
- Halt, power-off or reboot the machine
+ Halt, power off or reboot the machine
@@ -33,8 +33,7 @@
Description
- shutdown may be used to halt, power-off
- or reboot the machine.
+ shutdown may be used to halt, power off, or reboot the machine.The first argument may be a time string (which is usually
now). Optionally, this may be followed by a
@@ -81,47 +80,41 @@
- Power-off the machine (the
- default).
+ Power the machine off (the default).
- Reboot the
- machine.
+ Reboot the machine.
- Equivalent to ,
- unless is specified.
+ The same as , but does not override the action to take if
+ it is "halt". E.g. shutdown --reboot -h means "poweroff", but shutdown
+ --halt -h means "halt".
- Do not halt, power-off, reboot, just write
- wall message.
+ Do not halt, power off, or reboot, but just write the wall message.
- Do not send wall
- message before
- halt, power-off, reboot.
+ Do not send wall message before halt, power off, or reboot.
- Cancel a pending shutdown. This may be used
- to cancel the effect of an invocation of
- shutdown with a time argument that is not
- +0 or
+ Cancel a pending shutdown. This may be used to cancel the effect of an invocation of
+ shutdown with a time argument that is not +0 or
now.
diff --git a/man/systemd-creds.xml b/man/systemd-creds.xml
index 2ccbb223e..d803b5c12 100644
--- a/man/systemd-creds.xml
+++ b/man/systemd-creds.xml
@@ -25,6 +25,8 @@
systemd-credsOPTIONS
+ COMMAND
+ ARGS
diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml
index da35a7d26..c7c8b91e1 100644
--- a/man/systemd.automount.xml
+++ b/man/systemd.automount.xml
@@ -26,10 +26,9 @@
Description
- A unit configuration file whose name ends in
- .automount encodes information about a file
- system automount point controlled and supervised by
- systemd.
+ A unit configuration file whose name ends in .automount encodes information
+ about a file system automount point controlled and supervised by systemd. Automount units may be used to
+ implement on-demand mounting as well as parallelized mounting of file systems.This man page lists the configuration options specific to
this unit type. See
@@ -55,9 +54,6 @@
accesses /home/lennart the mount unit
home-lennart.mount will be activated.
- Automount units may be used to implement on-demand mounting
- as well as parallelized mounting of file systems.
-
Note that automount units are separate from the mount itself, so you
should not set After= or Requires=
for mount dependencies here. For example, you should not set
@@ -65,8 +61,11 @@
filesystems. Doing so may result in an ordering cycle.Note that automount support on Linux is privileged, automount units are hence only available in the
- system service manager (and root's user service manager), but not in unprivileged user's service
- manager.
+ system service manager (and root's user service manager), but not in unprivileged users' service
+ managers.
+
+ Note that automount units should not be nested. (The establishment of the inner automount point
+ would unconditionally pin the outer mount point, defeating its purpose.)
@@ -78,12 +77,12 @@
The following dependencies are implicitly added:
- If an automount unit is beneath another mount unit in the
- file system hierarchy, both a requirement and an ordering
- dependency between both units are created automatically.
+ If an automount unit is beneath another mount unit in the file system hierarchy, a
+ requirement and ordering dependencies are created to the on the unit higher in the hierarchy.
+
- An implicit Before= dependency is created
- between an automount unit and the mount unit it activates.
+ An implicit Before= dependency is created between an automount
+ unit and the mount unit it activates.
@@ -161,6 +160,7 @@
creating these directories. Takes an access mode in octal
notation. Defaults to 0755.
+
TimeoutIdleSec=Configures an idle timeout. Once the mount has been
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 95bf177a6..b03cc70e2 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -357,20 +357,29 @@ int cg_kill(
Set *s,
cg_kill_log_func_t log_kill,
void *userdata) {
- int r;
+
+ int r, ret;
r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.procs");
if (r < 0 || sig != SIGKILL)
return r;
+ ret = r;
+
/* Only in case of killing with SIGKILL and when using cgroupsv2, kill remaining threads manually as
a workaround for kernel bug. It was fixed in 5.2-rc5 (c03cd7738a83), backported to 4.19.66
(4340d175b898) and 4.14.138 (feb6b123b7dd). */
r = cg_unified_controller(controller);
- if (r <= 0)
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return ret;
+
+ r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads");
+ if (r < 0)
return r;
- return cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads");
+ return r > 0 || ret > 0;
}
int cg_kill_kernel_sigkill(const char *controller, const char *path) {
diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c
index 258d09dd4..ce3b76c51 100644
--- a/src/core/bpf-firewall.c
+++ b/src/core/bpf-firewall.c
@@ -543,7 +543,7 @@ int bpf_firewall_compile(Unit *u) {
return supported;
if (supported == BPF_FIREWALL_UNSUPPORTED)
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
- "BPF firewalling not supported on this manager, proceeding without.");
+ "bpf-firewall: BPF firewalling not supported, proceeding without.");
if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE)
/* If BPF_F_ALLOW_MULTI is not supported we don't support any BPF magic on inner nodes (i.e. on slice
* units), since that would mean leaf nodes couldn't do any BPF anymore at all. Under the assumption
@@ -551,7 +551,7 @@ int bpf_firewall_compile(Unit *u) {
* consistent with old systemd behaviour from before v238, where BPF wasn't supported in inner nodes at
* all, either. */
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
- "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units.");
+ "bpf-firewall: BPF_F_ALLOW_MULTI is not supported, not doing BPF firewall on slice units.");
/* If BPF_F_ALLOW_MULTI flag is supported program name is also supported (both were added to v4.15
* kernel). */
@@ -582,24 +582,24 @@ int bpf_firewall_compile(Unit *u) {
r = bpf_firewall_prepare_access_maps(u, ACCESS_ALLOWED, &u->ipv4_allow_map_fd, &u->ipv6_allow_map_fd, &ip_allow_any);
if (r < 0)
- return log_unit_error_errno(u, r, "Preparation of eBPF allow maps failed: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF allow maps failed: %m");
r = bpf_firewall_prepare_access_maps(u, ACCESS_DENIED, &u->ipv4_deny_map_fd, &u->ipv6_deny_map_fd, &ip_deny_any);
if (r < 0)
- return log_unit_error_errno(u, r, "Preparation of eBPF deny maps failed: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF deny maps failed: %m");
}
r = bpf_firewall_prepare_accounting_maps(u, cc->ip_accounting, &u->ip_accounting_ingress_map_fd, &u->ip_accounting_egress_map_fd);
if (r < 0)
- return log_unit_error_errno(u, r, "Preparation of eBPF accounting maps failed: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF accounting maps failed: %m");
r = bpf_firewall_compile_bpf(u, ingress_name, true, &u->ip_bpf_ingress, ip_allow_any, ip_deny_any);
if (r < 0)
- return log_unit_error_errno(u, r, "Compilation for ingress BPF program failed: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Compilation of ingress BPF program failed: %m");
r = bpf_firewall_compile_bpf(u, egress_name, false, &u->ip_bpf_egress, ip_allow_any, ip_deny_any);
if (r < 0)
- return log_unit_error_errno(u, r, "Compilation for egress BPF program failed: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Compilation of egress BPF program failed: %m");
return 0;
}
@@ -613,15 +613,15 @@ static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set
r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &prog);
if (r < 0)
- return log_unit_error_errno(u, r, "Can't allocate CGROUP SKB BPF program: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Allocation of SKB BPF program failed: %m");
r = bpf_program_load_from_bpf_fs(prog, *bpf_fs_path);
if (r < 0)
- return log_unit_error_errno(u, r, "Loading of ingress BPF program %s failed: %m", *bpf_fs_path);
+ return log_unit_error_errno(u, r, "bpf-firewall: Loading of ingress BPF program %s failed: %m", *bpf_fs_path);
r = set_ensure_consume(set, &bpf_program_hash_ops, TAKE_PTR(prog));
if (r < 0)
- return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m");
+ return log_oom();
}
return 0;
@@ -645,7 +645,8 @@ int bpf_firewall_load_custom(Unit *u) {
return supported;
if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI)
- return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs.");
+ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "bpf-firewall: BPF_F_ALLOW_MULTI not supported, cannot attach custom BPF programs.");
r = load_bpf_progs_from_fs_to_set(u, cc->ip_filters_ingress, &u->ip_bpf_custom_ingress);
if (r < 0)
@@ -671,7 +672,7 @@ static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, S
SET_FOREACH_MOVE(prog, *set_installed, *set) {
r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI);
if (r < 0)
- return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path);
+ return log_unit_error_errno(u, r, "bpf-firewall: Attaching custom egress BPF program to cgroup %s failed: %m", path);
}
return 0;
}
@@ -697,16 +698,19 @@ int bpf_firewall_install(Unit *u) {
if (supported < 0)
return supported;
if (supported == BPF_FIREWALL_UNSUPPORTED)
- return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF firewalling not supported on this manager, proceeding without.");
+ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "bpf-firewall: BPF firewalling not supported, proceeding without.");
if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE)
- return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units.");
+ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "bpf-firewall: BPF_F_ALLOW_MULTI not supported, not doing BPF firewall on slice units.");
if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI &&
(!set_isempty(u->ip_bpf_custom_ingress) || !set_isempty(u->ip_bpf_custom_egress)))
- return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs.");
+ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "bpf-firewall: BPF_F_ALLOW_MULTI not supported, cannot attach custom BPF programs.");
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &path);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m");
+ return log_unit_error_errno(u, r, "bpf-firewall: Failed to determine cgroup path: %m");
flags = supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI ? BPF_F_ALLOW_MULTI : 0;
@@ -728,7 +732,8 @@ int bpf_firewall_install(Unit *u) {
if (u->ip_bpf_egress) {
r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags);
if (r < 0)
- return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path);
+ return log_unit_error_errno(u, r,
+ "bpf-firewall: Attaching egress BPF program to cgroup %s failed: %m", path);
/* Remember that this BPF program is installed now. */
u->ip_bpf_egress_installed = TAKE_PTR(u->ip_bpf_egress);
@@ -737,7 +742,8 @@ int bpf_firewall_install(Unit *u) {
if (u->ip_bpf_ingress) {
r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags);
if (r < 0)
- return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path);
+ return log_unit_error_errno(u, r,
+ "bpf-firewall: Attaching ingress BPF program to cgroup %s failed: %m", path);
u->ip_bpf_ingress_installed = TAKE_PTR(u->ip_bpf_ingress);
}
@@ -824,11 +830,11 @@ int bpf_firewall_supported(void) {
r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
- return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m");
+ return log_error_errno(r, "bpf-firewall: Can't determine whether the unified hierarchy is used: %m");
if (r == 0) {
bpf_firewall_unsupported_reason =
log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
- "Not running with unified cgroups, BPF firewalling is not supported.");
+ "bpf-firewall: Not running with unified cgroup hierarchy, BPF firewalling is not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@@ -836,21 +842,21 @@ int bpf_firewall_supported(void) {
r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &program);
if (r < 0) {
bpf_firewall_unsupported_reason =
- log_debug_errno(r, "Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m");
+ log_debug_errno(r, "bpf-firewall: Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
r = bpf_program_add_instructions(program, trivial, ELEMENTSOF(trivial));
if (r < 0) {
bpf_firewall_unsupported_reason =
- log_debug_errno(r, "Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m");
+ log_debug_errno(r, "bpf-firewall: Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
r = bpf_program_load_kernel(program, NULL, 0);
if (r < 0) {
bpf_firewall_unsupported_reason =
- log_debug_errno(r, "Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m");
+ log_debug_errno(r, "bpf-firewall: Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@@ -874,7 +880,7 @@ int bpf_firewall_supported(void) {
if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) {
if (errno != EBADF) {
bpf_firewall_unsupported_reason =
- log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m");
+ log_debug_errno(errno, "bpf-firewall: Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@@ -882,7 +888,7 @@ int bpf_firewall_supported(void) {
} else {
bpf_firewall_unsupported_reason =
log_debug_errno(SYNTHETIC_ERRNO(EBADE),
- "Wut? Kernel accepted our invalid BPF_PROG_DETACH call? "
+ "bpf-firewall: Wut? Kernel accepted our invalid BPF_PROG_DETACH call? "
"Something is weird, assuming BPF firewalling is broken and hence not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@@ -902,20 +908,20 @@ int bpf_firewall_supported(void) {
if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) {
if (errno == EBADF) {
- log_debug_errno(errno, "Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!");
+ log_debug_errno(errno, "bpf-firewall: Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!");
return supported = BPF_FIREWALL_SUPPORTED_WITH_MULTI;
}
if (errno == EINVAL)
- log_debug_errno(errno, "Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported.");
+ log_debug_errno(errno, "bpf-firewall: Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported.");
else
- log_debug_errno(errno, "Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m");
+ log_debug_errno(errno, "bpf-firewall: Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m");
return supported = BPF_FIREWALL_SUPPORTED;
} else {
bpf_firewall_unsupported_reason =
log_debug_errno(SYNTHETIC_ERRNO(EBADE),
- "Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? "
+ "bpf-firewall: Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? "
"Something is weird, assuming BPF firewalling is broken and hence not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c
index 7f50f5738..83c3bac87 100644
--- a/src/core/bpf-foreign.c
+++ b/src/core/bpf-foreign.c
@@ -63,7 +63,7 @@ static int attach_programs(Unit *u, const char *path, Hashmap* foreign_by_key, u
HASHMAP_FOREACH_KEY(prog, key, foreign_by_key) {
r = bpf_program_cgroup_attach(prog, key->attach_type, path, attach_flags);
if (r < 0)
- return log_unit_error_errno(u, r, "Attaching foreign BPF program to cgroup %s failed: %m", path);
+ return log_unit_error_errno(u, r, "bpf-foreign: Attaching foreign BPF program to cgroup %s failed: %m", path);
}
return 0;
@@ -89,31 +89,31 @@ static int bpf_foreign_prepare(
r = path_is_fs_type(bpffs_path, BPF_FS_MAGIC);
if (r < 0)
return log_unit_error_errno(u, r,
- "Failed to determine filesystem type of %s: %m", bpffs_path);
+ "bpf-foreign: Failed to determine filesystem type of %s: %m", bpffs_path);
if (r == 0)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
- "Path in BPF filesystem is expected.");
+ "bpf-foreign: Path in BPF filesystem is expected.");
r = bpf_program_new_from_bpffs_path(bpffs_path, &prog);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to create foreign BPFProgram: %m");
+ return log_unit_error_errno(u, r, "bpf-foreign: Failed to create foreign BPF program: %m");
r = bpf_program_get_id_by_fd(prog->kernel_fd, &prog_id);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to get BPF program id by fd: %m");
+ return log_unit_error_errno(u, r, "bpf-foreign: Failed to get BPF program id from fd: %m");
r = bpf_foreign_key_new(prog_id, attach_type, &key);
if (r < 0)
return log_unit_error_errno(u, r,
- "Failed to create foreign BPF program key from path '%s': %m", bpffs_path);
+ "bpf-foreign: Failed to create foreign BPF program key from path '%s': %m", bpffs_path);
r = hashmap_ensure_put(&u->bpf_foreign_by_key, &bpf_foreign_by_key_hash_ops, key, prog);
if (r == -EEXIST) {
- log_unit_warning_errno(u, r, "Foreign BPF program already exists, ignoring: %m");
+ log_unit_warning_errno(u, r, "bpf-foreign: Foreign BPF program already exists, ignoring: %m");
return 0;
}
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to put foreign BPFProgram into map: %m");
+ return log_unit_error_errno(u, r, "bpf-foreign: Failed to put foreign BPF program into map: %m");
TAKE_PTR(key);
TAKE_PTR(prog);
@@ -134,17 +134,17 @@ int bpf_foreign_install(Unit *u) {
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to get cgroup path: %m");
+ return log_unit_error_errno(u, r, "bpf-foreign: Failed to get cgroup path: %m");
LIST_FOREACH(programs, p, cc->bpf_foreign_programs) {
r = bpf_foreign_prepare(u, p->attach_type, p->bpffs_path);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to prepare foreign BPF hashmap: %m");
+ return log_unit_error_errno(u, r, "bpf-foreign: Failed to prepare foreign BPF hashmap: %m");
}
r = attach_programs(u, cgroup_path, u->bpf_foreign_by_key, BPF_F_ALLOW_MULTI);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to install foreign BPF programs: %m");
+ return log_unit_error_errno(u, r, "bpf-foreign: Failed to install foreign BPF programs: %m");
return 0;
}
diff --git a/src/core/bpf-lsm.c b/src/core/bpf-lsm.c
index d3e92b98a..f3b933955 100644
--- a/src/core/bpf-lsm.c
+++ b/src/core/bpf-lsm.c
@@ -26,6 +26,7 @@
/* libbpf, clang and llc compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
+#include "bpf-util.h"
#include "bpf/restrict_fs/restrict-fs-skel.h"
#define CGROUP_HASH_SIZE_MAX 2048
@@ -61,29 +62,29 @@ static int prepare_restrict_fs_bpf(struct restrict_fs_bpf **ret_obj) {
obj = restrict_fs_bpf__open();
if (!obj)
- return log_error_errno(errno, "Failed to open BPF object: %m");
+ return log_error_errno(errno, "bpf-lsm: Failed to open BPF object: %m");
/* TODO Maybe choose a number based on runtime information? */
r = sym_bpf_map__resize(obj->maps.cgroup_hash, CGROUP_HASH_SIZE_MAX);
assert(r <= 0);
if (r < 0)
- return log_error_errno(r, "Failed to resize BPF map '%s': %m",
+ return log_error_errno(r, "bpf-lsm: Failed to resize BPF map '%s': %m",
sym_bpf_map__name(obj->maps.cgroup_hash));
/* Dummy map to satisfy the verifier */
inner_map_fd = sym_bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint32_t), 128, 0);
if (inner_map_fd < 0)
- return log_error_errno(errno, "Failed to create BPF map: %m");
+ return log_error_errno(errno, "bpf-lsm: Failed to create BPF map: %m");
r = sym_bpf_map__set_inner_map_fd(obj->maps.cgroup_hash, inner_map_fd);
assert(r <= 0);
if (r < 0)
- return log_error_errno(r, "Failed to set inner map fd: %m");
+ return log_error_errno(r, "bpf-lsm: Failed to set inner map fd: %m");
r = restrict_fs_bpf__load(obj);
assert(r <= 0);
if (r < 0)
- return log_error_errno(r, "Failed to load BPF object");
+ return log_error_errno(r, "bpf-lsm: Failed to load BPF object: %m");
*ret_obj = TAKE_PTR(obj);
@@ -103,7 +104,7 @@ static int mac_bpf_use(void) {
r = read_one_line_file("/sys/kernel/security/lsm", &lsm_list);
if (r < 0) {
if (r != -ENOENT)
- log_notice_errno(r, "Failed to read /sys/kernel/security/lsm, assuming bpf is unavailable: %m");
+ log_notice_errno(r, "bpf-lsm: Failed to read /sys/kernel/security/lsm, assuming bpf is unavailable: %m");
return 0;
}
@@ -116,7 +117,7 @@ static int mac_bpf_use(void) {
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_notice_errno(r, "Failed to parse /sys/kernel/security/lsm, assuming bpf is unavailable: %m");
+ log_notice_errno(r, "bpf-lsm: Failed to parse /sys/kernel/security/lsm, assuming bpf is unavailable: %m");
return 0;
}
@@ -135,33 +136,18 @@ bool lsm_bpf_supported(bool initialize) {
if (!initialize)
return false;
- r = dlopen_bpf();
- if (r < 0) {
- log_info_errno(r, "Failed to open libbpf, LSM BPF is not supported: %m");
+ if (!cgroup_bpf_supported())
return (supported = false);
- }
-
- r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
- if (r < 0) {
- log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m");
- return (supported = false);
- }
-
- if (r == 0) {
- log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Not running with unified cgroup hierarchy, LSM BPF is not supported");
- return (supported = false);
- }
r = mac_bpf_use();
if (r < 0) {
- log_warning_errno(r, "Can't determine whether the BPF LSM module is used: %m");
+ log_warning_errno(r, "bpf-lsm: Can't determine whether the BPF LSM module is used: %m");
return (supported = false);
}
if (r == 0) {
log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "BPF LSM hook not enabled in the kernel, LSM BPF not supported");
+ "bpf-lsm: BPF LSM hook not enabled in the kernel, BPF LSM not supported");
return (supported = false);
}
@@ -171,7 +157,7 @@ bool lsm_bpf_supported(bool initialize) {
if (!bpf_can_link_lsm_program(obj->progs.restrict_filesystems)) {
log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Failed to link BPF program. Assuming BPF is not available");
+ "bpf-lsm: Failed to link program; assuming BPF LSM is not available");
return (supported = false);
}
@@ -192,10 +178,10 @@ int lsm_bpf_setup(Manager *m) {
link = sym_bpf_program__attach_lsm(obj->progs.restrict_filesystems);
r = sym_libbpf_get_error(link);
if (r != 0)
- return log_error_errno(r, "Failed to link '%s' LSM BPF program: %m",
+ return log_error_errno(r, "bpf-lsm: Failed to link '%s' LSM BPF program: %m",
sym_bpf_program__name(obj->progs.restrict_filesystems));
- log_info("LSM BPF program attached");
+ log_info("bpf-lsm: LSM BPF program attached");
obj->links.restrict_filesystems = TAKE_PTR(link);
m->restrict_fs = TAKE_PTR(obj);
@@ -214,7 +200,7 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo
if (!u->manager->restrict_fs)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
- "Restrict filesystems BPF object is not set, BPF LSM setup has failed?");
+ "bpf-lsm: BPF LSM object is not installed, has setup failed?");
int inner_map_fd = sym_bpf_create_map(
BPF_MAP_TYPE_HASH,
@@ -223,39 +209,39 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo
128, /* Should be enough for all filesystem types */
0);
if (inner_map_fd < 0)
- return log_unit_error_errno(u, errno, "Failed to create inner LSM map: %m");
+ return log_unit_error_errno(u, errno, "bpf-lsm: Failed to create inner BPF map: %m");
int outer_map_fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash);
if (outer_map_fd < 0)
- return log_unit_error_errno(u, errno, "Failed to get BPF map fd: %m");
+ return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m");
if (sym_bpf_map_update_elem(outer_map_fd, &u->cgroup_id, &inner_map_fd, BPF_ANY) != 0)
- return log_unit_error_errno(u, errno, "Error populating LSM BPF map: %m");
+ return log_unit_error_errno(u, errno, "bpf-lsm: Error populating BPF map: %m");
uint32_t allow = allow_list;
/* Use key 0 to store whether this is an allow list or a deny list */
if (sym_bpf_map_update_elem(inner_map_fd, &zero, &allow, BPF_ANY) != 0)
- return log_unit_error_errno(u, errno, "Error initializing BPF map: %m");
+ return log_unit_error_errno(u, errno, "bpf-lsm: Error initializing map: %m");
SET_FOREACH(fs, filesystems) {
r = fs_type_from_string(fs, &magic);
if (r < 0) {
- log_unit_warning(u, "Invalid filesystem name '%s', ignoring.", fs);
+ log_unit_warning(u, "bpf-lsm: Invalid filesystem name '%s', ignoring.", fs);
continue;
}
- log_unit_debug(u, "Restricting filesystem access to '%s'", fs);
+ log_unit_debug(u, "bpf-lsm: Restricting filesystem access to '%s'", fs);
for (int i = 0; i < FILESYSTEM_MAGIC_MAX; i++) {
if (magic[i] == 0)
break;
if (sym_bpf_map_update_elem(inner_map_fd, &magic[i], &dummy_value, BPF_ANY) != 0) {
- r = log_unit_error_errno(u, errno, "Failed to update BPF map: %m");
+ r = log_unit_error_errno(u, errno, "bpf-lsm: Failed to update BPF map: %m");
if (sym_bpf_map_delete_elem(outer_map_fd, &u->cgroup_id) != 0)
- log_unit_debug_errno(u, errno, "Failed to delete cgroup entry from LSM BPF map: %m");
+ log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from BPF map: %m");
return r;
}
@@ -278,10 +264,10 @@ int lsm_bpf_cleanup(const Unit *u) {
int fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash);
if (fd < 0)
- return log_unit_error_errno(u, errno, "Failed to get BPF map fd: %m");
+ return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m");
if (sym_bpf_map_delete_elem(fd, &u->cgroup_id) != 0)
- return log_unit_debug_errno(u, errno, "Failed to delete cgroup entry from LSM BPF map: %m");
+ return log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from LSM BPF map: %m");
return 0;
}
@@ -305,11 +291,11 @@ bool lsm_bpf_supported(bool initialize) {
}
int lsm_bpf_setup(Manager *m) {
- return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set up LSM BPF: %m");
+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to set up LSM BPF: %m");
}
int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, const bool allow_list) {
- return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to restrict filesystems using LSM BPF: %m");
+ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to restrict filesystems using LSM BPF: %m");
}
int lsm_bpf_cleanup(const Unit *u) {
@@ -344,7 +330,7 @@ int lsm_bpf_parse_filesystem(
set = filesystem_set_find(name);
if (!set) {
log_syntax(unit, flags & FILESYSTEM_PARSE_LOG ? LOG_WARNING : LOG_DEBUG, filename, line, 0,
- "Unknown filesystem group, ignoring: %s", name);
+ "bpf-lsm: Unknown filesystem group, ignoring: %s", name);
return 0;
}
diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c
index 09f83dc66..3aa1bfa1f 100644
--- a/src/core/bpf-socket-bind.c
+++ b/src/core/bpf-socket-bind.c
@@ -11,8 +11,9 @@
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
-#include "bpf/socket_bind/socket-bind-skel.h"
+#include "bpf-util.h"
#include "bpf/socket_bind/socket-bind-api.bpf.h"
+#include "bpf/socket_bind/socket-bind-skel.h"
static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
/* socket_bind_bpf__destroy handles object == NULL case */
@@ -68,27 +69,27 @@ static int prepare_socket_bind_bpf(
if (allow_count > SOCKET_BIND_MAX_RULES)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
- "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES);
+ "bpf-socket-bind: Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES);
if (deny_count > SOCKET_BIND_MAX_RULES)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
- "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES);
+ "bpf-socket-bind: Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES);
obj = socket_bind_bpf__open();
if (!obj)
- return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "Failed to open BPF object: %m");
+ return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "bpf-socket-bind: Failed to open BPF object: %m");
if (sym_bpf_map__resize(obj->maps.sd_bind_allow, MAX(allow_count, 1u)) != 0)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno,
- "Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow));
+ "bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow));
if (sym_bpf_map__resize(obj->maps.sd_bind_deny, MAX(deny_count, 1u)) != 0)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno,
- "Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny));
+ "bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny));
if (socket_bind_bpf__load(obj) != 0)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno,
- "Failed to load BPF object: %m");
+ "bpf-socket-bind: Failed to load BPF object: %m");
allow_map_fd = sym_bpf_map__fd(obj->maps.sd_bind_allow);
assert(allow_map_fd >= 0);
@@ -96,7 +97,7 @@ static int prepare_socket_bind_bpf(
r = update_rules_map(allow_map_fd, allow);
if (r < 0)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r,
- "Failed to put socket bind allow rules into BPF map '%s'",
+ "bpf-socket-bind: Failed to put socket bind allow rules into BPF map '%s'",
sym_bpf_map__name(obj->maps.sd_bind_allow));
deny_map_fd = sym_bpf_map__fd(obj->maps.sd_bind_deny);
@@ -105,7 +106,7 @@ static int prepare_socket_bind_bpf(
r = update_rules_map(deny_map_fd, deny);
if (r < 0)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r,
- "Failed to put socket bind deny rules into BPF map '%s'",
+ "bpf-socket-bind: Failed to put socket bind deny rules into BPF map '%s'",
sym_bpf_map__name(obj->maps.sd_bind_deny));
*ret_obj = TAKE_PTR(obj);
@@ -116,25 +117,17 @@ int bpf_socket_bind_supported(void) {
_cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL;
int r;
- r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
- if (r < 0)
- return log_debug_errno(r, "Can't determine whether the unified hierarchy is used: %m");
- if (r == 0) {
- log_debug("Not running with unified cgroup hierarchy, BPF is not supported");
- return false;
- }
-
- if (dlopen_bpf() < 0)
+ if (!cgroup_bpf_supported())
return false;
if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*ifindex=*/0)) {
- log_debug("BPF program type cgroup_sock_addr is not supported");
+ log_debug("bpf-socket-bind: BPF program type cgroup_sock_addr is not supported");
return false;
}
r = prepare_socket_bind_bpf(/*unit=*/NULL, /*allow_rules=*/NULL, /*deny_rules=*/NULL, &obj);
if (r < 0) {
- log_debug_errno(r, "BPF based socket_bind is not supported: %m");
+ log_debug_errno(r, "bpf-socket-bind: socket bind filtering is not supported: %m");
return false;
}
@@ -154,7 +147,7 @@ int bpf_socket_bind_add_initial_link_fd(Unit *u, int fd) {
r = fdset_put(u->initial_socket_bind_link_fds, fd);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to put socket-bind BPF link fd %d to initial fdset", fd);
+ return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to put BPF fd %d to initial fdset", fd);
return 0;
}
@@ -175,29 +168,29 @@ static int socket_bind_install_impl(Unit *u) {
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to get cgroup path: %m");
+ return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to get cgroup path: %m");
if (!cc->socket_bind_allow && !cc->socket_bind_deny)
return 0;
r = prepare_socket_bind_bpf(u, cc->socket_bind_allow, cc->socket_bind_deny, &obj);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to load BPF object: %m");
+ return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to load BPF object: %m");
cgroup_fd = open(cgroup_path, O_RDONLY | O_CLOEXEC, 0);
if (cgroup_fd < 0)
- return log_unit_error_errno(u, errno, "Failed to open cgroup=%s for reading: %m", cgroup_path);
+ return log_unit_error_errno(u, errno, "bpf-socket-bind: Failed to open cgroup %s for reading: %m", cgroup_path);
ipv4 = sym_bpf_program__attach_cgroup(obj->progs.sd_bind4, cgroup_fd);
r = sym_libbpf_get_error(ipv4);
if (r != 0)
- return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program: %m",
+ return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m",
sym_bpf_program__name(obj->progs.sd_bind4));
ipv6 = sym_bpf_program__attach_cgroup(obj->progs.sd_bind6, cgroup_fd);
r = sym_libbpf_get_error(ipv6);
if (r != 0)
- return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program: %m",
+ return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m",
sym_bpf_program__name(obj->progs.sd_bind6));
u->ipv4_socket_bind_link = TAKE_PTR(ipv4);
@@ -241,7 +234,8 @@ int bpf_socket_bind_add_initial_link_fd(Unit *u, int fd) {
}
int bpf_socket_bind_install(Unit *u) {
- return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to install socket bind: BPF framework is not supported");
+ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "bpf-socket-bind: Failed to install; BPF framework is not supported");
}
int bpf_serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) {
diff --git a/src/core/bpf-util.c b/src/core/bpf-util.c
new file mode 100644
index 000000000..9130aa373
--- /dev/null
+++ b/src/core/bpf-util.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "bpf-dlopen.h"
+#include "bpf-util.h"
+#include "cgroup-util.h"
+#include "log.h"
+
+bool cgroup_bpf_supported(void) {
+ static int supported = -1;
+ int r;
+
+ if (supported >= 0)
+ return supported;
+
+ r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
+ if (r < 0) {
+ log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m");
+ return (supported = false);
+ }
+
+ if (r == 0) {
+ log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Not running with unified cgroup hierarchy, disabling cgroup BPF features.");
+ return (supported = false);
+ }
+
+ r = dlopen_bpf();
+ if (r < 0) {
+ log_info_errno(r, "Failed to open libbpf, cgroup BPF features disabled: %m");
+ return (supported = false);
+ }
+
+ return (supported = true);
+}
diff --git a/src/core/bpf-util.h b/src/core/bpf-util.h
new file mode 100644
index 000000000..a6c55cd7e
--- /dev/null
+++ b/src/core/bpf-util.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include
+
+bool cgroup_bpf_supported(void);
diff --git a/src/core/device.c b/src/core/device.c
index 934676287..fcde8a420 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -163,14 +163,56 @@ static int device_coldplug(Unit *u) {
assert(d->state == DEVICE_DEAD);
/* First, let's put the deserialized state and found mask into effect, if we have it. */
-
- if (d->deserialized_state < 0 ||
- (d->deserialized_state == d->state &&
- d->deserialized_found == d->found))
+ if (d->deserialized_state < 0)
return 0;
- d->found = d->deserialized_found;
- device_set_state(d, d->deserialized_state);
+ Manager *m = u->manager;
+ DeviceFound found = d->deserialized_found;
+ DeviceState state = d->deserialized_state;
+
+ /* On initial boot, switch-root, reload, reexecute, the following happen:
+ * 1. MANAGER_IS_RUNNING() == false
+ * 2. enumerate devices: manager_enumerate() -> device_enumerate()
+ * Device.enumerated_found is set.
+ * 3. deserialize devices: manager_deserialize() -> device_deserialize()
+ * Device.deserialize_state and Device.deserialized_found are set.
+ * 4. coldplug devices: manager_coldplug() -> device_coldplug()
+ * deserialized properties are copied to the main properties.
+ * 5. MANAGER_IS_RUNNING() == true: manager_ready()
+ * 6. catchup devices: manager_catchup() -> device_catchup()
+ * Device.enumerated_found is applied to Device.found, and state is updated based on that.
+ *
+ * Notes:
+ * - On initial boot, no udev database exists. Hence, no devices are enumerated in the step 2.
+ * Also, there is no deserialized device. Device units are (a) generated based on dependencies of
+ * other units, or (b) generated when uevents are received.
+ *
+ * - On switch-root, the udev database may be cleared, except for devices with sticky bit, i.e.
+ * OPTIONS="db_persist". Hence, almost no devices are enumerated in the step 2. However, in general,
+ * we have several serialized devices. So, DEVICE_FOUND_UDEV bit in the deserialized_found must be
+ * ignored, as udev rules in initramfs and the main system are often different. If the deserialized
+ * state is DEVICE_PLUGGED, we need to downgrade it to DEVICE_TENTATIVE (or DEVICE_DEAD if nobody
+ * sees the device). Unlike the other starting mode, Manager.honor_device_enumeration == false
+ * (maybe, it is better to rename the flag) when device_coldplug() and device_catchup() are called.
+ * Hence, let's conditionalize the operations by using the flag. After switch-root, systemd-udevd
+ * will (re-)process all devices, and the Device.found and Device.state will be adjusted.
+ *
+ * - On reload or reexecute, we can trust enumerated_found, deserialized_found, and deserialized_state.
+ * Of course, deserialized parameters may be outdated, but the unit state can be adjusted later by
+ * device_catchup() or uevents. */
+
+ if (!m->honor_device_enumeration && !MANAGER_IS_USER(m) &&
+ !FLAGS_SET(d->enumerated_found, DEVICE_FOUND_UDEV)) {
+ found &= ~DEVICE_FOUND_UDEV; /* ignore DEVICE_FOUND_UDEV bit */
+ if (state == DEVICE_PLUGGED)
+ state = DEVICE_TENTATIVE; /* downgrade state */
+ }
+
+ if (d->found == found && d->state == state)
+ return 0;
+
+ d->found = found;
+ device_set_state(d, state);
return 0;
}
@@ -644,13 +686,9 @@ static void device_found_changed(Device *d, DeviceFound previous, DeviceFound no
}
static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
- Manager *m;
-
assert(d);
- m = UNIT(d)->manager;
-
- if (MANAGER_IS_RUNNING(m) && (m->honor_device_enumeration || MANAGER_IS_USER(m))) {
+ if (MANAGER_IS_RUNNING(UNIT(d)->manager)) {
DeviceFound n, previous;
/* When we are already running, then apply the new mask right-away, and trigger state changes
diff --git a/src/core/meson.build b/src/core/meson.build
index 1e8b6dc31..9efa542ac 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -135,6 +135,13 @@ libcore_sources = '''
unit.h
'''.split()
+if conf.get('BPF_FRAMEWORK') == 1
+ libcore_sources += files(
+ 'bpf-util.c',
+ 'bpf-util.h',
+ )
+endif
+
subdir('bpf')
subdir('bpf/socket_bind')
diff --git a/src/core/restrict-ifaces.c b/src/core/restrict-ifaces.c
index efa5c8d85..a0ecaff81 100644
--- a/src/core/restrict-ifaces.c
+++ b/src/core/restrict-ifaces.c
@@ -9,7 +9,7 @@
#include "bpf-dlopen.h"
#include "bpf-link.h"
-
+#include "bpf-util.h"
#include "bpf/restrict_ifaces/restrict-ifaces-skel.h"
static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) {
@@ -34,19 +34,19 @@ static int prepare_restrict_ifaces_bpf(
obj = restrict_ifaces_bpf__open();
if (!obj)
- return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "Failed to open BPF object: %m");
+ return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "restrict-interfaces: Failed to open BPF object: %m");
r = sym_bpf_map__resize(obj->maps.sd_restrictif, MAX(set_size(restrict_network_interfaces), 1u));
if (r != 0)
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r,
- "Failed to resize BPF map '%s': %m",
+ "restrict-interfaces: Failed to resize BPF map '%s': %m",
sym_bpf_map__name(obj->maps.sd_restrictif));
obj->rodata->is_allow_list = is_allow_list;
r = restrict_ifaces_bpf__load(obj);
if (r != 0)
- return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, r, "Failed to load BPF object: %m");
+ return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, r, "restrict-interfaces: Failed to load BPF object: %m");
map_fd = sym_bpf_map__fd(obj->maps.sd_restrictif);
@@ -56,13 +56,15 @@ static int prepare_restrict_ifaces_bpf(
ifindex = rtnl_resolve_interface(&rtnl, iface);
if (ifindex < 0) {
- log_unit_warning_errno(u, ifindex, "Couldn't find index of network interface '%s', ignoring: %m", iface);
+ log_unit_warning_errno(u, ifindex,
+ "restrict-interfaces: Couldn't find index of network interface '%s', ignoring: %m",
+ iface);
continue;
}
if (sym_bpf_map_update_elem(map_fd, &ifindex, &dummy, BPF_ANY))
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno,
- "Failed to update BPF map '%s' fd: %m",
+ "restrict-interfaces: Failed to update BPF map '%s' fd: %m",
sym_bpf_map__name(obj->maps.sd_restrictif));
}
@@ -78,29 +80,21 @@ int restrict_network_interfaces_supported(void) {
if (supported >= 0)
return supported;
- r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
- if (r < 0)
- return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m");
- if (r == 0) {
- log_debug("Not running with unified cgroup hierarchy, BPF is not supported");
- return supported = 0;
- }
-
- if (dlopen_bpf() < 0)
- return false;
+ if (!cgroup_bpf_supported())
+ return (supported = false);
if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*ifindex=*/0)) {
- log_debug("BPF program type cgroup_skb is not supported");
- return supported = 0;
+ log_debug("restrict-interfaces: BPF program type cgroup_skb is not supported");
+ return (supported = false);
}
r = prepare_restrict_ifaces_bpf(NULL, true, NULL, &obj);
if (r < 0) {
- log_debug_errno(r, "Failed to load BPF object: %m");
- return supported = 0;
+ log_debug_errno(r, "restrict-interfaces: Failed to load BPF object: %m");
+ return (supported = false);
}
- return supported = bpf_can_link_program(obj->progs.sd_restrictif_i);
+ return (supported = bpf_can_link_program(obj->progs.sd_restrictif_i));
}
static int restrict_network_interfaces_install_impl(Unit *u) {
@@ -117,7 +111,7 @@ static int restrict_network_interfaces_install_impl(Unit *u) {
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to get cgroup path: %m");
+ return log_unit_error_errno(u, r, "restrict-interfaces: Failed to get cgroup path: %m");
if (!cc->restrict_network_interfaces)
return 0;
@@ -136,12 +130,12 @@ static int restrict_network_interfaces_install_impl(Unit *u) {
ingress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_i, cgroup_fd);
r = sym_libbpf_get_error(ingress_link);
if (r != 0)
- return log_unit_error_errno(u, r, "Failed to create ingress cgroup link: %m");
+ return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create ingress cgroup link: %m");
egress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_e, cgroup_fd);
r = sym_libbpf_get_error(egress_link);
if (r != 0)
- return log_unit_error_errno(u, r, "Failed to create egress cgroup link: %m");
+ return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create egress cgroup link: %m");
u->restrict_ifaces_ingress_bpf_link = TAKE_PTR(ingress_link);
u->restrict_ifaces_egress_bpf_link = TAKE_PTR(egress_link);
@@ -180,7 +174,8 @@ int restrict_network_interfaces_add_initial_link_fd(Unit *u, int fd) {
r = fdset_put(u->initial_restric_ifaces_link_fds, fd);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to put restrict-ifaces-bpf-fd %d to restored fdset: %m", fd);
+ return log_unit_error_errno(u, r,
+ "restrict-interfaces: Failed to put restrict-ifaces-bpf-fd %d to restored fdset: %m", fd);
return 0;
}
@@ -192,7 +187,7 @@ int restrict_network_interfaces_supported(void) {
int restrict_network_interfaces_install(Unit *u) {
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Failed to install RestrictInterfaces: BPF programs built from source code are not supported: %m");
+ "restrict-interfaces: Failed to install; BPF programs built from source code are not supported: %m");
}
int serialize_restrict_network_interfaces(Unit *u, FILE *f, FDSet *fds) {
diff --git a/src/fundamental/sha256.c b/src/fundamental/sha256.c
index 0577a2492..cd16aec4d 100644
--- a/src/fundamental/sha256.c
+++ b/src/fundamental/sha256.c
@@ -47,6 +47,20 @@
# define SWAP64(n) (n)
#endif
+/* The condition below is from glibc's string/string-inline.c.
+ * See definition of _STRING_INLINE_unaligned. */
+#if !defined(__mc68020__) && !defined(__s390__) && !defined(__i386__)
+
+/* To check alignment gcc has an appropriate operator. Other compilers don't. */
+# if __GNUC__ >= 2
+# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0)
+# else
+# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0)
+# endif
+#else
+# define UNALIGNED_P(p) false
+#endif
+
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (FIPS 180-2:5.1.1) */
static const uint8_t fillbuf[64] = {
@@ -94,10 +108,7 @@ void sha256_init_ctx(struct sha256_ctx *ctx) {
}
/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
+ prolog according to the standard and write the result to RESBUF. */
void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Take yet unprocessed bytes into account. */
uint32_t bytes = ctx->buflen;
@@ -122,7 +133,10 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Put result from CTX in first 32 bytes following RESBUF. */
for (size_t i = 0; i < 8; ++i)
- ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
+ if (UNALIGNED_P(resbuf))
+ memcpy((uint8_t*) resbuf + i * sizeof(uint32_t), (uint32_t[]) { SWAP(ctx->H[i]) }, sizeof(uint32_t));
+ else
+ ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
return resbuf;
}
@@ -156,17 +170,6 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx
/* Process available complete blocks. */
if (len >= 64) {
-
-/* The condition below is from glibc's string/string-inline.c.
- * See definition of _STRING_INLINE_unaligned. */
-#if !defined(__mc68020__) && !defined(__s390__) && !defined(__i386__)
-
-/* To check alignment gcc has an appropriate operator. Other compilers don't. */
-# if __GNUC__ >= 2
-# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0)
-# else
-# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0)
-# endif
if (UNALIGNED_P(buffer))
while (len > 64) {
memcpy(ctx->buffer, buffer, 64);
@@ -174,9 +177,7 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx
buffer = (const char *) buffer + 64;
len -= 64;
}
- else
-#endif
- {
+ else {
sha256_process_block(buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in
index d1630937e..a41a56a3d 100755
--- a/src/kernel-install/kernel-install.in
+++ b/src/kernel-install/kernel-install.in
@@ -80,12 +80,13 @@ fi
if [ "${0##*/}" = "installkernel" ]; then
COMMAND=add
- # make install doesn't pass any initrds
- no_initrds=1
+ # kernel's install.sh invokes us as
+ # /sbin/installkernel