diff options
Diffstat (limited to 'src')
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), - ¶m); + 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); |