summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-16 18:18:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-16 18:18:14 +0000
commit67c5de60daa85b91fa68be4157e248fa31e75316 (patch)
tree7d567f3360f705ac21600343ef7f7cea645a9222 /src
parentAdding upstream version 256.1. (diff)
downloadsystemd-06a0a2fdeaf41892705cfec541146336e3c21087.tar.xz
systemd-06a0a2fdeaf41892705cfec541146336e3c21087.zip
Adding upstream version 256.2.upstream/256.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src')
-rw-r--r--src/analyze/analyze-security.c4
-rw-r--r--src/basic/build.c4
-rw-r--r--src/basic/missing_sched.h18
-rw-r--r--src/basic/missing_syscall.h17
-rw-r--r--src/basic/mountpoint-util.c4
-rw-r--r--src/basic/os-util.c10
-rw-r--r--src/basic/terminal-util.h14
-rw-r--r--src/boot/efi/boot.c7
-rw-r--r--src/boot/efi/meson.build11
-rw-r--r--src/boot/efi/util.c12
-rw-r--r--src/boot/efi/util.h2
-rw-r--r--src/boot/efi/vmm.c13
-rw-r--r--src/core/dbus-execute.c4
-rw-r--r--src/core/dbus-manager.c4
-rw-r--r--src/core/exec-invoke.c24
-rw-r--r--src/core/load-fragment.c7
-rw-r--r--src/core/manager.c70
-rw-r--r--src/core/namespace.c10
-rw-r--r--src/core/unit.c9
-rw-r--r--src/coredump/coredump.c20
-rw-r--r--src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c2
-rw-r--r--src/hostname/hostnamed.c4
-rwxr-xr-xsrc/kernel-install/60-ukify.install.in2
-rw-r--r--src/kernel-install/kernel-install.c2
-rw-r--r--src/login/user-runtime-dir.c27
-rw-r--r--src/network/networkd-ndisc.c69
-rw-r--r--src/nspawn/nspawn.c3
-rw-r--r--src/partition/repart.c48
-rw-r--r--src/resolve/resolved-dns-packet.c6
-rw-r--r--src/resolve/resolved-dns-packet.h2
-rw-r--r--src/run/run.c3
-rw-r--r--src/shared/bus-polkit.c12
-rw-r--r--src/shared/bus-polkit.h1
-rw-r--r--src/shared/condition.c10
-rw-r--r--src/shared/mkfs-util.c9
-rw-r--r--src/shared/parse-helpers.c19
-rw-r--r--src/shared/parse-helpers.h11
-rw-r--r--src/shared/pretty-print.c7
-rw-r--r--src/shared/ptyfwd.c16
-rw-r--r--src/shared/ptyfwd.h2
-rw-r--r--src/shared/seccomp-util.c56
-rw-r--r--src/shared/seccomp-util.h1
-rw-r--r--src/sysusers/sysusers.c12
-rw-r--r--src/test/test-cgroup.c2
-rw-r--r--src/test/test-execute.c2
-rw-r--r--src/test/test-mountpoint-util.c30
-rwxr-xr-xsrc/ukify/ukify.py2
-rw-r--r--src/vmspawn/vmspawn-util.h2
-rw-r--r--src/vmspawn/vmspawn.c3
49 files changed, 431 insertions, 198 deletions
diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c
index 75508f4..3d7b647 100644
--- a/src/analyze/analyze-security.c
+++ b/src/analyze/analyze-security.c
@@ -1244,8 +1244,8 @@ static const struct security_assessor security_assessor_table[] = {
{
.id = "CapabilityBoundingSet=~CAP_BPF",
.json_field = "CapabilityBoundingSet_CAP_BPF",
- .description_good = "Service may load BPF programs",
- .description_bad = "Service may not load BPF programs",
+ .description_good = "Service may not load BPF programs",
+ .description_bad = "Service may load BPF programs",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
.weight = 25,
.range = 1,
diff --git a/src/basic/build.c b/src/basic/build.c
index 3ab25f7..488ed20 100644
--- a/src/basic/build.c
+++ b/src/basic/build.c
@@ -287,8 +287,8 @@ int version(void) {
if (colors_enabled())
b = systemd_features_with_color();
- printf("%ssystemd " PROJECT_VERSION_FULL "%s (" GIT_VERSION ")\n%s\n",
- ansi_highlight(), ansi_normal(),
+ printf("%ssystemd %i%s (" GIT_VERSION ")\n%s\n",
+ ansi_highlight(), PROJECT_VERSION, ansi_normal(),
b ?: systemd_features);
return 0;
}
diff --git a/src/basic/missing_sched.h b/src/basic/missing_sched.h
index b8109d3..bd83b41 100644
--- a/src/basic/missing_sched.h
+++ b/src/basic/missing_sched.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <linux/types.h>
#include <sched.h>
#include "macro.h"
@@ -35,3 +36,20 @@ assert_cc(PF_KTHREAD == 0x00200000);
#else
assert_cc(TASK_COMM_LEN == 16);
#endif
+
+#if !HAVE_STRUCT_SCHED_ATTR
+struct sched_attr {
+ __u32 size; /* Size of this structure */
+ __u32 sched_policy; /* Policy (SCHED_*) */
+ __u64 sched_flags; /* Flags */
+ __s32 sched_nice; /* Nice value (SCHED_OTHER,
+ SCHED_BATCH) */
+ __u32 sched_priority; /* Static priority (SCHED_FIFO,
+ SCHED_RR) */
+ /* Remaining fields are for SCHED_DEADLINE
+ and potentially soon for SCHED_OTHER/SCHED_BATCH */
+ __u64 sched_runtime;
+ __u64 sched_deadline;
+ __u64 sched_period;
+};
+#endif
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index 8628077..e2cd8b4 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -22,6 +22,7 @@
#include "macro.h"
#include "missing_keyctl.h"
+#include "missing_sched.h"
#include "missing_stat.h"
#include "missing_syscall_def.h"
@@ -667,6 +668,22 @@ static inline ssize_t missing_getdents64(int fd, void *buffer, size_t length) {
/* ======================================================================= */
+#if !HAVE_SCHED_SETATTR
+
+static inline ssize_t missing_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) {
+# if defined __NR_sched_setattr
+ return syscall(__NR_sched_setattr, pid, attr, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+# define sched_setattr missing_sched_setattr
+#endif
+
+/* ======================================================================= */
+
/* glibc does not provide clone() on ia64, only clone2(). Not only that, but it also doesn't provide a
* prototype, only the symbol in the shared library (it provides a prototype for clone(), but not the
* symbol in the shared library). */
diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c
index 66fa35b..135b296 100644
--- a/src/basic/mountpoint-util.c
+++ b/src/basic/mountpoint-util.c
@@ -231,8 +231,6 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
/* If statx() is not available or forbidden, fall back to name_to_handle_at() below */
} else if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) /* yay! */
return FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
- else if (FLAGS_SET(sx.stx_mask, STATX_TYPE) && S_ISLNK(sx.stx_mode))
- return false; /* symlinks are never mount points */
r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags);
if (r < 0) {
@@ -311,8 +309,6 @@ fallback_fstat:
flags |= AT_SYMLINK_NOFOLLOW;
if (fstatat(fd, filename, &a, flags) < 0)
return -errno;
- if (S_ISLNK(a.st_mode)) /* Symlinks are never mount points */
- return false;
if (isempty(filename))
r = fstatat(fd, "..", &b, 0);
diff --git a/src/basic/os-util.c b/src/basic/os-util.c
index 0d26d18..79f641b 100644
--- a/src/basic/os-util.c
+++ b/src/basic/os-util.c
@@ -259,13 +259,7 @@ int open_extension_release_at(
}
if (!relax_extension_release_check) {
- _cleanup_free_ char *base_image_name = NULL, *base_extension = NULL;
-
- r = path_extract_image_name(image_name, &base_image_name);
- if (r < 0) {
- log_debug_errno(r, "Failed to extract image name from %s/%s, ignoring: %m", dir_path, de->d_name);
- continue;
- }
+ _cleanup_free_ char *base_extension = NULL;
r = path_extract_image_name(extension, &base_extension);
if (r < 0) {
@@ -273,7 +267,7 @@ int open_extension_release_at(
continue;
}
- if (!streq(base_image_name, base_extension) &&
+ if (!streq(image_name, base_extension) &&
extension_release_strict_xattr_value(fd, dir_path, image_name) != 0)
continue;
}
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index ecfe574..c70c938 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -42,26 +42,26 @@
#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
#define ANSI_HIGHLIGHT_CYAN "\x1B[0;1;36m"
#define ANSI_HIGHLIGHT_WHITE "\x1B[0;1;37m"
-#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38;5;100m"
-#define ANSI_HIGHLIGHT_KHAKI3 "\x1B[0;1;38;5;185m"
-#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m"
+#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38:5:100m"
+#define ANSI_HIGHLIGHT_KHAKI3 "\x1B[0;1;38:5:185m"
+#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38:5:245m"
#define ANSI_HIGHLIGHT_YELLOW ANSI_HIGHLIGHT_KHAKI3 /* Replacement yellow that is more legible */
/* Underlined */
-#define ANSI_GREY_UNDERLINE "\x1B[0;4;38;5;245m"
+#define ANSI_GREY_UNDERLINE "\x1B[0;4;38:5:245m"
#define ANSI_BRIGHT_BLACK_UNDERLINE "\x1B[0;4;90m"
#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
-#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;38;5;185m"
+#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;38:5:185m"
#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
-#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38;5;245m"
+#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38:5:245m"
/* Other ANSI codes */
#define ANSI_UNDERLINE "\x1B[0;4m"
#define ANSI_ADD_UNDERLINE "\x1B[4m"
-#define ANSI_ADD_UNDERLINE_GREY ANSI_ADD_UNDERLINE "\x1B[58;5;245m"
+#define ANSI_ADD_UNDERLINE_GREY ANSI_ADD_UNDERLINE "\x1B[58:5:245m"
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 79de121..8287c21 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -879,6 +879,7 @@ static bool menu_run(
switch (key) {
case KEYPRESS(0, SCAN_UP, 0):
+ case KEYPRESS(0, SCAN_VOLUME_UP, 0): /* Handle phones/tablets that only have a volume up/down rocker + power key (and otherwise just touchscreen input) */
case KEYPRESS(0, 0, 'k'):
case KEYPRESS(0, 0, 'K'):
if (idx_highlight > 0)
@@ -886,6 +887,7 @@ static bool menu_run(
break;
case KEYPRESS(0, SCAN_DOWN, 0):
+ case KEYPRESS(0, SCAN_VOLUME_DOWN, 0):
case KEYPRESS(0, 0, 'j'):
case KEYPRESS(0, 0, 'J'):
if (idx_highlight < config->n_entries-1)
@@ -923,9 +925,10 @@ static bool menu_run(
case KEYPRESS(0, 0, '\n'):
case KEYPRESS(0, 0, '\r'):
- case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
- case KEYPRESS(0, SCAN_F3, '\r'): /* Teclast X98+ II firmware sends malformed events */
+ case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
+ case KEYPRESS(0, SCAN_F3, '\r'): /* Teclast X98+ II firmware sends malformed events */
case KEYPRESS(0, SCAN_RIGHT, 0):
+ case KEYPRESS(0, SCAN_SUSPEND, 0): /* Handle phones/tablets with only a power key + volume up/down rocker (and otherwise just touchscreen input) */
action = ACTION_RUN;
break;
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
index 7a60b0e..a1bdd58 100644
--- a/src/boot/efi/meson.build
+++ b/src/boot/efi/meson.build
@@ -63,13 +63,14 @@ foreach ctype : ['color-normal', 'color-entry', 'color-highlight', 'color-edit']
'EFI_' + c[1].strip().underscorify().to_upper()))
endforeach
+efi_conf.set_quoted('PROJECT_VERSION', project_major_version)
+efi_conf.set_quoted('VERSION_TAG', version_tag)
+efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
+
if meson.is_cross_build() and get_option('sbat-distro') == 'auto'
warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.')
elif get_option('sbat-distro') != ''
efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
- efi_conf.set_quoted('PROJECT_VERSION', meson.project_version().split('~')[0])
- efi_conf.set_quoted('VERSION_TAG', version_tag)
- efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
if get_option('sbat-distro-generation') < 1
error('SBAT Distro Generation must be a positive integer')
endif
@@ -388,8 +389,8 @@ foreach efi_elf_binary : efi_elf_binaries
install_tag : 'systemd-boot',
command : [
elf2efi_py,
- '--version-major=' + meson.project_version().split('~')[0],
- '--version-minor=0',
+ '--version-major=' + project_major_version,
+ '--version-minor=' + project_minor_version,
'--efi-major=1',
'--efi-minor=1',
'--subsystem=10',
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
index b5c8c63..eb29eb2 100644
--- a/src/boot/efi/util.c
+++ b/src/boot/efi/util.c
@@ -330,7 +330,14 @@ EFI_STATUS chunked_read(EFI_FILE *file, size_t *size, void *buf) {
return EFI_SUCCESS;
}
-EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, size_t off, size_t size, char **ret, size_t *ret_size) {
+EFI_STATUS file_read(
+ EFI_FILE *dir,
+ const char16_t *name,
+ uint64_t off,
+ size_t size,
+ char **ret,
+ size_t *ret_size) {
+
_cleanup_(file_closep) EFI_FILE *handle = NULL;
_cleanup_free_ char *buf = NULL;
EFI_STATUS err;
@@ -350,6 +357,9 @@ EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, size_t off, size_t siz
if (err != EFI_SUCCESS)
return err;
+ if (info->FileSize > SIZE_MAX)
+ return EFI_BAD_BUFFER_SIZE;
+
size = info->FileSize;
}
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
index ceac07c..dc624f4 100644
--- a/src/boot/efi/util.h
+++ b/src/boot/efi/util.h
@@ -102,7 +102,7 @@ char16_t *xstr8_to_path(const char *stra);
char16_t *mangle_stub_cmdline(char16_t *cmdline);
EFI_STATUS chunked_read(EFI_FILE *file, size_t *size, void *buf);
-EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, size_t off, size_t size, char **content, size_t *content_size);
+EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, uint64_t off, size_t size, char **content, size_t *content_size);
static inline void file_closep(EFI_FILE **handle) {
if (!*handle)
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
index 60e216d..bfc7acc 100644
--- a/src/boot/efi/vmm.c
+++ b/src/boot/efi/vmm.c
@@ -241,13 +241,21 @@ static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_lef
size -= header->length;
p += header->length;
- /* Skip over string table. */
+ /* Special case: if there are no strings appended, we'll see two NUL bytes, skip over them */
+ if (size >= 2 && p[0] == 0 && p[1] == 0) {
+ size -= 2;
+ p += 2;
+ continue;
+ }
+
+ /* Skip over a populated string table. */
+ bool first = true;
for (;;) {
const uint8_t *e = memchr(p, 0, size);
if (!e)
return NULL;
- if (e == p) {/* Double NUL byte means we've reached the end of the string table. */
+ if (!first && e == p) {/* Double NUL byte means we've reached the end of the string table. */
p++;
size--;
break;
@@ -255,6 +263,7 @@ static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_lef
size -= e + 1 - p;
p = e + 1;
+ first = false;
}
}
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 21c260b..b0d9402 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -2743,10 +2743,6 @@ int bus_exec_context_set_transient_property(
if (!path_is_normalized(simplified))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"WorkingDirectory= expects a normalized path or '~'");
-
- if (path_below_api_vfs(simplified))
- return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
- "WorkingDirectory= may not be below /proc/, /sys/ or /dev/");
}
}
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 2515f54..7da35a8 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1708,6 +1708,10 @@ static int method_soft_reboot(sd_bus_message *message, void *userdata, sd_bus_er
assert(message);
+ if (!MANAGER_IS_SYSTEM(m))
+ return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Soft reboot is only supported by system manager.");
+
r = verify_run_space_permissive("soft reboot may fail", error);
if (r < 0)
return r;
diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c
index ee8db04..09f98d3 100644
--- a/src/core/exec-invoke.c
+++ b/src/core/exec-invoke.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include <linux/sched.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
@@ -44,6 +45,7 @@
#include "journal-send.h"
#include "missing_ioprio.h"
#include "missing_prctl.h"
+#include "missing_sched.h"
#include "missing_securebits.h"
#include "missing_syscall.h"
#include "mkdir-label.h"
@@ -1439,6 +1441,13 @@ static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p, b
return r;
}
+ /* Sending over exec_fd or handoff_timestamp_fd requires write() syscall. */
+ if (p->exec_fd >= 0 || p->handoff_timestamp_fd >= 0) {
+ r = seccomp_filter_set_add_by_name(c->syscall_filter, c->syscall_allow_list, "write");
+ if (r < 0)
+ return r;
+ }
+
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false);
}
@@ -3775,7 +3784,7 @@ static int get_open_file_fd(const ExecContext *c, const ExecParameters *p, const
else if (FLAGS_SET(of->flags, OPENFILE_TRUNCATE))
flags |= O_TRUNC;
- fd = fd_reopen(ofd, flags | O_CLOEXEC);
+ fd = fd_reopen(ofd, flags|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return log_exec_error_errno(c, p, fd, "Failed to reopen file '%s': %m", of->path);
@@ -4011,7 +4020,7 @@ static int send_handoff_timestamp(
dual_timestamp dt;
dual_timestamp_now(&dt);
- if (send(p->handoff_timestamp_fd, (const usec_t[2]) { dt.realtime, dt.monotonic }, sizeof(usec_t) * 2, 0) < 0) {
+ if (write(p->handoff_timestamp_fd, (const usec_t[2]) { dt.realtime, dt.monotonic }, sizeof(usec_t) * 2) < 0) {
if (reterr_exit_status)
*reterr_exit_status = EXIT_EXEC;
return log_exec_error_errno(c, p, errno, "Failed to send handoff timestamp: %m");
@@ -4402,15 +4411,14 @@ int exec_invoke(
}
if (context->cpu_sched_set) {
- struct sched_param param = {
+ struct sched_attr attr = {
+ .size = sizeof(attr),
+ .sched_policy = context->cpu_sched_policy,
.sched_priority = context->cpu_sched_priority,
+ .sched_flags = context->cpu_sched_reset_on_fork ? SCHED_FLAG_RESET_ON_FORK : 0,
};
- r = sched_setscheduler(0,
- context->cpu_sched_policy |
- (context->cpu_sched_reset_on_fork ?
- SCHED_RESET_ON_FORK : 0),
- &param);
+ r = sched_setattr(/* pid= */ 0, &attr, /* flags= */ 0);
if (r < 0) {
*exit_status = EXIT_SETSCHEDULER;
return log_exec_error_errno(context, params, errno, "Failed to set up CPU scheduling: %m");
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 5ae6888..a1a116a 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2634,7 +2634,8 @@ int config_parse_working_directory(
return missing_ok ? 0 : -ENOEXEC;
}
- r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS|(missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue);
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE|(missing_ok ? 0 : PATH_CHECK_FATAL),
+ unit, filename, line, lvalue);
if (r < 0)
return missing_ok ? 0 : -ENOEXEC;
@@ -5396,7 +5397,7 @@ int config_parse_mount_images(
continue;
}
- r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS_DEV_OK, unit, filename, line, lvalue);
if (r < 0)
continue;
@@ -5412,7 +5413,7 @@ int config_parse_mount_images(
continue;
}
- r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS_DEV_OK, unit, filename, line, lvalue);
if (r < 0)
continue;
diff --git a/src/core/manager.c b/src/core/manager.c
index 90e72b0..5997ef0 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -3086,41 +3086,43 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
default: {
- /* Starting SIGRTMIN+0 */
- static const struct {
- const char *target;
- JobMode mode;
- } target_table[] = {
- [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
- [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
- [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
- [3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [7] = { SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
- };
-
- /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
- static const ManagerObjective objective_table[] = {
- [0] = MANAGER_HALT,
- [1] = MANAGER_POWEROFF,
- [2] = MANAGER_REBOOT,
- [3] = MANAGER_KEXEC,
- [4] = MANAGER_SOFT_REBOOT,
- };
-
- if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
- (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
- int idx = (int) sfsi.ssi_signo - SIGRTMIN;
- manager_start_special(m, target_table[idx].target, target_table[idx].mode);
- break;
- }
+ if (MANAGER_IS_SYSTEM(m)) {
+ /* Starting SIGRTMIN+0 */
+ static const struct {
+ const char *target;
+ JobMode mode;
+ } target_table[] = {
+ [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
+ [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
+ [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
+ [3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [7] = { SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ };
+
+ /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
+ static const ManagerObjective objective_table[] = {
+ [0] = MANAGER_HALT,
+ [1] = MANAGER_POWEROFF,
+ [2] = MANAGER_REBOOT,
+ [3] = MANAGER_KEXEC,
+ [4] = MANAGER_SOFT_REBOOT,
+ };
+
+ if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
+ (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
+ int idx = (int) sfsi.ssi_signo - SIGRTMIN;
+ manager_start_special(m, target_table[idx].target, target_table[idx].mode);
+ break;
+ }
- if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
- (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) {
- m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13];
- break;
+ if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
+ (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) {
+ m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13];
+ break;
+ }
}
switch (sfsi.ssi_signo - SIGRTMIN) {
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 6c0dc94..a9b98bc 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1695,11 +1695,11 @@ static int apply_one_mount(
(void) mkdir_parents(mount_entry_path(m), 0755);
q = make_mount_point_inode_from_path(what, mount_entry_path(m), 0755);
- if (q < 0) {
- if (q != -EEXIST) // FIXME: this shouldn't be logged at LOG_WARNING, but be bubbled up, and logged there to avoid duplicate logging
- log_warning_errno(q, "Failed to create destination mount point node '%s', ignoring: %m",
- mount_entry_path(m));
- } else
+ if (q < 0 && q != -EEXIST)
+ // FIXME: this shouldn't be logged at LOG_WARNING, but be bubbled up, and logged there to avoid duplicate logging
+ log_warning_errno(q, "Failed to create destination mount point node '%s', ignoring: %m",
+ mount_entry_path(m));
+ else
try_again = true;
}
diff --git a/src/core/unit.c b/src/core/unit.c
index 2d40618..852926b 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -41,6 +41,7 @@
#include "logarithm.h"
#include "macro.h"
#include "mkdir-label.h"
+#include "mountpoint-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rm-rf.h"
@@ -1405,11 +1406,13 @@ int unit_load_fragment_and_dropin(Unit *u, bool fragment_required) {
u->load_state = UNIT_LOADED;
}
+ u = unit_follow_merge(u);
+
/* Load drop-in directory data. If u is an alias, we might be reloading the
* target unit needlessly. But we cannot be sure which drops-ins have already
* been loaded and which not, at least without doing complicated book-keeping,
* so let's always reread all drop-ins. */
- r = unit_load_dropin(unit_follow_merge(u));
+ r = unit_load_dropin(u);
if (r < 0)
return r;
@@ -4234,6 +4237,10 @@ static int unit_verify_contexts(const Unit *u, const ExecContext *ec) {
if (ec->dynamic_user && ec->working_directory_home)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC), "WorkingDirectory=~ is not allowed under DynamicUser=yes. Refusing.");
+ if (ec->working_directory && path_below_api_vfs(ec->working_directory) &&
+ exec_needs_mount_namespace(ec, /* params = */ NULL, /* runtime = */ NULL))
+ return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC), "WorkingDirectory= may not be below /proc/, /sys/ or /dev/ when using mount namespacing. Refusing.");
+
return 0;
}
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index a8ee8e0..f5c4cf5 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -503,17 +503,21 @@ static int save_external_coredump(
bus_error_message(&error, r));
}
+ /* First, ensure we are not going to go over the cgroup limit */
max_size = MIN(cgroup_limit, max_size);
- max_size = LESS_BY(max_size, 1024U) / 2; /* Account for 1KB metadata overhead for compressing */
- max_size = MAX(PROCESS_SIZE_MIN, max_size); /* Impose a lower minimum */
-
- /* tmpfs might get full quickly, so check the available space too.
- * But don't worry about errors here, failing to access the storage
- * location will be better logged when writing to it. */
+ /* tmpfs might get full quickly, so check the available space too. But don't worry about
+ * errors here, failing to access the storage location will be better logged when writing to
+ * it. */
if (fstatvfs(fd, &sv) >= 0)
max_size = MIN((uint64_t)sv.f_frsize * (uint64_t)sv.f_bfree, max_size);
-
- log_debug("Limiting core file size to %" PRIu64 " bytes due to cgroup memory limits.", max_size);
+ /* Impose a lower minimum, otherwise we will miss the basic headers. */
+ max_size = MAX(PROCESS_SIZE_MIN, max_size);
+ /* Ensure we can always switch to compressing on the fly in case we are running out of space
+ * by keeping half of the space/memory available, plus 1KB metadata overhead from the
+ * compression algorithm. */
+ max_size = LESS_BY(max_size, 1024U) / 2;
+
+ log_debug("Limiting core file size to %" PRIu64 " bytes due to cgroup and/or filesystem limits.", max_size);
}
r = copy_bytes(input_fd, fd, max_size, 0);
diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c
index 8b4754a..f064e1d 100644
--- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c
+++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c
@@ -223,7 +223,7 @@ _public_ void cryptsetup_token_dump(
crypt_log(cd, "\ttpm2-pubkey:" CRYPT_DUMP_LINE_SEP "%s\n", pubkey_str);
crypt_log(cd, "\ttpm2-pubkey-pcrs: %s\n", strna(pubkey_pcrs_str));
crypt_log(cd, "\ttpm2-primary-alg: %s\n", strna(tpm2_asym_alg_to_string(primary_alg)));
- crypt_log(cd, "\ttpm2-blob: %s\n", blob_str);
+ crypt_log(cd, "\ttpm2-blob: %s\n", blob_str);
crypt_log(cd, "\ttpm2-policy-hash:" CRYPT_DUMP_LINE_SEP "%s\n", policy_hash_str);
crypt_log(cd, "\ttpm2-pin: %s\n", true_false(flags & TPM2_FLAGS_USE_PIN));
crypt_log(cd, "\ttpm2-pcrlock: %s\n", true_false(flags & TPM2_FLAGS_USE_PCRLOCK));
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index fe1216f..a4030d0 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -1619,11 +1619,13 @@ static int vl_method_describe(Varlink *link, JsonVariant *parameters, VarlinkMet
if (r != 0)
return r;
- r = varlink_verify_polkit_async(
+ r = varlink_verify_polkit_async_full(
link,
c->bus,
"org.freedesktop.hostname1.get-hardware-serial",
/* details= */ NULL,
+ UID_INVALID,
+ POLKIT_DONT_REPLY,
&c->polkit_registry);
if (r == 0)
return 0; /* No authorization for now, but the async polkit stuff will call us again when it has it */
diff --git a/src/kernel-install/60-ukify.install.in b/src/kernel-install/60-ukify.install.in
index 54a5daf..076390d 100755
--- a/src/kernel-install/60-ukify.install.in
+++ b/src/kernel-install/60-ukify.install.in
@@ -27,7 +27,7 @@ from shutil import which
from pathlib import Path
from typing import Optional
-__version__ = '{{PROJECT_VERSION_FULL}} ({{VERSION_TAG}})'
+__version__ = '{{PROJECT_VERSION}} ({{VERSION_TAG}})'
try:
VERBOSE = int(os.environ['KERNEL_INSTALL_VERBOSE']) > 0
diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c
index 5d559a9..2762927 100644
--- a/src/kernel-install/kernel-install.c
+++ b/src/kernel-install/kernel-install.c
@@ -1467,7 +1467,7 @@ static int help(void) {
return log_oom();
printf("%1$s [OPTIONS...] COMMAND ...\n\n"
- "%5$sAdd and remove kernel and initrd images to and from /boot/%6$s\n"
+ "%5$sAdd and remove kernel and initrd images to and from the boot partition.%6$s\n"
"\n%3$sUsage:%4$s\n"
" kernel-install [OPTIONS...] add [[[KERNEL-VERSION] KERNEL-IMAGE] [INITRD ...]]\n"
" kernel-install [OPTIONS...] add-all\n"
diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c
index 575f8eb..b242f83 100644
--- a/src/login/user-runtime-dir.c
+++ b/src/login/user-runtime-dir.c
@@ -25,27 +25,38 @@
#include "strv.h"
#include "user-util.h"
-static int acquire_runtime_dir_properties(uint64_t *size, uint64_t *inodes) {
+static int acquire_runtime_dir_properties(uint64_t *ret_size, uint64_t *ret_inodes) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ uint64_t size, inodes;
int r;
+ assert(ret_size);
+ assert(ret_inodes);
+
r = sd_bus_default_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect to system bus: %m");
- r = bus_get_property_trivial(bus, bus_login_mgr, "RuntimeDirectorySize", &error, 't', size);
+ r = bus_get_property_trivial(bus, bus_login_mgr, "RuntimeDirectorySize", &error, 't', &size);
if (r < 0) {
log_warning_errno(r, "Failed to acquire runtime directory size, ignoring: %s", bus_error_message(&error, r));
- *size = physical_memory_scale(10U, 100U); /* 10% */
+ sd_bus_error_free(&error);
+
+ size = physical_memory_scale(10U, 100U); /* 10% */
}
- r = bus_get_property_trivial(bus, bus_login_mgr, "RuntimeDirectoryInodesMax", &error, 't', inodes);
+ r = bus_get_property_trivial(bus, bus_login_mgr, "RuntimeDirectoryInodesMax", &error, 't', &inodes);
if (r < 0) {
log_warning_errno(r, "Failed to acquire number of inodes for runtime directory, ignoring: %s", bus_error_message(&error, r));
- *inodes = DIV_ROUND_UP(*size, 4096);
+ sd_bus_error_free(&error);
+
+ inodes = DIV_ROUND_UP(size, 4096);
}
+ *ret_size = size;
+ *ret_inodes = inodes;
+
return 0;
}
@@ -70,7 +81,7 @@ static int user_mkdir_runtime_path(
if (path_is_mount_point(runtime_path) > 0)
log_debug("%s is already a mount point", runtime_path);
else {
- char options[sizeof("mode=0700,uid=,gid=,size=,nr_inodes=,smackfsroot=*")
+ char options[STRLEN("mode=0700,uid=,gid=,size=,nr_inodes=,smackfsroot=*")
+ DECIMAL_STR_MAX(uid_t)
+ DECIMAL_STR_MAX(gid_t)
+ DECIMAL_STR_MAX(uint64_t)
@@ -140,7 +151,7 @@ static int user_remove_runtime_path(const char *runtime_path) {
}
static int do_mount(const char *user) {
- char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)];
+ char runtime_path[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)];
uint64_t runtime_dir_size, runtime_dir_inodes;
uid_t uid;
gid_t gid;
@@ -165,7 +176,7 @@ static int do_mount(const char *user) {
}
static int do_umount(const char *user) {
- char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)];
+ char runtime_path[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)];
uid_t uid;
int r;
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 7cafe1f..50d284b 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -222,20 +222,33 @@ static int ndisc_request_route(Route *route, Link *link) {
/* Note, here do not call route_remove_and_cancel() with 'route' directly, otherwise
* existing route(s) may be removed needlessly. */
- if (route_get(link->manager, route, &existing) >= 0) {
- /* Found an existing route that may conflict with this route. */
+ /* First, check if a conflicting route is already requested. If there is an existing route,
+ * and also an existing pending request, then the source may be updated by the request. So,
+ * we first need to check the source of the requested route. */
+ if (route_get_request(link->manager, route, &req) >= 0) {
+ existing = ASSERT_PTR(req->userdata);
if (!route_can_update(existing, route)) {
- log_link_debug(link, "Found an existing route that conflicts with new route based on a received RA, removing.");
+ if (existing->source == NETWORK_CONFIG_SOURCE_STATIC) {
+ log_link_debug(link, "Found a pending route request that conflicts with new request based on a received RA, ignoring request.");
+ return 0;
+ }
+
+ log_link_debug(link, "Found a pending route request that conflicts with new request based on a received RA, cancelling.");
r = route_remove_and_cancel(existing, link->manager);
if (r < 0)
return r;
}
}
- if (route_get_request(link->manager, route, &req) >= 0) {
- existing = ASSERT_PTR(req->userdata);
+ /* Then, check if a conflicting route exists. */
+ if (route_get(link->manager, route, &existing) >= 0) {
if (!route_can_update(existing, route)) {
- log_link_debug(link, "Found a pending route request that conflicts with new request based on a received RA, cancelling.");
+ if (existing->source == NETWORK_CONFIG_SOURCE_STATIC) {
+ log_link_debug(link, "Found an existing route that conflicts with new route based on a received RA, ignoring request.");
+ return 0;
+ }
+
+ log_link_debug(link, "Found an existing route that conflicts with new route based on a received RA, removing.");
r = route_remove_and_cancel(existing, link->manager);
if (r < 0)
return r;
@@ -291,18 +304,44 @@ static int ndisc_remove_route(Route *route, Link *link) {
if (r < 0)
return r;
- if (route->pref_set) {
- ndisc_set_route_priority(link, route);
- return route_remove_and_cancel(route, link->manager);
- }
-
- uint8_t pref;
+ uint8_t pref, pref_original = route->pref;
FOREACH_ARGUMENT(pref, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_MEDIUM, SD_NDISC_PREFERENCE_HIGH) {
+ Route *existing;
+ Request *req;
+
+ /* If the preference is specified by the user config (that is, for semi-static routes),
+ * rather than RA, then only search conflicting routes that have the same preference. */
+ if (route->pref_set && pref != pref_original)
+ continue;
+
route->pref = pref;
ndisc_set_route_priority(link, route);
- r = route_remove_and_cancel(route, link->manager);
- if (r < 0)
- return r;
+
+ /* Unfortunately, we cannot directly pass 'route' to route_remove_and_cancel() here, as the
+ * same or similar route may be configured or requested statically. */
+
+ /* First, check if the route is already requested. If there is an existing route, and also an
+ * existing pending request, then the source may be updated by the request. So, we first need
+ * to check the source of the requested route. */
+ if (route_get_request(link->manager, route, &req) >= 0) {
+ existing = ASSERT_PTR(req->userdata);
+ if (existing->source == NETWORK_CONFIG_SOURCE_STATIC)
+ continue;
+
+ r = route_remove_and_cancel(existing, link->manager);
+ if (r < 0)
+ return r;
+ }
+
+ /* Then, check if the route exists. */
+ if (route_get(link->manager, route, &existing) >= 0) {
+ if (existing->source == NETWORK_CONFIG_SOURCE_STATIC)
+ continue;
+
+ r = route_remove_and_cancel(existing, link->manager);
+ if (r < 0)
+ return r;
+ }
}
return 0;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 5842d3b..f8c34b5 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -5567,7 +5567,8 @@ static int run_container(
} else if (!isempty(arg_background))
(void) pty_forward_set_background_color(forward, arg_background);
- set_window_title(forward);
+ if (shall_set_terminal_title())
+ set_window_title(forward);
break;
default:
diff --git a/src/partition/repart.c b/src/partition/repart.c
index 8f64520..f87a87e 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -2562,7 +2562,7 @@ static int context_load_partition_table(Context *context) {
if (IN_SET(arg_empty, EMPTY_REQUIRE, EMPTY_FORCE, EMPTY_CREATE) && S_ISREG(st.st_mode))
/* Don't probe sector size from partition table if we are supposed to start from an empty disk */
- fs_secsz = ssz = 512;
+ ssz = 512;
else {
/* Auto-detect sector size if not specified. */
r = probe_sector_size_prefer_ioctl(context->backing_fd, &ssz);
@@ -2572,8 +2572,10 @@ static int context_load_partition_table(Context *context) {
/* If we found the sector size and we're operating on a block device, use it as the file
* system sector size as well, as we know its the sector size of the actual block device and
* not just the offset at which we found the GPT header. */
- if (r > 0 && S_ISBLK(st.st_mode))
+ if (r > 0 && S_ISBLK(st.st_mode)) {
+ log_debug("Probed sector size of %s is %" PRIu32 " bytes.", context->node, ssz);
fs_secsz = ssz;
+ }
}
r = fdisk_save_user_sector_size(c, /* phy= */ 0, ssz);
@@ -2637,7 +2639,7 @@ static int context_load_partition_table(Context *context) {
* larger */
grainsz = secsz < 4096 ? 4096 : secsz;
- log_debug("Sector size of device is %lu bytes. Using grain size of %" PRIu64 ".", secsz, grainsz);
+ log_debug("Sector size of device is %lu bytes. Using filesystem sector size of %" PRIu64 " and grain size of %" PRIu64 ".", secsz, fs_secsz, grainsz);
switch (arg_empty) {
@@ -6902,26 +6904,38 @@ static int help(void) {
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...] [DEVICE]\n"
- "\n%sGrow and add partitions to partition table.%s\n\n"
+ printf("%1$s [OPTIONS...] [DEVICE]\n"
+ "\n%5$sGrow and add partitions to a partition table, and generate disk images (DDIs).%6$s\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"
+ "\n%3$sOperation:%4$s\n"
" --dry-run=BOOL Whether to run dry-run operation\n"
" --empty=MODE One of refuse, allow, require, force, create; controls\n"
" how to handle empty disks lacking partition tables\n"
+ " --offline=BOOL Whether to build the image offline\n"
" --discard=BOOL Whether to discard backing blocks for new partitions\n"
+ " --sector-size=SIZE Set the logical sector size for the image\n"
+ " --architecture=ARCH Set the generic architecture for the image\n"
+ " --size=BYTES Grow loopback file to specified size\n"
+ " --seed=UUID 128-bit seed UUID to derive all UUIDs from\n"
+ " --split=BOOL Whether to generate split artifacts\n"
+ "\n%3$sOutput:%4$s\n"
" --pretty=BOOL Whether to show pretty summary before doing changes\n"
+ " --json=pretty|short|off\n"
+ " Generate JSON output\n"
+ "\n%3$sFactory Reset:%4$s\n"
" --factory-reset=BOOL Whether to remove data partitions before recreating\n"
" them\n"
" --can-factory-reset Test whether factory reset is defined\n"
+ "\n%3$sConfiguration & Image Control:%4$s\n"
" --root=PATH Operate relative to root path\n"
" --image=PATH Operate relative to image file\n"
" --image-policy=POLICY\n"
" Specify disk image dissection policy\n"
" --definitions=DIR Find partition definitions in specified directory\n"
- " --key-file=PATH Key to use when encrypting partitions\n"
+ "\n%3$sVerity:%4$s\n"
" --private-key=PATH|URI\n"
" Private key to use when generating verity roothash\n"
" signatures, or an engine or provider specific\n"
@@ -6932,6 +6946,8 @@ static int help(void) {
" verity roothash signatures\n"
" --certificate=PATH PEM certificate to use when generating verity\n"
" roothash signatures\n"
+ "\n%3$sEncryption:%4$s\n"
+ " --key-file=PATH Key to use when encrypting partitions\n"
" --tpm2-device=PATH Path to TPM2 device node to use\n"
" --tpm2-device-key=PATH\n"
" Enroll a TPM2 device using its public key\n"
@@ -6945,11 +6961,7 @@ static int help(void) {
" Enroll signed TPM2 PCR policy for specified TPM2 PCRs\n"
" --tpm2-pcrlock=PATH\n"
" Specify pcrlock policy to lock against\n"
- " --seed=UUID 128-bit seed UUID to derive all UUIDs from\n"
- " --size=BYTES Grow loopback file to specified size\n"
- " --json=pretty|short|off\n"
- " Generate JSON output\n"
- " --split=BOOL Whether to generate split artifacts\n"
+ "\n%3$sPartition Control:%4$s\n"
" --include-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
" Ignore partitions not of the specified types\n"
" --exclude-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
@@ -6957,23 +6969,25 @@ static int help(void) {
" --defer-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
" Take partitions of the specified types into account\n"
" but don't populate them yet\n"
- " --sector-size=SIZE Set the logical sector size for the image\n"
- " --architecture=ARCH Set the generic architecture for the image\n"
- " --offline=BOOL Whether to build the image offline\n"
+ "\n%3$sCopying:%4$s\n"
" -s --copy-source=PATH Specify the primary source tree to copy files from\n"
" --copy-from=IMAGE Copy partitions from the given image(s)\n"
+ "\n%3$sDDI Profile:%4$s\n"
" -S --make-ddi=sysext Make a system extension DDI\n"
" -C --make-ddi=confext Make a configuration extension DDI\n"
" -P --make-ddi=portable Make a portable service DDI\n"
+ "\n%3$sAuxiliary Resource Generation:%4$s\n"
" --generate-fstab=PATH\n"
" Write fstab configuration to the given path\n"
" --generate-crypttab=PATH\n"
" Write crypttab configuration to the given path\n"
- "\nSee the %s for details.\n",
+ "\nSee the %2$s for details.\n",
program_invocation_short_name,
- ansi_highlight(),
+ link,
+ ansi_underline(),
ansi_normal(),
- link);
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index e626740..e446461 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -1804,9 +1804,9 @@ int dns_packet_read_rr(
if (r < 0)
return r;
- /* RFC 2181, Section 8, suggests to
- * treat a TTL with the MSB set as a zero TTL. */
- if (rr->ttl & UINT32_C(0x80000000))
+ /* RFC 2181, Section 8, suggests to treat a TTL with the MSB set as a zero TTL. We avoid doing this
+ * for OPT records so that all 8 bits of the extended RCODE may be used .*/
+ if (key->type != DNS_TYPE_OPT && rr->ttl & UINT32_C(0x80000000))
rr->ttl = 0;
r = dns_packet_read_uint16(p, &rdlength, NULL);
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index 393b7b2..1b649af 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -117,7 +117,7 @@ static inline uint16_t DNS_PACKET_RCODE(DnsPacket *p) {
uint16_t rcode;
if (p->opt)
- rcode = (uint16_t) (p->opt->ttl >> 24);
+ rcode = (uint16_t) ((p->opt->ttl >> 20) & 0xFF0);
else
rcode = 0;
diff --git a/src/run/run.c b/src/run/run.c
index 5779403..ba7bb21 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -1848,7 +1848,8 @@ static int start_transient_service(sd_bus *bus) {
if (!isempty(arg_background))
(void) pty_forward_set_background_color(c.forward, arg_background);
- set_window_title(c.forward);
+ if (shall_set_terminal_title())
+ set_window_title(c.forward);
}
path = unit_dbus_path_from_name(service);
diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
index 0382d0b..58cffb6 100644
--- a/src/shared/bus-polkit.c
+++ b/src/shared/bus-polkit.c
@@ -786,11 +786,13 @@ int varlink_verify_polkit_async_full(
if (r != 0)
log_debug("Found matching previous polkit authentication for '%s'.", action);
if (r < 0) {
- /* Reply with a nice error */
- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED))
- (void) varlink_error(link, VARLINK_ERROR_INTERACTIVE_AUTHENTICATION_REQUIRED, NULL);
- else if (ERRNO_IS_NEG_PRIVILEGE(r))
- (void) varlink_error(link, VARLINK_ERROR_PERMISSION_DENIED, NULL);
+ if (!FLAGS_SET(flags, POLKIT_DONT_REPLY)) {
+ /* Reply with a nice error */
+ if (sd_bus_error_has_name(&error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED))
+ (void) varlink_error(link, VARLINK_ERROR_INTERACTIVE_AUTHENTICATION_REQUIRED, NULL);
+ else if (ERRNO_IS_NEG_PRIVILEGE(r))
+ (void) varlink_error(link, VARLINK_ERROR_PERMISSION_DENIED, NULL);
+ }
return r;
}
diff --git a/src/shared/bus-polkit.h b/src/shared/bus-polkit.h
index f3741b2..e0999bc 100644
--- a/src/shared/bus-polkit.h
+++ b/src/shared/bus-polkit.h
@@ -11,6 +11,7 @@ typedef enum PolkitFLags {
POLKIT_ALLOW_INTERACTIVE = 1 << 0, /* Allow interactive auth (typically not required, because can be derived from bus message/link automatically) */
POLKIT_ALWAYS_QUERY = 1 << 1, /* Query polkit even if client is privileged */
POLKIT_DEFAULT_ALLOW = 1 << 2, /* If polkit is not around, assume "allow" rather than the usual "deny" */
+ POLKIT_DONT_REPLY = 1 << 3, /* Varlink: don't immediately propagate polkit error to the Varlink client */
} PolkitFlags;
int bus_test_polkit(sd_bus_message *call, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e);
diff --git a/src/shared/condition.c b/src/shared/condition.c
index b53b2ef..1f72ba8 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -1009,6 +1009,7 @@ static int condition_test_psi(Condition *c, char **env) {
loadavg_t *current, limit;
ResourcePressure pressure;
int r;
+ PressureType preferred_pressure_type = PRESSURE_TYPE_FULL;
assert(c);
assert(c->parameter);
@@ -1029,6 +1030,10 @@ static int condition_test_psi(Condition *c, char **env) {
return log_debug_errno(r < 0 ? r : SYNTHETIC_ERRNO(EINVAL), "Failed to parse condition parameter %s: %m", c->parameter);
/* If only one parameter is passed, then we look at the global system pressure rather than a specific cgroup. */
if (r == 1) {
+ /* cpu.pressure 'full' is reported but undefined at system level */
+ if(c->type == CONDITION_CPU_PRESSURE)
+ preferred_pressure_type = PRESSURE_TYPE_SOME;
+
pressure_path = path_join("/proc/pressure", pressure_type);
if (!pressure_path)
return log_oom_debug();
@@ -1133,8 +1138,9 @@ static int condition_test_psi(Condition *c, char **env) {
if (r < 0)
return log_debug_errno(r, "Failed to parse loadavg: %s", c->parameter);
- r = read_resource_pressure(pressure_path, PRESSURE_TYPE_FULL, &pressure);
- if (r == -ENODATA) /* cpu.pressure 'full' was added recently, fall back to 'some'. */
+ r = read_resource_pressure(pressure_path, preferred_pressure_type, &pressure);
+ /* cpu.pressure 'full' was recently added at cgroup level, fall back to 'some' */
+ if (r == -ENODATA && preferred_pressure_type == PRESSURE_TYPE_FULL)
r = read_resource_pressure(pressure_path, PRESSURE_TYPE_SOME, &pressure);
if (r == -ENOENT) {
/* We already checked that /proc/pressure exists, so this means we were given a cgroup
diff --git a/src/shared/mkfs-util.c b/src/shared/mkfs-util.c
index 4d44012..14bf82b 100644
--- a/src/shared/mkfs-util.c
+++ b/src/shared/mkfs-util.c
@@ -461,6 +461,15 @@ int make_filesystem(
if (quiet)
stdio_fds[1] = -EBADF;
+ if (sector_size > 0) {
+ if (strv_extend(&argv, "--sectorsize") < 0)
+ return log_oom();
+
+ /* mkfs.btrfs expects a sector size of at least 4k bytes. */
+ if (strv_extendf(&argv, "%"PRIu64, MAX(sector_size, 4 * U64_KB)) < 0)
+ return log_oom();
+ }
+
} else if (streq(fstype, "f2fs")) {
argv = strv_new(mkfs,
"-g", /* "default options" */
diff --git a/src/shared/parse-helpers.c b/src/shared/parse-helpers.c
index ca6842d..63f592d 100644
--- a/src/shared/parse-helpers.c
+++ b/src/shared/parse-helpers.c
@@ -10,6 +10,22 @@
#include "path-util.h"
#include "utf8.h"
+static bool validate_api_vfs(const char *path, PathSimplifyWarnFlags flags) {
+
+ assert(path);
+
+ if ((flags & (PATH_CHECK_NON_API_VFS|PATH_CHECK_NON_API_VFS_DEV_OK)) == 0)
+ return true;
+
+ if (!path_below_api_vfs(path))
+ return true;
+
+ if (FLAGS_SET(flags, PATH_CHECK_NON_API_VFS_DEV_OK) && path_startswith(path, "/dev"))
+ return true;
+
+ return false;
+}
+
int path_simplify_and_warn(
char *path,
PathSimplifyWarnFlags flags,
@@ -23,6 +39,7 @@ int path_simplify_and_warn(
assert(path);
assert(!FLAGS_SET(flags, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
+ assert(!FLAGS_SET(flags, PATH_CHECK_NON_API_VFS | PATH_CHECK_NON_API_VFS_DEV_OK));
assert(lvalue);
if (!utf8_is_valid(path))
@@ -56,7 +73,7 @@ int path_simplify_and_warn(
"%s= path is not normalized%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
- if (FLAGS_SET(flags, PATH_CHECK_NON_API_VFS) && path_below_api_vfs(path))
+ if (!validate_api_vfs(path, flags))
return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is below API VFS%s: %s",
lvalue, fatal ? ", refusing" : ", ignoring",
diff --git a/src/shared/parse-helpers.h b/src/shared/parse-helpers.h
index 6d1034b..29ab60f 100644
--- a/src/shared/parse-helpers.h
+++ b/src/shared/parse-helpers.h
@@ -4,11 +4,12 @@
#include <stdint.h>
typedef enum PathSimplifyWarnFlags {
- PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
- PATH_CHECK_ABSOLUTE = 1 << 1,
- PATH_CHECK_RELATIVE = 1 << 2,
- PATH_KEEP_TRAILING_SLASH = 1 << 3,
- PATH_CHECK_NON_API_VFS = 1 << 4,
+ PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
+ PATH_CHECK_ABSOLUTE = 1 << 1,
+ PATH_CHECK_RELATIVE = 1 << 2,
+ PATH_KEEP_TRAILING_SLASH = 1 << 3,
+ PATH_CHECK_NON_API_VFS = 1 << 4,
+ PATH_CHECK_NON_API_VFS_DEV_OK = 1 << 5,
} PathSimplifyWarnFlags;
int path_simplify_and_warn(
diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c
index c75f74a..4692a6a 100644
--- a/src/shared/pretty-print.c
+++ b/src/shared/pretty-print.c
@@ -17,6 +17,7 @@
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
+#include "utf8.h"
void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
char *p = buffer;
@@ -467,8 +468,8 @@ void draw_progress_bar(const char *prefix, double percentage) {
if (!terminal_is_dumb()) {
size_t cols = columns();
- size_t prefix_length = strlen_ptr(prefix);
- size_t length = cols > prefix_length + 6 ? cols - prefix_length - 6 : 0;
+ size_t prefix_width = utf8_console_width(prefix);
+ size_t length = cols > prefix_width + 6 ? cols - prefix_width - 6 : 0;
if (length > 5 && percentage >= 0.0 && percentage <= 100.0) {
size_t p = (size_t) (length * percentage / 100.0);
@@ -519,7 +520,7 @@ void clear_progress_bar(const char *prefix) {
fputc('\r', stderr);
if (terminal_is_dumb())
- fputs(strrepa(" ", strlen_ptr(prefix) + 4), /* 4: %3.0f%% */
+ fputs(strrepa(" ", utf8_console_width(prefix) + 4), /* 4: %3.0f%% */
stderr);
else
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 998ce96..842aef9 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -17,6 +17,7 @@
#include "sd-event.h"
#include "alloc-util.h"
+#include "env-util.h"
#include "errno-util.h"
#include "extract-word.h"
#include "fd-util.h"
@@ -367,6 +368,21 @@ static int insert_background_fix(PTYForward *f, size_t offset) {
return insert_string(f, offset, s);
}
+bool shall_set_terminal_title(void) {
+ static int cache = -1;
+
+ if (cache >= 0)
+ return cache;
+
+ cache = getenv_bool("SYSTEMD_ADJUST_TERMINAL_TITLE");
+ if (cache == -ENXIO)
+ return (cache = true);
+ if (cache < 0)
+ log_debug_errno(cache, "Failed to parse $SYSTEMD_ADJUST_TERMINAL_TITLE, leaving terminal title setting enabled: %m");
+
+ return cache != 0;
+}
+
static int insert_window_title_fix(PTYForward *f, size_t offset) {
assert(f);
diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h
index 248646d..b86027e 100644
--- a/src/shared/ptyfwd.h
+++ b/src/shared/ptyfwd.h
@@ -50,4 +50,6 @@ int pty_forward_set_titlef(PTYForward *f, const char *format, ...) _printf_(2,3)
int pty_forward_set_title_prefix(PTYForward *f, const char *prefix);
+bool shall_set_terminal_title(void);
+
DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free);
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 2469e24..d31d6b4 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -2030,39 +2030,43 @@ int parse_syscall_archs(char **l, Set **ret_archs) {
return 0;
}
-int seccomp_filter_set_add(Hashmap *filter, bool add, const SyscallFilterSet *set) {
- int r;
+int seccomp_filter_set_add_by_name(Hashmap *filter, bool add, const char *name) {
+ assert(filter);
+ assert(name);
- assert(set);
+ if (name[0] == '@') {
+ const SyscallFilterSet *more;
- NULSTR_FOREACH(i, set->value) {
+ more = syscall_filter_set_find(name);
+ if (!more)
+ return -ENXIO;
- if (i[0] == '@') {
- const SyscallFilterSet *more;
+ return seccomp_filter_set_add(filter, add, more);
+ }
- more = syscall_filter_set_find(i);
- if (!more)
- return -ENXIO;
+ int id = seccomp_syscall_resolve_name(name);
+ if (id == __NR_SCMP_ERROR) {
+ log_debug("System call %s is not known, ignoring.", name);
+ return 0;
+ }
- r = seccomp_filter_set_add(filter, add, more);
- if (r < 0)
- return r;
- } else {
- int id;
+ if (add)
+ return hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(-1));
- id = seccomp_syscall_resolve_name(i);
- if (id == __NR_SCMP_ERROR) {
- log_debug("System call %s is not known, ignoring.", i);
- continue;
- }
+ (void) hashmap_remove(filter, INT_TO_PTR(id + 1));
+ return 0;
+}
- if (add) {
- r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(-1));
- if (r < 0)
- return r;
- } else
- (void) hashmap_remove(filter, INT_TO_PTR(id + 1));
- }
+int seccomp_filter_set_add(Hashmap *filter, bool add, const SyscallFilterSet *set) {
+ int r;
+
+ assert(filter);
+ assert(set);
+
+ NULSTR_FOREACH(i, set->value) {
+ r = seccomp_filter_set_add_by_name(filter, add, i);
+ if (r < 0)
+ return r;
}
return 0;
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index 7583357..7be1117 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -70,6 +70,7 @@ extern const SyscallFilterSet syscall_filter_sets[];
const SyscallFilterSet *syscall_filter_set_find(const char *name);
+int seccomp_filter_set_add_by_name(Hashmap *s, bool b, const char *name);
int seccomp_filter_set_add(Hashmap *s, bool b, const SyscallFilterSet *set);
int seccomp_add_syscall_filter_item(
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 52f4a47..5fe3b0c 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1051,7 +1051,7 @@ static int uid_is_ok(
if (r >= 0)
return 0;
if (r != -ESRCH)
- return r;
+ log_warning_errno(r, "Unexpected failure while looking up UID '" UID_FMT "' via NSS, assuming it doesn't exist: %m", uid);
if (check_with_gid) {
r = getgrgid_malloc((gid_t) uid, &g);
@@ -1059,7 +1059,7 @@ static int uid_is_ok(
if (!streq(g->gr_name, name))
return 0;
} else if (r != -ESRCH)
- return r;
+ log_warning_errno(r, "Unexpected failure while looking up GID '" GID_FMT "' via NSS, assuming it doesn't exist: %m", uid);
}
}
@@ -1164,7 +1164,7 @@ static int add_user(Context *c, Item *i) {
return 0;
}
if (r != -ESRCH)
- return log_error_errno(r, "Failed to check if user %s already exists: %m", i->name);
+ log_warning_errno(r, "Unexpected failure while looking up user '%s' via NSS, assuming it doesn't exist: %m", i->name);
}
/* Try to use the suggested numeric UID */
@@ -1284,14 +1284,14 @@ static int gid_is_ok(
if (r >= 0)
return 0;
if (r != -ESRCH)
- return r;
+ log_warning_errno(r, "Unexpected failure while looking up GID '" GID_FMT "' via NSS, assuming it doesn't exist: %m", gid);
if (check_with_uid) {
r = getpwuid_malloc(gid, /* ret= */ NULL);
if (r >= 0)
return 0;
if (r != -ESRCH)
- return r;
+ log_warning_errno(r, "Unexpected failure while looking up GID '" GID_FMT "' via NSS, assuming it doesn't exist: %m", gid);
}
}
@@ -1326,7 +1326,7 @@ static int get_gid_by_name(
return 0;
}
if (r != -ESRCH)
- return log_error_errno(r, "Failed to check if group %s already exists: %m", name);
+ log_warning_errno(r, "Unexpected failure while looking up group '%s' via NSS, assuming it doesn't exist: %m", name);
}
return -ENOENT;
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 8bd4af9..040e9e9 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -159,6 +159,8 @@ TEST(id) {
if (ERRNO_IS_NEG_PRIVILEGE(fd2))
log_notice("Skipping open-by-cgroup-id test because lacking privs.");
+ else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2))
+ log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked.");
else {
assert_se(fd2 >= 0);
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 4b8daa4..56f5e34 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -832,6 +832,8 @@ static void test_exec_systemcallfilter(Manager *m) {
return;
}
+ test(m, "exec-systemcallfilter-writing-handoff-timestamp.service", 0, CLD_EXITED);
+
test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-not-failing3.service", 0, CLD_EXITED);
diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c
index 85c0859..07c0480 100644
--- a/src/test/test-mountpoint-util.c
+++ b/src/test/test-mountpoint-util.c
@@ -10,6 +10,7 @@
#include "fileio.h"
#include "hashmap.h"
#include "log.h"
+#include "missing_syscall.h"
#include "mountpoint-util.h"
#include "path-util.h"
#include "rm-rf.h"
@@ -317,6 +318,35 @@ TEST(fd_is_mount_point) {
r = fd_is_mount_point(fd, NULL, 0);
assert_se(IN_SET(r, 0, -ENOTDIR)); /* on old kernels we can't determine if regular files are mount points if we have no directory fd */
assert_se(fd_is_mount_point(fd, "", 0) == -EINVAL);
+
+ if (!mount_new_api_supported())
+ return;
+
+ /* Symlinks can be mount points with new mount API */
+ _cleanup_close_ int mfd = -EBADF, rfd = -EBADF;
+ _cleanup_free_ char *t = NULL;
+ struct stat st;
+
+ safe_close(fd);
+ ASSERT_OK_ERRNO(fd = open(tmpdir, O_DIRECTORY|O_PATH|O_CLOEXEC));
+
+ ASSERT_OK_ERRNO(symlinkat("/usr", fd, "symlink"));
+
+ mfd = open_tree(fd, "symlink", AT_SYMLINK_NOFOLLOW|OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC);
+ if (mfd < 0 && ERRNO_IS_PRIVILEGE(errno))
+ return;
+ ASSERT_OK_ERRNO(mfd);
+
+ ASSERT_OK_ERRNO(rfd = openat(fd, "regular", O_CLOEXEC|O_CREAT|O_EXCL, 0644));
+
+ ASSERT_OK_ERRNO(move_mount(mfd, "", rfd, "", MOVE_MOUNT_F_EMPTY_PATH|MOVE_MOUNT_T_EMPTY_PATH));
+
+ ASSERT_OK_ERRNO(fstatat(fd, "regular", &st, AT_SYMLINK_NOFOLLOW));
+ ASSERT_OK(stat_verify_symlink(&st));
+ ASSERT_OK(readlinkat_malloc(fd, "regular", &t));
+ ASSERT_STREQ(t, "/usr");
+
+ ASSERT_OK(fd_is_mount_point(fd, "regular", 0));
}
TEST(ms_nosymfollow_supported) {
diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
index f1db9ba..75e4286 100755
--- a/src/ukify/ukify.py
+++ b/src/ukify/ukify.py
@@ -51,7 +51,7 @@ from typing import (Any,
import pefile # type: ignore
-__version__ = '{{PROJECT_VERSION_FULL}} ({{VERSION_TAG}})'
+__version__ = '{{PROJECT_VERSION}} ({{VERSION_TAG}})'
EFI_ARCH_MAP = {
# host_arch glob : [efi_arch, 32_bit_efi_arch if mixed mode is supported]
diff --git a/src/vmspawn/vmspawn-util.h b/src/vmspawn/vmspawn-util.h
index fed0996..ee02752 100644
--- a/src/vmspawn/vmspawn-util.h
+++ b/src/vmspawn/vmspawn-util.h
@@ -34,7 +34,7 @@
#if defined(__x86_64__) || defined(__i386__)
# define QEMU_MACHINE_TYPE "q35"
-#elif defined(__arm__) || defined(__aarch64__)
+#elif defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch64)
# define QEMU_MACHINE_TYPE "virt"
#elif defined(__s390__) || defined(__s390x__)
# define QEMU_MACHINE_TYPE "s390-ccw-virtio"
diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c
index 326722d..8f15d04 100644
--- a/src/vmspawn/vmspawn.c
+++ b/src/vmspawn/vmspawn.c
@@ -2141,7 +2141,8 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
} else if (!isempty(arg_background))
(void) pty_forward_set_background_color(forward, arg_background);
- set_window_title(forward);
+ if (shall_set_terminal_title())
+ set_window_title(forward);
}
r = sd_event_loop(event);