diff options
-rw-r--r-- | .github/workflows/make_release.yml | 8 | ||||
-rw-r--r-- | src/analyze/analyze-blame.c | 2 | ||||
-rw-r--r-- | src/analyze/analyze-critical-chain.c | 6 | ||||
-rw-r--r-- | src/analyze/analyze-plot.c | 4 | ||||
-rw-r--r-- | src/analyze/analyze-time-data.c | 45 | ||||
-rw-r--r-- | src/analyze/analyze-time-data.h | 4 | ||||
-rw-r--r-- | src/basic/chase.c | 68 | ||||
-rw-r--r-- | src/basic/chase.h | 5 | ||||
-rw-r--r-- | src/basic/fd-util.c | 20 | ||||
-rw-r--r-- | src/basic/fileio.c | 11 | ||||
-rw-r--r-- | src/basic/fileio.h | 5 | ||||
-rw-r--r-- | src/basic/path-util.c | 8 | ||||
-rw-r--r-- | src/boot/bootctl-uki.c | 6 | ||||
-rw-r--r-- | src/shared/kernel-image.c | 9 | ||||
-rw-r--r-- | src/shared/kernel-image.h | 1 | ||||
-rw-r--r-- | src/test/test-path-util.c | 27 | ||||
-rwxr-xr-x | test/units/testsuite-01.sh | 6 | ||||
-rwxr-xr-x | test/units/testsuite-65.sh | 6 |
18 files changed, 154 insertions, 87 deletions
diff --git a/.github/workflows/make_release.yml b/.github/workflows/make_release.yml index 47dbbea374..c789d33f16 100644 --- a/.github/workflows/make_release.yml +++ b/.github/workflows/make_release.yml @@ -5,14 +5,20 @@ on: tags: - "v*" +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest + permissions: + contents: write + if: ${{ github.repository_owner == 'systemd' }} steps: - name: Checkout uses: actions/checkout@v3 - name: Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 with: prerelease: ${{ contains(github.ref_name, '-rc') }} draft: ${{ github.repository == 'systemd/systemd' }} diff --git a/src/analyze/analyze-blame.c b/src/analyze/analyze-blame.c index c9112685f8..81e5c590b9 100644 --- a/src/analyze/analyze-blame.c +++ b/src/analyze/analyze-blame.c @@ -16,7 +16,7 @@ int verb_blame(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_connect_error(r, arg_transport); - n = acquire_time_data(bus, ×); + n = acquire_time_data(bus, /* require_finished = */ false, ×); if (n <= 0) return n; diff --git a/src/analyze/analyze-critical-chain.c b/src/analyze/analyze-critical-chain.c index f782f95d5f..f80f3ddb63 100644 --- a/src/analyze/analyze-critical-chain.c +++ b/src/analyze/analyze-critical-chain.c @@ -93,7 +93,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level, typesafe_qsort(deps, strv_length(deps), list_dependencies_compare); - r = acquire_boot_times(bus, &boot); + r = acquire_boot_times(bus, /* require_finished = */ true, &boot); if (r < 0) return r; @@ -178,7 +178,7 @@ static int list_dependencies(sd_bus *bus, const char *name) { times = hashmap_get(unit_times_hashmap, id); - r = acquire_boot_times(bus, &boot); + r = acquire_boot_times(bus, /* require_finished = */ true, &boot); if (r < 0) return r; @@ -205,7 +205,7 @@ int verb_critical_chain(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_connect_error(r, arg_transport); - n = acquire_time_data(bus, ×); + n = acquire_time_data(bus, /* require_finished = */ true, ×); if (n <= 0) return n; diff --git a/src/analyze/analyze-plot.c b/src/analyze/analyze-plot.c index e44b9c11f6..ef40e64631 100644 --- a/src/analyze/analyze-plot.c +++ b/src/analyze/analyze-plot.c @@ -439,7 +439,7 @@ int verb_plot(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_connect_error(r, arg_transport); - n = acquire_boot_times(bus, &boot); + n = acquire_boot_times(bus, /* require_finished = */ true, &boot); if (n < 0) return n; @@ -453,7 +453,7 @@ int verb_plot(int argc, char *argv[], void *userdata) { return n; } - n = acquire_time_data(bus, ×); + n = acquire_time_data(bus, /* require_finished = */ true, ×); if (n <= 0) return n; diff --git a/src/analyze/analyze-time-data.c b/src/analyze/analyze-time-data.c index 07843f74bc..baee3cedbb 100644 --- a/src/analyze/analyze-time-data.c +++ b/src/analyze/analyze-time-data.c @@ -17,7 +17,16 @@ static void subtract_timestamp(usec_t *a, usec_t b) { } } -int acquire_boot_times(sd_bus *bus, BootTimes **ret) { +static int log_not_finished(usec_t finish_time) { + return log_error_errno(SYNTHETIC_ERRNO(EINPROGRESS), + "Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" + "Please try again later.\n" + "Hint: Use 'systemctl%s list-jobs' to see active jobs", + finish_time, + arg_runtime_scope == RUNTIME_SCOPE_SYSTEM ? "" : " --user"); +} + +int acquire_boot_times(sd_bus *bus, bool require_finished, BootTimes **ret) { static const struct bus_properties_map property_map[] = { { "FirmwareTimestampMonotonic", "t", NULL, offsetof(BootTimes, firmware_time) }, { "LoaderTimestampMonotonic", "t", NULL, offsetof(BootTimes, loader_time) }, @@ -44,8 +53,14 @@ int acquire_boot_times(sd_bus *bus, BootTimes **ret) { static bool cached = false; int r; - if (cached) - goto finish; + if (cached) { + if (require_finished && times.finish_time <= 0) + return log_not_finished(times.finish_time); + + if (ret) + *ret = × + return 0; + } assert_cc(sizeof(usec_t) == sizeof(uint64_t)); @@ -61,13 +76,8 @@ int acquire_boot_times(sd_bus *bus, BootTimes **ret) { if (r < 0) return log_error_errno(r, "Failed to get timestamp properties: %s", bus_error_message(&error, r)); - if (times.finish_time <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EINPROGRESS), - "Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" - "Please try again later.\n" - "Hint: Use 'systemctl%s list-jobs' to see active jobs", - times.finish_time, - arg_runtime_scope == RUNTIME_SCOPE_SYSTEM ? "" : " --user"); + if (require_finished && times.finish_time <= 0) + return log_not_finished(times.finish_time); if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM && times.security_start_time > 0) { /* security_start_time is set when systemd is not running under container environment. */ @@ -85,7 +95,8 @@ int acquire_boot_times(sd_bus *bus, BootTimes **ret) { times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = times.userspace_time = times.security_start_time = times.security_finish_time = 0; - subtract_timestamp(×.finish_time, times.reverse_offset); + if (times.finish_time > 0) + subtract_timestamp(×.finish_time, times.reverse_offset); subtract_timestamp(×.generators_start_time, times.reverse_offset); subtract_timestamp(×.generators_finish_time, times.reverse_offset); @@ -96,8 +107,8 @@ int acquire_boot_times(sd_bus *bus, BootTimes **ret) { cached = true; -finish: - *ret = × + if (ret) + *ret = × return 0; } @@ -132,7 +143,7 @@ int pretty_boot_time(sd_bus *bus, char **ret) { BootTimes *t; int r; - r = acquire_boot_times(bus, &t); + r = acquire_boot_times(bus, /* require_finished = */ true, &t); if (r < 0) return r; @@ -214,7 +225,7 @@ UnitTimes* unit_times_free_array(UnitTimes *t) { return mfree(t); } -int acquire_time_data(sd_bus *bus, UnitTimes **out) { +int acquire_time_data(sd_bus *bus, bool require_finished, UnitTimes **out) { static const struct bus_properties_map property_map[] = { { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activating) }, { "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activated) }, @@ -225,12 +236,12 @@ int acquire_time_data(sd_bus *bus, UnitTimes **out) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(unit_times_free_arrayp) UnitTimes *unit_times = NULL; - BootTimes *boot_times = NULL; + BootTimes *boot_times; size_t c = 0; UnitInfo u; int r; - r = acquire_boot_times(bus, &boot_times); + r = acquire_boot_times(bus, require_finished, &boot_times); if (r < 0) return r; diff --git a/src/analyze/analyze-time-data.h b/src/analyze/analyze-time-data.h index 02ee16a714..79240745cb 100644 --- a/src/analyze/analyze-time-data.h +++ b/src/analyze/analyze-time-data.h @@ -47,10 +47,10 @@ typedef struct UnitTimes { usec_t time; } UnitTimes; -int acquire_boot_times(sd_bus *bus, BootTimes **ret); +int acquire_boot_times(sd_bus *bus, bool require_finished, BootTimes **ret); int pretty_boot_time(sd_bus *bus, char **ret); UnitTimes* unit_times_free_array(UnitTimes *t); DEFINE_TRIVIAL_CLEANUP_FUNC(UnitTimes*, unit_times_free_array); -int acquire_time_data(sd_bus *bus, UnitTimes **out); +int acquire_time_data(sd_bus *bus, bool require_finished, UnitTimes **out); diff --git a/src/basic/chase.c b/src/basic/chase.c index 318454ca88..f62c317026 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -77,7 +77,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int _cleanup_close_ int fd = -EBADF, root_fd = -EBADF; unsigned max_follow = CHASE_MAX; /* how many symlinks to follow before giving up and returning ELOOP */ bool exists = true, append_trail_slash = false; - struct stat previous_stat; + struct stat st; /* stat obtained from fd */ const char *todo; int r; @@ -176,7 +176,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int /* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root * set and doesn't care about any of the other special features we provide either. */ - r = openat(dir_fd, buffer ?: path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); + r = openat(dir_fd, path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); if (r < 0) return -errno; @@ -184,11 +184,9 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int return 0; } - if (!buffer) { - buffer = strdup(path); - if (!buffer) - return -ENOMEM; - } + buffer = strdup(path); + if (!buffer) + return -ENOMEM; /* If we receive an absolute path together with AT_FDCWD, we need to return an absolute path, because * a relative path would be interpreted relative to the current working directory. */ @@ -220,7 +218,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int if (fd < 0) return -errno; - if (fstat(fd, &previous_stat) < 0) + if (fstat(fd, &st) < 0) return -errno; if (flags & CHASE_TRAIL_SLASH) @@ -229,7 +227,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int for (todo = buffer;;) { _cleanup_free_ char *first = NULL; _cleanup_close_ int child = -EBADF; - struct stat st; + struct stat st_child; const char *e; r = path_find_first_component(&todo, /* accept_dot_dot= */ true, &e); @@ -250,6 +248,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int if (path_equal(first, "..")) { _cleanup_free_ char *parent = NULL; _cleanup_close_ int fd_parent = -EBADF; + struct stat st_parent; /* If we already are at the top, then going up will not change anything. This is * in-line with how the kernel handles this. */ @@ -260,13 +259,19 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int if (fd_parent < 0) return -errno; - if (fstat(fd_parent, &st) < 0) + if (fstat(fd_parent, &st_parent) < 0) return -errno; - /* If we opened the same directory, that means we're at the host root directory, so + /* If we opened the same directory, that _may_ indicate that we're at the host root + * directory. Let's confirm that in more detail with dir_fd_is_root(). And if so, * going up won't change anything. */ - if (st.st_dev == previous_stat.st_dev && st.st_ino == previous_stat.st_ino) - continue; + if (stat_inode_same(&st_parent, &st)) { + r = dir_fd_is_root(fd); + if (r < 0) + return r; + if (r > 0) + continue; + } r = path_extract_directory(done, &parent); if (r >= 0 || r == -EDESTADDRREQ) @@ -281,18 +286,16 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int if (flags & CHASE_STEP) goto chased_one; - if (flags & CHASE_SAFE) { - if (unsafe_transition(&previous_stat, &st)) - return log_unsafe_transition(fd, fd_parent, path, flags); - - previous_stat = st; - } + if (flags & CHASE_SAFE && + unsafe_transition(&st, &st_parent)) + return log_unsafe_transition(fd, fd_parent, path, flags); if (FLAGS_SET(flags, CHASE_PARENT) && isempty(todo)) break; + /* update fd and stat */ + st = st_parent; close_and_replace(fd, fd_parent); - continue; } @@ -324,19 +327,18 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int return r; } - if (fstat(child, &st) < 0) + if (fstat(child, &st_child) < 0) return -errno; + if ((flags & CHASE_SAFE) && - unsafe_transition(&previous_stat, &st)) + unsafe_transition(&st, &st_child)) return log_unsafe_transition(fd, child, path, flags); - previous_stat = st; - if ((flags & CHASE_NO_AUTOFS) && fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0) return log_autofs_mount_point(child, path, flags); - if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { + if (S_ISLNK(st_child.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { _cleanup_free_ char *destination = NULL; if (flags & CHASE_PROHIBIT_SYMLINKS) @@ -363,15 +365,12 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int if (fd < 0) return fd; - if (flags & CHASE_SAFE) { - if (fstat(fd, &st) < 0) - return -errno; - - if (unsafe_transition(&previous_stat, &st)) - return log_unsafe_transition(child, fd, path, flags); + if (fstat(fd, &st) < 0) + return -errno; - previous_stat = st; - } + if (flags & CHASE_SAFE && + unsafe_transition(&st_child, &st)) + return log_unsafe_transition(child, fd, path, flags); r = free_and_strdup(&done, need_absolute ? "/" : NULL); if (r < 0) @@ -400,11 +399,12 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int break; /* And iterate again, but go one directory further down. */ + st = st_child; close_and_replace(fd, child); } if (flags & CHASE_PARENT) { - r = fd_verify_directory(fd); + r = stat_verify_directory(&st); if (r < 0) return r; } diff --git a/src/basic/chase.h b/src/basic/chase.h index 1314777cb4..7e9ebe0685 100644 --- a/src/basic/chase.h +++ b/src/basic/chase.h @@ -22,7 +22,9 @@ typedef enum ChaseFlags { CHASE_PROHIBIT_SYMLINKS = 1 << 9, /* Refuse all symlinks */ CHASE_PARENT = 1 << 10, /* Chase the parent directory of the given path. Note that the * full path is still stored in ret_path and only the returned - * file descriptor will point to the parent directory. */ + * file descriptor will point to the parent directory. Note that + * the result path is the root or '.', then the file descriptor + * also points to the result path even if this flag is set. */ CHASE_MKDIR_0755 = 1 << 11, /* Create any missing parent directories in the given path. */ CHASE_EXTRACT_FILENAME = 1 << 12, /* Only return the last component of the resolved path */ } ChaseFlags; @@ -51,4 +53,3 @@ int chase_and_accessat(int dir_fd, const char *path, ChaseFlags chase_flags, int int chase_and_fopenat_unlocked(int dir_fd, const char *path, ChaseFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file); int chase_and_unlinkat(int dir_fd, const char *path, ChaseFlags chase_flags, int unlink_flags, char **ret_path); int chase_and_open_parent_at(int dir_fd, const char *path, ChaseFlags chase_flags, char **ret_filename); - diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 3cc4f44bcd..7125e28e1b 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -903,6 +903,14 @@ int dir_fd_is_root(int dir_fd) { if (r < 0) return r; + r = statx_fallback(dir_fd, "..", 0, STATX_TYPE|STATX_INO|STATX_MNT_ID, &pst.sx); + if (r < 0) + return r; + + /* First, compare inode. If these are different, the fd does not point to the root directory "/". */ + if (!statx_inode_same(&st.sx, &pst.sx)) + return false; + if (!FLAGS_SET(st.nsx.stx_mask, STATX_MNT_ID)) { int mntid; @@ -915,10 +923,6 @@ int dir_fd_is_root(int dir_fd) { st.nsx.stx_mask |= STATX_MNT_ID; } - r = statx_fallback(dir_fd, "..", 0, STATX_TYPE|STATX_INO|STATX_MNT_ID, &pst.sx); - if (r < 0) - return r; - if (!FLAGS_SET(pst.nsx.stx_mask, STATX_MNT_ID)) { int mntid; @@ -931,14 +935,14 @@ int dir_fd_is_root(int dir_fd) { pst.nsx.stx_mask |= STATX_MNT_ID; } - /* If the parent directory is the same inode, the fd points to the root directory "/". We also check - * that the mount ids are the same. Otherwise, a construct like the following could be used to trick - * us: + /* Even if the parent directory has the same inode, the fd may not point to the root directory "/", + * and we also need to check that the mount ids are the same. Otherwise, a construct like the + * following could be used to trick us: * * $ mkdir /tmp/x /tmp/x/y * $ mount --bind /tmp/x /tmp/x/y */ - return statx_inode_same(&st.sx, &pst.sx) && statx_mount_same(&st.nsx, &pst.nsx); + return statx_mount_same(&st.nsx, &pst.nsx); } const char *accmode_to_string(int flags) { diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 2c28a7f6b3..48ffb4e5e6 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -339,18 +339,19 @@ int write_string_filef( return write_string_file(fn, p, flags); } -int read_one_line_file(const char *fn, char **line) { +int read_one_line_file_at(int dir_fd, const char *filename, char **ret) { _cleanup_fclose_ FILE *f = NULL; int r; - assert(fn); - assert(line); + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); + assert(filename); + assert(ret); - r = fopen_unlocked(fn, "re", &f); + r = fopen_unlocked_at(dir_fd, filename, "re", 0, &f); if (r < 0) return r; - return read_line(f, LONG_LINE_MAX, line); + return read_line(f, LONG_LINE_MAX, ret); } int verify_file_at(int dir_fd, const char *fn, const char *blob, bool accept_extra_nl) { diff --git a/src/basic/fileio.h b/src/basic/fileio.h index bda18fd066..769bf394fd 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -67,7 +67,10 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4); -int read_one_line_file(const char *filename, char **line); +int read_one_line_file_at(int dir_fd, const char *filename, char **ret); +static inline int read_one_line_file(const char *filename, char **ret) { + return read_one_line_file_at(AT_FDCWD, filename, ret); +} int read_full_file_full(int dir_fd, const char *filename, uint64_t offset, size_t size, ReadFullFileFlags flags, const char *bind_name, char **ret_contents, size_t *ret_size); static inline int read_full_file_at(int dir_fd, const char *filename, char **ret_contents, size_t *ret_size) { return read_full_file_full(dir_fd, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index a5ab6045cd..0b0f0da760 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -901,6 +901,8 @@ static const char *skip_slash_or_dot_backward(const char *path, const char *q) { continue; if (q > path && strneq(q - 1, "/.", 2)) continue; + if (q == path && *q == '.') + continue; break; } return q; @@ -925,6 +927,12 @@ int path_find_last_component(const char *path, bool accept_dot_dot, const char * * ret: "bbbbb/cc//././" * return value: 5 (== strlen("bbbbb")) * + * Input: path: "//.//aaa///bbbbb/cc//././" + * next: "///bbbbb/cc//././" + * Output: next: "//.//aaa///bbbbb/cc//././" (next == path) + * ret: "aaa///bbbbb/cc//././" + * return value: 3 (== strlen("aaa")) + * * Input: path: "/", ".", "", or NULL * Output: next: equivalent to path * ret: NULL diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c index 718bac5ab2..8808c30569 100644 --- a/src/boot/bootctl-uki.c +++ b/src/boot/bootctl-uki.c @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <fcntl.h> + #include "alloc-util.h" #include "bootctl-uki.h" #include "kernel-image.h" @@ -8,7 +10,7 @@ int verb_kernel_identify(int argc, char *argv[], void *userdata) { KernelImageType t; int r; - r = inspect_kernel(argv[1], &t, NULL, NULL, NULL); + r = inspect_kernel(AT_FDCWD, argv[1], &t, NULL, NULL, NULL); if (r < 0) return r; @@ -21,7 +23,7 @@ int verb_kernel_inspect(int argc, char *argv[], void *userdata) { KernelImageType t; int r; - r = inspect_kernel(argv[1], &t, &cmdline, &uname, &pname); + r = inspect_kernel(AT_FDCWD, argv[1], &t, &cmdline, &uname, &pname); if (r < 0) return r; diff --git a/src/shared/kernel-image.c b/src/shared/kernel-image.c index b5ea1bb2a0..3d2ec820d9 100644 --- a/src/shared/kernel-image.c +++ b/src/shared/kernel-image.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "fd-util.h" +#include "fileio.h" #include "env-file.h" #include "kernel-image.h" #include "os-util.h" @@ -255,6 +256,7 @@ static int inspect_uki( } int inspect_kernel( + int dir_fd, const char *filename, KernelImageType *ret_type, char **ret_cmdline, @@ -267,11 +269,12 @@ int inspect_kernel( KernelImageType t; int r; + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(filename); - f = fopen(filename, "re"); - if (!f) - return log_error_errno(errno, "Failed to open kernel image file '%s': %m", filename); + r = xfopenat(dir_fd, filename, "re", 0, &f); + if (r < 0) + return log_error_errno(r, "Failed to open kernel image file '%s': %m", filename); r = pe_sections(f, §ions, &scount); if (r < 0) diff --git a/src/shared/kernel-image.h b/src/shared/kernel-image.h index d1875920cc..41b2c08f9a 100644 --- a/src/shared/kernel-image.h +++ b/src/shared/kernel-image.h @@ -16,6 +16,7 @@ typedef enum KernelImageType { const char* kernel_image_type_to_string(KernelImageType t) _const_; int inspect_kernel( + int dir_fd, const char *filename, KernelImageType *ret_type, char **ret_cmdline, diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 87e33919e0..e40ffea4d5 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -676,9 +676,10 @@ static void test_path_find_first_component_one( r = path_find_first_component(&p, accept_dot_dot, &e); if (r <= 0) { if (r == 0) { - if (path) + if (path) { assert_se(p == path + strlen_ptr(path)); - else + assert_se(isempty(p)); + } else assert_se(!p); assert_se(!e); } @@ -691,6 +692,15 @@ static void test_path_find_first_component_one( assert_se(strcspn(e, "/") == (size_t) r); assert_se(strlen_ptr(*expected) == (size_t) r); assert_se(strneq(e, *expected++, r)); + + assert_se(p); + log_debug("p=%s", p); + if (!isempty(*expected)) + assert_se(startswith(p, *expected)); + else if (ret >= 0) { + assert_se(p == path + strlen_ptr(path)); + assert_se(isempty(p)); + } } } @@ -712,7 +722,7 @@ TEST(path_find_first_component) { test_path_find_first_component_one("././//.///aa/bbb//./ccc", false, STRV_MAKE("aa", "bbb", "ccc"), 0); test_path_find_first_component_one("././//.///aa/.../../bbb//./ccc/.", false, STRV_MAKE("aa", "..."), -EINVAL); test_path_find_first_component_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", false, STRV_MAKE("aaa", ".bbb"), -EINVAL); - test_path_find_first_component_one("a/foo./b", false, STRV_MAKE("a", "foo.", "b"), 0); + test_path_find_first_component_one("a/foo./b//././/", false, STRV_MAKE("a", "foo.", "b"), 0); test_path_find_first_component_one(NULL, true, NULL, 0); test_path_find_first_component_one("", true, NULL, 0); @@ -728,7 +738,7 @@ TEST(path_find_first_component) { test_path_find_first_component_one("././//.///aa/bbb//./ccc", true, STRV_MAKE("aa", "bbb", "ccc"), 0); test_path_find_first_component_one("././//.///aa/.../../bbb//./ccc/.", true, STRV_MAKE("aa", "...", "..", "bbb", "ccc"), 0); test_path_find_first_component_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", true, STRV_MAKE("aaa", ".bbb", "..", "c.", "d.dd", "..eeee"), 0); - test_path_find_first_component_one("a/foo./b", true, STRV_MAKE("a", "foo.", "b"), 0); + test_path_find_first_component_one("a/foo./b//././/", true, STRV_MAKE("a", "foo.", "b"), 0); memset(foo, 'a', sizeof(foo) -1); char_array_0(foo); @@ -770,6 +780,15 @@ static void test_path_find_last_component_one( assert_se(strcspn(e, "/") == (size_t) r); assert_se(strlen_ptr(*expected) == (size_t) r); assert_se(strneq(e, *expected++, r)); + + assert_se(next); + log_debug("path=%s\nnext=%s", path, next); + if (!isempty(*expected)) { + assert_se(next < path + strlen(path)); + assert_se(next >= path + strlen(*expected)); + assert_se(startswith(next - strlen(*expected), *expected)); + } else if (ret >= 0) + assert_se(next == path); } } diff --git a/test/units/testsuite-01.sh b/test/units/testsuite-01.sh index ebb8a78128..cd18a9fd74 100755 --- a/test/units/testsuite-01.sh +++ b/test/units/testsuite-01.sh @@ -35,4 +35,10 @@ fi systemctl --state=failed --no-legend --no-pager | tee /failed systemctl daemon-reload +# Check that the early setup is actually skipped on reexec. +# If the early setup is done more than once, then several timestamps, +# e.g. SecurityStartTimestamp, are re-initialized, and causes an ABRT +# of systemd-analyze blame. See issue #27187. +systemd-analyze blame + echo OK >/testok diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh index edaf667107..0ee56dfc00 100755 --- a/test/units/testsuite-65.sh +++ b/test/units/testsuite-65.sh @@ -11,13 +11,15 @@ export SYSTEMD_LOG_LEVEL=debug # Sanity checks # -# We can't really test time, blame, critical-chain and plot verbs here, as +# We can't really test time, critical-chain and plot verbs here, as # the testsuite service is a part of the boot transaction, so let's assume # they fail systemd-analyze || : systemd-analyze time || : -systemd-analyze blame || : systemd-analyze critical-chain || : +# blame +systemd-analyze blame +systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame # plot systemd-analyze plot >/dev/null || : systemd-analyze plot --json=pretty >/dev/null || : |