summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/base-filesystem.c4
-rw-r--r--src/shared/blockdev-util.c58
-rw-r--r--src/shared/bpf-dlopen.c4
-rw-r--r--src/shared/clean-ipc.c2
-rw-r--r--src/shared/copy.c2
-rw-r--r--src/shared/dlfcn-util.c2
-rw-r--r--src/shared/idn-util.c5
-rw-r--r--src/shared/install.c7
-rw-r--r--src/shared/reboot-util.c10
-rw-r--r--src/shared/reboot-util.h1
-rw-r--r--src/shared/tpm2-util.c2
-rw-r--r--src/shared/verbs.c18
-rw-r--r--src/shared/watchdog.c16
13 files changed, 89 insertions, 42 deletions
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index 47a766e..950ed1e 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -107,12 +107,12 @@ static const BaseFilesystem table[] = {
# else
# error "Unknown RISC-V ABI"
# endif
-#elif defined(__s390__)
- /* s390-linux-gnu */
#elif defined(__s390x__)
{ "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
"usr/lib64\0", "ld-lsb-s390x.so.3" },
# define KNOW_LIB64_DIRS 1
+#elif defined(__s390__)
+ /* s390-linux-gnu */
#elif defined(__sparc__)
#endif
/* gcc doesn't allow pragma to be used within constructs, hence log about this separately below */
diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c
index 72fad16..99e37fd 100644
--- a/src/shared/blockdev-util.c
+++ b/src/shared/blockdev-util.c
@@ -11,6 +11,7 @@
#include "alloc-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
+#include "device-private.h"
#include "device-util.h"
#include "devnum-util.h"
#include "dirent-util.h"
@@ -397,24 +398,36 @@ int lock_whole_block_device(dev_t devt, int operation) {
}
int blockdev_partscan_enabled(int fd) {
- _cleanup_free_ char *p = NULL, *buf = NULL;
- unsigned long long ull;
- struct stat st;
- int r;
-
- /* Checks if partition scanning is correctly enabled on the block device */
-
- if (fstat(fd, &st) < 0)
- return -errno;
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ unsigned capability;
+ int r, ext_range;
+
+ /* Checks if partition scanning is correctly enabled on the block device.
+ *
+ * The 'GENHD_FL_NO_PART_SCAN' flag was introduced by
+ * https://github.com/torvalds/linux/commit/d27769ec3df1a8de9ca450d2dcd72d1ab259ba32 (v3.2).
+ * But at that time, the flag is also effectively implied when 'minors' element of 'struct gendisk'
+ * 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/e81cd5a983bb35dabd38ee472cf3fea1c63e0f23 (v6.3),
+ * the 'capability' sysfs attribute is deprecated, hence we cannot check the flag from it.
+ *
+ * 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. */
- if (!S_ISBLK(st.st_mode))
- return -ENOTBLK;
+ assert(fd >= 0);
- if (asprintf(&p, "/sys/dev/block/%u:%u/capability", major(st.st_rdev), minor(st.st_rdev)) < 0)
- return -ENOMEM;
+ r = block_device_new_from_fd(fd, 0, &dev);
+ if (r < 0)
+ return r;
- r = read_one_line_file(p, &buf);
- if (r == -ENOENT) /* If the capability file doesn't exist then we are most likely looking at a
+ 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
* partition scanning on for it (we do for its parent, but not for the partition
* itself). */
@@ -422,7 +435,13 @@ int blockdev_partscan_enabled(int fd) {
if (r < 0)
return r;
- r = safe_atollu_full(buf, 16, &ull);
+ if (ext_range <= 1) /* The valus should be always positive, but the kernel uses '%d' for the
+ * attribute. Let's gracefully handle zero or negative. */
+ return false;
+
+ r = device_get_sysattr_unsigned_full(dev, "capability", 16, &capability);
+ if (r == -ENOENT)
+ return false;
if (r < 0)
return r;
@@ -430,7 +449,12 @@ int blockdev_partscan_enabled(int fd) {
#define GENHD_FL_NO_PART_SCAN (0x0200)
#endif
- return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN);
+ /* If 0x200 is set, part scanning is definitely off. */
+ if (FLAGS_SET(capability, GENHD_FL_NO_PART_SCAN))
+ return false;
+
+ /* Otherwise, assume part scanning is on, we have no further checks available. Assume the best. */
+ return true;
}
static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c
index 2556053..808f8c0 100644
--- a/src/shared/bpf-dlopen.c
+++ b/src/shared/bpf-dlopen.c
@@ -60,11 +60,15 @@ int dlopen_bpf(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"neither libbpf.so.1 nor libbpf.so.0 are installed: %s", dlerror());
+ log_debug("Loaded 'libbpf.so.0' via dlopen()");
+
/* symbols deprecated in 1.0 we use as compat */
r = dlsym_many_or_warn(dl, LOG_DEBUG,
DLSYM_ARG(bpf_create_map),
DLSYM_ARG(bpf_probe_prog_type));
} else {
+ log_debug("Loaded 'libbpf.so.1' via dlopen()");
+
/* symbols available from 0.7.0 */
r = dlsym_many_or_warn(dl, LOG_DEBUG,
DLSYM_ARG(bpf_map_create),
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index bbb343f..1e90cc2 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -58,7 +58,7 @@ static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid, bool rm) {
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
- return log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m");
+ return log_warning_errno(r, "Failed to read /proc/sysvipc/shm: %m");
if (r == 0)
break;
diff --git a/src/shared/copy.c b/src/shared/copy.c
index 9b78b9e..64c61e1 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -304,7 +304,7 @@ int copy_bytes_full(
if (try_cfr) {
n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
if (n < 0) {
- if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
+ if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF, -EOPNOTSUPP))
return n;
try_cfr = false;
diff --git a/src/shared/dlfcn-util.c b/src/shared/dlfcn-util.c
index a321df3..8022f55 100644
--- a/src/shared/dlfcn-util.c
+++ b/src/shared/dlfcn-util.c
@@ -49,6 +49,8 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"%s is not installed: %s", filename, dlerror());
+ log_debug("Loaded '%s' via dlopen()", filename);
+
va_list ap;
va_start(ap, log_level);
r = dlsym_many_or_warnv(dl, log_level, ap);
diff --git a/src/shared/idn-util.c b/src/shared/idn-util.c
index d4108d0..d9e0cca 100644
--- a/src/shared/idn-util.c
+++ b/src/shared/idn-util.c
@@ -50,7 +50,10 @@ int dlopen_idn(void) {
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libidn support is not installed: %s", dlerror());
- }
+ log_debug("Loaded 'libidn.so.11' via dlopen()");
+ } else
+ log_debug("Loaded 'libidn.so.12' via dlopen()");
+
r = dlsym_many_or_warn(
dl,
diff --git a/src/shared/install.c b/src/shared/install.c
index 84d29dc..af3e8a3 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -342,9 +342,12 @@ void install_changes_dump(int r, const char *verb, const InstallChange *changes,
assert(verb || r >= 0);
for (size_t i = 0; i < n_changes; i++) {
- if (changes[i].type < 0)
- assert(verb);
assert(changes[i].path);
+ /* This tries to tell the compiler that it's safe to use 'verb' in a string format if there
+ * was an error, but the compiler doesn't care and fails anyway, so strna(verb) is used
+ * too. */
+ assert(verb || changes[i].type >= 0);
+ verb = strna(verb);
/* When making changes here, make sure to also change install_error() in dbus-manager.c. */
diff --git a/src/shared/reboot-util.c b/src/shared/reboot-util.c
index 756f9d3..618658a 100644
--- a/src/shared/reboot-util.c
+++ b/src/shared/reboot-util.c
@@ -11,8 +11,15 @@
#include "reboot-util.h"
#include "string-util.h"
#include "umask-util.h"
+#include "utf8.h"
#include "virt.h"
+bool reboot_parameter_is_valid(const char *parameter) {
+ assert(parameter);
+
+ return ascii_is_valid(parameter) && strlen(parameter) <= NAME_MAX;
+}
+
int update_reboot_parameter_and_warn(const char *parameter, bool keep) {
int r;
@@ -30,6 +37,9 @@ int update_reboot_parameter_and_warn(const char *parameter, bool keep) {
return 0;
}
+ if (!reboot_parameter_is_valid(parameter))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid reboot parameter '%s'.", parameter);
+
RUN_WITH_UMASK(0022) {
r = write_string_file("/run/systemd/reboot-param", parameter,
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
diff --git a/src/shared/reboot-util.h b/src/shared/reboot-util.h
index bbca8b8..137f237 100644
--- a/src/shared/reboot-util.h
+++ b/src/shared/reboot-util.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+bool reboot_parameter_is_valid(const char *parameter);
int update_reboot_parameter_and_warn(const char *parameter, bool keep);
typedef enum RebootFlags {
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index dd8b825..04794c5 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -199,6 +199,8 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
if (!dl)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
+ log_debug("Loaded '%s' via dlopen()", fn);
+
func = dlsym(dl, TSS2_TCTI_INFO_SYMBOL);
if (!func)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
diff --git a/src/shared/verbs.c b/src/shared/verbs.c
index 2d19172..2973fe3 100644
--- a/src/shared/verbs.c
+++ b/src/shared/verbs.c
@@ -13,22 +13,21 @@
#include "verbs.h"
#include "virt.h"
-/* Wraps running_in_chroot() which is used in various places, but also adds an environment variable check so external
- * processes can reliably force this on.
- */
+/* Wraps running_in_chroot() which is used in various places, but also adds an environment variable check
+ * so external processes can reliably force this on. */
bool running_in_chroot_or_offline(void) {
int r;
- /* Added to support use cases like rpm-ostree, where from %post scripts we only want to execute "preset", but
- * not "start"/"restart" for example.
+ /* Added to support use cases like rpm-ostree, where from %post scripts we only want to execute "preset",
+ * but not "start"/"restart" for example.
*
* See docs/ENVIRONMENT.md for docs.
*/
r = getenv_bool("SYSTEMD_OFFLINE");
- if (r < 0 && r != -ENXIO)
- log_debug_errno(r, "Failed to parse $SYSTEMD_OFFLINE: %m");
- else if (r >= 0)
+ if (r >= 0)
return r > 0;
+ if (r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_OFFLINE, ignoring: %m");
/* We've had this condition check for a long time which basically checks for legacy chroot case like Fedora's
* "mock", which is used for package builds. We don't want to try to start systemd services there, since
@@ -40,8 +39,7 @@ bool running_in_chroot_or_offline(void) {
*/
r = running_in_chroot();
if (r < 0)
- log_debug_errno(r, "running_in_chroot(): %m");
-
+ log_debug_errno(r, "Failed to check if we're running in chroot, assuming not: %m");
return r > 0;
}
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
index 8871476..1b19fc4 100644
--- a/src/shared/watchdog.c
+++ b/src/shared/watchdog.c
@@ -95,7 +95,7 @@ static int set_pretimeout_governor(const char *governor) {
governor,
WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
if (r < 0)
- return log_error_errno(r, "Failed to set pretimeout_governor to '%s': %m", governor);
+ return log_error_errno(r, "Failed to set watchdog pretimeout_governor to '%s': %m", governor);
return r;
}
@@ -157,7 +157,7 @@ static int watchdog_read_pretimeout(void) {
if (ioctl(watchdog_fd, WDIOC_GETPRETIMEOUT, &sec) < 0) {
watchdog_pretimeout = 0;
- return log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Failed to get pretimeout value, ignoring: %m");
+ return log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Failed to get watchdog pretimeout value, ignoring: %m");
}
watchdog_pretimeout = sec * USEC_PER_SEC;
@@ -181,7 +181,7 @@ static int watchdog_set_pretimeout(void) {
return 0;
}
- return log_error_errno(errno, "Failed to set pretimeout to %s: %m", FORMAT_TIMESPAN(sec, USEC_PER_SEC));
+ return log_error_errno(errno, "Failed to set watchdog pretimeout to %s: %m", FORMAT_TIMESPAN(sec, USEC_PER_SEC));
}
/* The set ioctl does not return the actual value set so get it now. */
@@ -274,10 +274,10 @@ static int update_timeout(void) {
r = watchdog_set_timeout();
if (r < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(r))
- return log_error_errno(r, "Failed to set timeout to %s: %m",
+ return log_error_errno(r, "Failed to set watchdog hardware timeout to %s: %m",
FORMAT_TIMESPAN(watchdog_timeout, 0));
- log_info("Modifying watchdog timeout is not supported, reusing the programmed timeout.");
+ log_info("Modifying watchdog hardware timeout is not supported, reusing the programmed timeout.");
watchdog_timeout = USEC_INFINITY;
}
}
@@ -286,8 +286,8 @@ static int update_timeout(void) {
r = watchdog_read_timeout();
if (r < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(r))
- return log_error_errno(r, "Failed to query watchdog HW timeout: %m");
- log_info("Reading watchdog timeout is not supported, reusing the configured timeout.");
+ return log_error_errno(r, "Failed to query watchdog hardware timeout: %m");
+ log_info("Reading watchdog hardware timeout is not supported, reusing the configured timeout.");
watchdog_timeout = previous_timeout;
}
}
@@ -302,7 +302,7 @@ static int update_timeout(void) {
if (r < 0)
return r;
- log_info("Watchdog running with a timeout of %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
+ log_info("Watchdog running with a hardware timeout of %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
return watchdog_ping_now();
}