From 51fac37bb20c9440a9a4e0a20846c139364d6d13 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 25 Apr 2024 04:54:52 +0200 Subject: Adding upstream version 255.5. Signed-off-by: Daniel Baumann --- src/basic/chase.c | 30 ++++++++++----------- src/basic/chattr-util.c | 2 +- src/basic/env-util.c | 31 ++++++++++++++++++---- src/basic/env-util.h | 2 ++ src/basic/filesystems-gperf.gperf | 1 + src/basic/fs-util.c | 8 +++--- src/basic/fs-util.h | 10 +++++-- src/basic/hashmap.h | 2 +- src/basic/lock-util.c | 14 +++++----- src/basic/log.c | 10 +++++-- src/basic/meson.build | 2 +- src/basic/missing_magic.h | 5 ++++ src/basic/os-util.c | 55 ++++++++++++++++++++++++++++++++++++--- src/basic/os-util.h | 1 + src/basic/stat-util.c | 26 +++++++++++++++--- src/basic/stat-util.h | 3 +++ src/basic/terminal-util.c | 2 +- src/basic/terminal-util.h | 3 ++- src/basic/virt.c | 1 + 19 files changed, 162 insertions(+), 46 deletions(-) (limited to 'src/basic') diff --git a/src/basic/chase.c b/src/basic/chase.c index 26bc2d6..9f5477e 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -374,11 +374,11 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int return r; if (FLAGS_SET(flags, CHASE_MKDIR_0755) && !isempty(todo)) { - child = xopenat(fd, - first, - O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, - /* xopen_flags = */ 0, - 0755); + child = xopenat_full(fd, + first, + O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, + /* xopen_flags = */ 0, + 0755); if (child < 0) return child; } else if (FLAGS_SET(flags, CHASE_PARENT) && isempty(todo)) { @@ -760,10 +760,10 @@ int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, i if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) /* Shortcut this call if none of the special features of this call are requested */ - return xopenat(AT_FDCWD, path, - open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0), - /* xopen_flags = */ 0, - mode); + return xopenat_full(AT_FDCWD, path, + open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0), + /* xopen_flags = */ 0, + mode); r = chase(path, root, CHASE_PARENT|chase_flags, &p, &path_fd); if (r < 0) @@ -777,7 +777,7 @@ int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, i return r; } - r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode); + r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode); if (r < 0) return r; @@ -964,10 +964,10 @@ int chase_and_openat(int dir_fd, const char *path, ChaseFlags chase_flags, int o if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) /* Shortcut this call if none of the special features of this call are requested */ - return xopenat(dir_fd, path, - open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0), - /* xopen_flags = */ 0, - mode); + return xopenat_full(dir_fd, path, + open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0), + /* xopen_flags = */ 0, + mode); r = chaseat(dir_fd, path, chase_flags|CHASE_PARENT, &p, &path_fd); if (r < 0) @@ -979,7 +979,7 @@ int chase_and_openat(int dir_fd, const char *path, ChaseFlags chase_flags, int o return r; } - r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode); + r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode); if (r < 0) return r; diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c index fe8b9ab..d76be5c 100644 --- a/src/basic/chattr-util.c +++ b/src/basic/chattr-util.c @@ -29,7 +29,7 @@ int chattr_full( assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, /* xopen_flags = */ 0, /* mode = */ 0); + fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return fd; diff --git a/src/basic/env-util.c b/src/basic/env-util.c index d3bf733..a97651d 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -983,8 +983,8 @@ int putenv_dup(const char *assignment, bool override) { } int setenv_systemd_exec_pid(bool update_only) { - char str[DECIMAL_STR_MAX(pid_t)]; const char *e; + int r; /* Update $SYSTEMD_EXEC_PID=pid except when '*' is set for the variable. */ @@ -995,10 +995,9 @@ int setenv_systemd_exec_pid(bool update_only) { if (streq_ptr(e, "*")) return 0; - xsprintf(str, PID_FMT, getpid_cached()); - - if (setenv("SYSTEMD_EXEC_PID", str, 1) < 0) - return -errno; + r = setenvf("SYSTEMD_EXEC_PID", /* overwrite= */ 1, PID_FMT, getpid_cached()); + if (r < 0) + return r; return 1; } @@ -1093,3 +1092,25 @@ int set_full_environment(char **env) { return 0; } + +int setenvf(const char *name, bool overwrite, const char *valuef, ...) { + _cleanup_free_ char *value = NULL; + va_list ap; + int r; + + assert(name); + + if (!valuef) + return RET_NERRNO(unsetenv(name)); + + va_start(ap, valuef); + DISABLE_WARNING_FORMAT_NONLITERAL; + r = vasprintf(&value, valuef, ap); + REENABLE_WARNING; + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return RET_NERRNO(setenv(name, value, overwrite)); +} diff --git a/src/basic/env-util.h b/src/basic/env-util.h index f7fb1e9..34cf1f9 100644 --- a/src/basic/env-util.h +++ b/src/basic/env-util.h @@ -79,3 +79,5 @@ int getenv_path_list(const char *name, char ***ret_paths); int getenv_steal_erase(const char *name, char **ret); int set_full_environment(char **env); + +int setenvf(const char *name, bool overwrite, const char *valuef, ...) _printf_(3,4); diff --git a/src/basic/filesystems-gperf.gperf b/src/basic/filesystems-gperf.gperf index e8c5357..1cd66b5 100644 --- a/src/basic/filesystems-gperf.gperf +++ b/src/basic/filesystems-gperf.gperf @@ -91,6 +91,7 @@ ocfs2, {OCFS2_SUPER_MAGIC} openpromfs, {OPENPROM_SUPER_MAGIC} orangefs, {ORANGEFS_DEVREQ_MAGIC} overlay, {OVERLAYFS_SUPER_MAGIC} +pidfs, {PID_FS_MAGIC} pipefs, {PIPEFS_MAGIC} ppc-cmm, {PPC_CMM_MAGIC} proc, {PROC_SUPER_MAGIC} diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 9ba9268..5bc7d2f 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1054,7 +1054,7 @@ int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) { path = fname; } - fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode); + fd = xopenat_full(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode); if (IN_SET(fd, -ELOOP, -ENOTDIR)) return -EEXIST; if (fd < 0) @@ -1110,7 +1110,7 @@ int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, b } } -int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) { +int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) { _cleanup_close_ int fd = -EBADF; bool made = false; int r; @@ -1191,7 +1191,7 @@ int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags return TAKE_FD(fd); } -int xopenat_lock( +int xopenat_lock_full( int dir_fd, const char *path, int open_flags, @@ -1214,7 +1214,7 @@ int xopenat_lock( for (;;) { struct stat st; - fd = xopenat(dir_fd, path, open_flags, xopen_flags, mode); + fd = xopenat_full(dir_fd, path, open_flags, xopen_flags, mode); if (fd < 0) return fd; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 1023ab7..6a1e2e7 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -137,6 +137,12 @@ typedef enum XOpenFlags { XO_SUBVOLUME = 1 << 1, } XOpenFlags; -int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode); +int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode); +static inline int xopenat(int dir_fd, const char *path, int open_flags) { + return xopenat_full(dir_fd, path, open_flags, 0, 0); +} -int xopenat_lock(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation); +int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation); +static inline int xopenat_lock(int dir_fd, const char *path, int open_flags, LockType locktype, int operation) { + return xopenat_lock_full(dir_fd, path, open_flags, 0, 0, locktype, operation); +} diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 233f1d7..d0ebdf5 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -39,8 +39,8 @@ typedef struct IteratedCache IteratedCache; /* Caches the iterated order of on * by hashmap users, so the definition has to be here. Do not use its fields * directly. */ typedef struct { - unsigned idx; /* index of an entry to be iterated next */ const void *next_key; /* expected value of that entry's key pointer */ + unsigned idx; /* index of an entry to be iterated next */ #if ENABLE_DEBUG_HASHMAP unsigned put_count; /* hashmap's put_count recorded at start of iteration */ unsigned rem_count; /* hashmap's rem_count in previous iteration */ diff --git a/src/basic/lock-util.c b/src/basic/lock-util.c index 047fd01..7bffe85 100644 --- a/src/basic/lock-util.c +++ b/src/basic/lock-util.c @@ -40,13 +40,13 @@ int make_lock_file_at(int dir_fd, const char *p, int operation, LockFile *ret) { if (!t) return -ENOMEM; - fd = xopenat_lock(dfd, - p, - O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, - /* xopen_flags = */ 0, - 0600, - LOCK_UNPOSIX, - operation); + fd = xopenat_lock_full(dfd, + p, + O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, + /* xopen_flags = */ 0, + 0600, + LOCK_UNPOSIX, + operation); if (fd < 0) return fd == -EAGAIN ? -EBUSY : fd; diff --git a/src/basic/log.c b/src/basic/log.c index 1470611..7a44300 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -427,6 +427,8 @@ static int write_to_console( const char *func, const char *buffer) { + static int dumb = -1; + char location[256], header_time[FORMAT_TIMESTAMP_MAX], prefix[1 + DECIMAL_STR_MAX(int) + 2], @@ -438,6 +440,9 @@ static int write_to_console( if (console_fd < 0) return 0; + if (dumb < 0) + dumb = getenv_terminal_is_dumb(); + if (log_target == LOG_TARGET_CONSOLE_PREFIXED) { xsprintf(prefix, "<%i>", level); iovec[n++] = IOVEC_MAKE_STRING(prefix); @@ -481,8 +486,9 @@ static int write_to_console( /* When writing to a TTY we output an extra '\r' (i.e. CR) first, to generate CRNL rather than just * NL. This is a robustness thing in case the TTY is currently in raw mode (specifically: has the * ONLCR flag off). We want that subsequent output definitely starts at the beginning of the line - * again, after all. If the TTY is not in raw mode the extra CR should not hurt. */ - iovec[n++] = IOVEC_MAKE_STRING(check_console_fd_is_tty() ? "\r\n" : "\n"); + * again, after all. If the TTY is not in raw mode the extra CR should not hurt. If we're writing to + * a dumb terminal, only write NL as CRNL might be interpreted as a double newline. */ + iovec[n++] = IOVEC_MAKE_STRING(check_console_fd_is_tty() && !dumb ? "\r\n" : "\n"); if (writev(console_fd, iovec, n) < 0) { diff --git a/src/basic/meson.build b/src/basic/meson.build index d7450d8..111253e 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -235,7 +235,7 @@ filesystem_includes = ['linux/magic.h', check_filesystems = find_program('check-filesystems.sh') r = run_command([check_filesystems, cpp, files('filesystems-gperf.gperf')] + filesystem_includes, check: false) if r.returncode() != 0 - error('Unknown filesystems defined in kernel headers:\n\n' + r.stdout()) + warning('Unknown filesystems defined in kernel headers:\n\n' + r.stdout()) endif filesystems_gperf_h = custom_target( diff --git a/src/basic/missing_magic.h b/src/basic/missing_magic.h index 27a33ad..82d71c8 100644 --- a/src/basic/missing_magic.h +++ b/src/basic/missing_magic.h @@ -128,6 +128,11 @@ #define DEVMEM_MAGIC 0x454d444d #endif +/* cb12fd8e0dabb9a1c8aef55a6a41e2c255fcdf4b (6.8) */ +#ifndef PID_FS_MAGIC +#define PID_FS_MAGIC 0x50494446 +#endif + /* Not in mainline but included in Ubuntu */ #ifndef SHIFTFS_MAGIC #define SHIFTFS_MAGIC 0x6a656a62 diff --git a/src/basic/os-util.c b/src/basic/os-util.c index dbd067f..985d89b 100644 --- a/src/basic/os-util.c +++ b/src/basic/os-util.c @@ -61,6 +61,39 @@ bool image_name_is_valid(const char *s) { return true; } +int path_extract_image_name(const char *path, char **ret) { + _cleanup_free_ char *fn = NULL; + int r; + + assert(path); + assert(ret); + + /* Extract last component from path, without any "/" suffixes. */ + r = path_extract_filename(path, &fn); + if (r < 0) + return r; + + if (r != O_DIRECTORY) { + /* Chop off any image suffixes we recognize (unless we already know this must refer to some dir */ + FOREACH_STRING(suffix, ".sysext.raw", ".confext.raw", ".raw") { + char *m = endswith(fn, suffix); + if (m) { + *m = 0; + break; + } + } + } + + /* Truncate the version/counting suffixes */ + fn[strcspn(fn, "_+")] = 0; + + if (!image_name_is_valid(fn)) + return -EINVAL; + + *ret = TAKE_PTR(fn); + return 0; +} + int path_is_extension_tree(ImageClass image_class, const char *path, const char *extension, bool relax_extension_release_check) { int r; @@ -230,9 +263,25 @@ int open_extension_release_at( continue; } - if (!relax_extension_release_check && - extension_release_strict_xattr_value(fd, dir_path, de->d_name) != 0) - continue; + 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; + } + + r = path_extract_image_name(extension, &base_extension); + if (r < 0) { + log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", extension); + continue; + } + + if (!streq(base_image_name, base_extension) && + extension_release_strict_xattr_value(fd, dir_path, image_name) != 0) + continue; + } /* We already found what we were looking for, but there's another candidate? We treat this as * an error, as we want to enforce that there are no ambiguities in case we are in the diff --git a/src/basic/os-util.h b/src/basic/os-util.h index 7cee3dd..f6a12a3 100644 --- a/src/basic/os-util.h +++ b/src/basic/os-util.h @@ -25,6 +25,7 @@ ImageClass image_class_from_string(const char *s) _pure_; * in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */ bool image_name_is_valid(const char *s) _pure_; +int path_extract_image_name(const char *path, char **ret); int path_is_extension_tree(ImageClass image_class, const char *path, const char *extension, bool relax_extension_release_check); static inline int path_is_os_tree(const char *path) { diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index c54374b..581370d 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -262,11 +262,31 @@ int path_is_network_fs(const char *path) { return is_network_fs(&s); } +int stat_verify_linked(const struct stat *st) { + assert(st); + + if (st->st_nlink <= 0) + return -EIDRM; /* recognizable error. */ + + return 0; +} + +int fd_verify_linked(int fd) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + return stat_verify_linked(&st); +} + int stat_verify_regular(const struct stat *st) { assert(st); - /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error - * code. */ + /* Checks whether the specified stat() structure refers to a regular file. If not returns an + * appropriate error code. */ if (S_ISDIR(st->st_mode)) return -EISDIR; @@ -470,7 +490,7 @@ int xstatfsat(int dir_fd, const char *path, struct statfs *ret) { assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(ret); - fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0); + fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY); if (fd < 0) return fd; diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index ae0aaf8..3501406 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -71,6 +71,9 @@ int path_is_network_fs(const char *path); */ #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) +int stat_verify_linked(const struct stat *st); +int fd_verify_linked(int fd); + int stat_verify_regular(const struct stat *st); int fd_verify_regular(int fd); int verify_regular_at(int dir_fd, const char *path, bool follow); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 3355b74..530ef9a 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1300,7 +1300,7 @@ static bool on_dev_null(void) { return cached_on_dev_null; } -static bool getenv_terminal_is_dumb(void) { +bool getenv_terminal_is_dumb(void) { const char *e; e = getenv("TERM"); diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 2a7d48b..b1d7aee 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -160,6 +160,7 @@ void columns_lines_cache_reset(int _unused_ signum); void reset_terminal_feature_caches(void); bool on_tty(void); +bool getenv_terminal_is_dumb(void); bool terminal_is_dumb(void); ColorMode get_color_mode(void); bool underline_enabled(void); @@ -186,7 +187,7 @@ static inline bool colors_enabled(void) { } static inline const char *ansi_underline(void) { - return underline_enabled() ? ANSI_UNDERLINE : ANSI_NORMAL; + return underline_enabled() ? ANSI_UNDERLINE : ""; } #define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME) \ diff --git a/src/basic/virt.c b/src/basic/virt.c index 93ccfaa..88357a9 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -178,6 +178,7 @@ static Virtualization detect_vm_dmi_vendor(void) { { "VMW", VIRTUALIZATION_VMWARE }, { "innotek GmbH", VIRTUALIZATION_ORACLE }, { "VirtualBox", VIRTUALIZATION_ORACLE }, + { "Oracle Corporation", VIRTUALIZATION_ORACLE }, /* Detect VirtualBox on some proprietary systems via the board_vendor */ { "Xen", VIRTUALIZATION_XEN }, { "Bochs", VIRTUALIZATION_BOCHS }, { "Parallels", VIRTUALIZATION_PARALLELS }, -- cgit v1.2.3