summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shared/ask-password-api.c29
-rw-r--r--src/shared/base-filesystem.c24
-rw-r--r--src/shared/bootspec.c27
-rw-r--r--src/shared/bus-polkit.c12
-rw-r--r--src/shared/bus-polkit.h1
-rw-r--r--src/shared/condition.c10
-rw-r--r--src/shared/copy.c8
-rw-r--r--src/shared/copy.h39
-rw-r--r--src/shared/cryptsetup-util.c19
-rw-r--r--src/shared/cryptsetup-util.h6
-rw-r--r--src/shared/dissect-image.c1
-rw-r--r--src/shared/edit-util.c2
-rw-r--r--src/shared/exec-util.c1
-rw-r--r--src/shared/gpt.c21
-rw-r--r--src/shared/gpt.h1
-rw-r--r--src/shared/install.c28
-rw-r--r--src/shared/logs-show.c6
-rw-r--r--src/shared/meson.build2
-rw-r--r--src/shared/mkfs-util.c9
-rw-r--r--src/shared/parse-helpers.c19
-rw-r--r--src/shared/parse-helpers.h11
-rw-r--r--src/shared/pretty-print.c7
-rw-r--r--src/shared/ptyfwd.c16
-rw-r--r--src/shared/ptyfwd.h2
-rw-r--r--src/shared/resize-fs.h6
-rw-r--r--src/shared/seccomp-util.c56
-rw-r--r--src/shared/seccomp-util.h1
-rw-r--r--src/shared/spawn-polkit-agent.c11
-rw-r--r--src/shared/tests.c19
-rw-r--r--src/shared/tests.h71
-rw-r--r--src/shared/tpm2-util.c2
-rw-r--r--src/shared/varlink-internal.h40
-rw-r--r--src/shared/varlink.c40
33 files changed, 384 insertions, 163 deletions
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index bf79dc2..042c0ad 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -167,7 +167,16 @@ static int ask_password_keyring(const AskPasswordRequest *req, AskPasswordFlags
if (r < 0)
return r;
- return retrieve_key(serial, ret);
+ _cleanup_strv_free_erase_ char **l = NULL;
+ r = retrieve_key(serial, &l);
+ if (r < 0)
+ return r;
+
+ if (strv_isempty(l))
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY), "Found an empty password from keyring.");
+
+ *ret = TAKE_PTR(l);
+ return 0;
}
static int backspace_chars(int ttyfd, size_t p) {
@@ -322,8 +331,8 @@ int ask_password_plymouth(
return -ENOENT;
} else if (IN_SET(buffer[0], 2, 9)) {
+ _cleanup_strv_free_erase_ char **l = NULL;
uint32_t size;
- char **l;
/* One or more answers */
if (p < 5)
@@ -341,15 +350,16 @@ int ask_password_plymouth(
if (!l)
return -ENOMEM;
- *ret = l;
- break;
+ if (strv_isempty(l))
+ return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED), "Received an empty password.");
+
+ *ret = TAKE_PTR(l);
+ return 0;
} else
/* Unknown packet */
return -EIO;
}
-
- return 0;
}
#define NO_ECHO "(no echo) "
@@ -949,8 +959,8 @@ finish:
static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) {
_cleanup_(erase_and_freep) char *buffer = NULL;
+ _cleanup_strv_free_erase_ char **l = NULL;
size_t size;
- char **l;
int r;
assert(req);
@@ -965,7 +975,10 @@ static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFla
if (!l)
return -ENOMEM;
- *ret = l;
+ if (strv_isempty(l))
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY), "Found an empty password in credential.");
+
+ *ret = TAKE_PTR(l);
return 0;
}
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index a4e2dae..0d5075e 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -56,8 +56,7 @@ static const BaseFilesystem table[] = {
/* aarch64 ELF ABI actually says dynamic loader is in /lib/, but Fedora puts it in /lib64/ anyway and
* just symlinks /lib/ld-linux-aarch64.so.1 to ../lib64/ld-linux-aarch64.so.1. For this to work
* correctly, /lib64/ must be symlinked to /usr/lib64/. */
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-linux-aarch64.so.1" },
# define KNOW_LIB64_DIRS 1
#elif defined(__alpha__)
@@ -66,24 +65,20 @@ static const BaseFilesystem table[] = {
/* No /lib64 on arm. The linker is /lib/ld-linux-armhf.so.3. */
# define KNOW_LIB64_DIRS 1
#elif defined(__i386__) || defined(__x86_64__)
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-linux-x86-64.so.2" },
# define KNOW_LIB64_DIRS 1
#elif defined(__ia64__)
#elif defined(__loongarch_lp64)
# define KNOW_LIB64_DIRS 1
# if defined(__loongarch_double_float)
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-linux-loongarch-lp64d.so.1" },
# elif defined(__loongarch_single_float)
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-linux-loongarch-lp64f.so.1" },
# elif defined(__loongarch_soft_float)
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-linux-loongarch-lp64s.so.1" },
# else
# error "Unknown LoongArch ABI"
@@ -100,8 +95,7 @@ static const BaseFilesystem table[] = {
# endif
#elif defined(__powerpc__)
# if defined(__PPC64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld64.so.2" },
# define KNOW_LIB64_DIRS 1
# elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -113,16 +107,14 @@ static const BaseFilesystem table[] = {
# if __riscv_xlen == 32
# elif __riscv_xlen == 64
/* Same situation as for aarch64 */
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-linux-riscv64-lp64d.so.1" },
# define KNOW_LIB64_DIRS 1
# else
# error "Unknown RISC-V ABI"
# endif
#elif defined(__s390x__)
- { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0"
- "usr/lib64\0"
+ { "lib64", 0, "usr/lib64\0"
"usr/lib\0", "ld-lsb-s390x.so.3" },
# define KNOW_LIB64_DIRS 1
#elif defined(__s390__)
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
index 4bc3ae7..9466866 100644
--- a/src/shared/bootspec.c
+++ b/src/shared/bootspec.c
@@ -505,6 +505,12 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
assert(a);
assert(b);
+ /* This mimics a function of the same name in src/boot/efi/sd-boot.c */
+
+ r = CMP(a->tries_left == 0, b->tries_left == 0);
+ if (r != 0)
+ return r;
+
r = CMP(!a->sort_key, !b->sort_key);
if (r != 0)
return r;
@@ -523,7 +529,18 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
return r;
}
- return -strverscmp_improved(a->id, b->id);
+ r = -strverscmp_improved(a->id, b->id);
+ if (r != 0)
+ return r;
+
+ if (a->tries_left != UINT_MAX || b->tries_left != UINT_MAX)
+ return 0;
+
+ r = -CMP(a->tries_left, b->tries_left);
+ if (r != 0)
+ return r;
+
+ return CMP(a->tries_done, b->tries_done);
}
static int config_check_inode_relevant_and_unseen(BootConfig *config, int fd, const char *fname) {
@@ -743,11 +760,11 @@ static int find_sections(
r = pe_load_headers(fd, &dos_header, &pe_header);
if (r < 0)
- return log_warning_errno(r, "Failed to parse PE file '%s': %m", path);
+ return log_error_errno(r, "Failed to parse PE file '%s': %m", path);
r = pe_load_sections(fd, dos_header, pe_header, &sections);
if (r < 0)
- return log_warning_errno(r, "Failed to parse PE sections of '%s': %m", path);
+ return log_error_errno(r, "Failed to parse PE sections of '%s': %m", path);
if (ret_pe_header)
*ret_pe_header = TAKE_PTR(pe_header);
@@ -809,7 +826,7 @@ static int find_osrel_section(
r = pe_read_section_data(fd, pe_header, sections, ".osrel", PE_SECTION_SIZE_MAX, (void**) ret_osrelease, NULL);
if (r < 0)
- return log_warning_errno(r, "Failed to read .osrel section of '%s': %m", path);
+ return log_error_errno(r, "Failed to read .osrel section of '%s': %m", path);
return 0;
}
@@ -829,7 +846,7 @@ static int find_uki_sections(
return r;
if (!pe_is_uki(pe_header, sections))
- return log_warning_errno(SYNTHETIC_ERRNO(EBADMSG), "Parsed PE file '%s' is not a UKI.", path);
+ return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Parsed PE file '%s' is not a UKI.", path);
r = find_osrel_section(fd, path, sections, pe_header, ret_osrelease);
if (r < 0)
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/copy.c b/src/shared/copy.c
index 8389774..9b90afa 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -982,6 +982,7 @@ static int fd_copy_directory(
_cleanup_close_ int fdf = -EBADF, fdt = -EBADF;
_cleanup_closedir_ DIR *d = NULL;
+ struct stat dt_st;
bool exists;
int r;
@@ -1026,6 +1027,9 @@ static int fd_copy_directory(
if (fdt < 0)
return fdt;
+ if (exists && FLAGS_SET(copy_flags, COPY_RESTORE_DIRECTORY_TIMESTAMPS) && fstat(fdt, &dt_st) < 0)
+ return -errno;
+
r = 0;
if (PTR_TO_INT(hashmap_get(denylist, st)) == DENY_CONTENTS) {
@@ -1125,7 +1129,9 @@ finish:
(void) copy_xattr(dirfd(d), NULL, fdt, NULL, copy_flags);
(void) futimens(fdt, (struct timespec[]) { st->st_atim, st->st_mtim });
- }
+ } else if (FLAGS_SET(copy_flags, COPY_RESTORE_DIRECTORY_TIMESTAMPS))
+ /* If the directory already exists, make sure the timestamps stay the same as before. */
+ (void) futimens(fdt, (struct timespec[]) { dt_st.st_atim, dt_st.st_mtim });
if (copy_flags & COPY_FSYNC_FULL) {
if (fsync(fdt) < 0)
diff --git a/src/shared/copy.h b/src/shared/copy.h
index b8fb28a..db95738 100644
--- a/src/shared/copy.h
+++ b/src/shared/copy.h
@@ -12,25 +12,26 @@
#include "set.h"
typedef enum CopyFlags {
- COPY_REFLINK = 1 << 0, /* Try to reflink */
- COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
- COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
- COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
- COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
- COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */
- COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */
- COPY_SIGTERM = 1 << 7, /* ditto, but for SIGTERM */
- COPY_MAC_CREATE = 1 << 8, /* Create files with the correct MAC label (currently SELinux only) */
- COPY_HARDLINKS = 1 << 9, /* Try to reproduce hard links */
- COPY_FSYNC = 1 << 10, /* fsync() after we are done */
- COPY_FSYNC_FULL = 1 << 11, /* fsync_full() after we are done */
- COPY_SYNCFS = 1 << 12, /* syncfs() the *top-level* dir after we are done */
- COPY_ALL_XATTRS = 1 << 13, /* Preserve all xattrs when copying, not just those in the user namespace */
- COPY_HOLES = 1 << 14, /* Copy holes */
- COPY_GRACEFUL_WARN = 1 << 15, /* Skip copying file types that aren't supported by the target filesystem */
- COPY_TRUNCATE = 1 << 16, /* Truncate to current file offset after copying */
- COPY_LOCK_BSD = 1 << 17, /* Return a BSD exclusively locked file descriptor referring to the copied image/directory. */
- COPY_VERIFY_LINKED = 1 << 18, /* Check the source file is still linked after copying. */
+ COPY_REFLINK = 1 << 0, /* Try to reflink */
+ COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
+ COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
+ COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
+ COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
+ COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */
+ COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */
+ COPY_SIGTERM = 1 << 7, /* ditto, but for SIGTERM */
+ COPY_MAC_CREATE = 1 << 8, /* Create files with the correct MAC label (currently SELinux only) */
+ COPY_HARDLINKS = 1 << 9, /* Try to reproduce hard links */
+ COPY_FSYNC = 1 << 10, /* fsync() after we are done */
+ COPY_FSYNC_FULL = 1 << 11, /* fsync_full() after we are done */
+ COPY_SYNCFS = 1 << 12, /* syncfs() the *top-level* dir after we are done */
+ COPY_ALL_XATTRS = 1 << 13, /* Preserve all xattrs when copying, not just those in the user namespace */
+ COPY_HOLES = 1 << 14, /* Copy holes */
+ COPY_GRACEFUL_WARN = 1 << 15, /* Skip copying file types that aren't supported by the target filesystem */
+ COPY_TRUNCATE = 1 << 16, /* Truncate to current file offset after copying */
+ COPY_LOCK_BSD = 1 << 17, /* Return a BSD exclusively locked file descriptor referring to the copied image/directory. */
+ COPY_VERIFY_LINKED = 1 << 18, /* Check the source file is still linked after copying. */
+ COPY_RESTORE_DIRECTORY_TIMESTAMPS = 1 << 19, /* Make sure existing directory timestamps don't change during copying. */
} CopyFlags;
typedef enum DenyType {
diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c
index 288e6e8..d0dd434 100644
--- a/src/shared/cryptsetup-util.c
+++ b/src/shared/cryptsetup-util.c
@@ -54,10 +54,10 @@ DLSYM_FUNCTION(crypt_volume_key_get);
#if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE
DLSYM_FUNCTION(crypt_reencrypt_init_by_passphrase);
#endif
-#if HAVE_CRYPT_REENCRYPT
-DISABLE_WARNING_DEPRECATED_DECLARATIONS;
+#if HAVE_CRYPT_REENCRYPT_RUN
+DLSYM_FUNCTION(crypt_reencrypt_run);
+#elif HAVE_CRYPT_REENCRYPT
DLSYM_FUNCTION(crypt_reencrypt);
-REENABLE_WARNING;
#endif
DLSYM_FUNCTION(crypt_metadata_locking);
#if HAVE_CRYPT_SET_DATA_OFFSET
@@ -246,11 +246,8 @@ int dlopen_cryptsetup(void) {
/* libcryptsetup added crypt_reencrypt() in 2.2.0, and marked it obsolete in 2.4.0, replacing it with
* crypt_reencrypt_run(), which takes one extra argument but is otherwise identical. The old call is
- * still available though, and given we want to support 2.2.0 for a while longer, we'll stick to the
- * old symbol. However, the old symbols now has a GCC deprecation decorator, hence let's turn off
- * warnings about this for now. */
-
- DISABLE_WARNING_DEPRECATED_DECLARATIONS;
+ * still available though, and given we want to support 2.2.0 for a while longer, we'll use the old
+ * symbol if the new one is not available. */
ELF_NOTE_DLOPEN("cryptsetup",
"Support for disk encryption, integrity, and authentication",
@@ -304,7 +301,9 @@ int dlopen_cryptsetup(void) {
#if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE
DLSYM_ARG(crypt_reencrypt_init_by_passphrase),
#endif
-#if HAVE_CRYPT_REENCRYPT
+#if HAVE_CRYPT_REENCRYPT_RUN
+ DLSYM_ARG(crypt_reencrypt_run),
+#elif HAVE_CRYPT_REENCRYPT
DLSYM_ARG(crypt_reencrypt),
#endif
DLSYM_ARG(crypt_metadata_locking),
@@ -316,8 +315,6 @@ int dlopen_cryptsetup(void) {
if (r <= 0)
return r;
- REENABLE_WARNING;
-
/* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
* libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
* whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
diff --git a/src/shared/cryptsetup-util.h b/src/shared/cryptsetup-util.h
index f00ac36..d255e59 100644
--- a/src/shared/cryptsetup-util.h
+++ b/src/shared/cryptsetup-util.h
@@ -70,10 +70,10 @@ DLSYM_PROTOTYPE(crypt_volume_key_get);
#if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE
DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase);
#endif
-#if HAVE_CRYPT_REENCRYPT
-DISABLE_WARNING_DEPRECATED_DECLARATIONS;
+#if HAVE_CRYPT_REENCRYPT_RUN
+DLSYM_PROTOTYPE(crypt_reencrypt_run);
+#elif HAVE_CRYPT_REENCRYPT
DLSYM_PROTOTYPE(crypt_reencrypt);
-REENABLE_WARNING;
#endif
DLSYM_PROTOTYPE(crypt_metadata_locking);
#if HAVE_CRYPT_SET_DATA_OFFSET
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index a9e211f..6a39010 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -3077,6 +3077,7 @@ int dissected_image_decrypt_interactively(
if (r < 0)
return log_error_errno(r, "Failed to query for passphrase: %m");
+ assert(!strv_isempty(z));
passphrase = z[0];
}
}
diff --git a/src/shared/edit-util.c b/src/shared/edit-util.c
index cfb2828..b049603 100644
--- a/src/shared/edit-util.c
+++ b/src/shared/edit-util.c
@@ -357,7 +357,7 @@ static int strip_edit_temp_file(EditFile *e) {
return 1; /* Contents have real changes */
r = write_string_file(e->temp, new_contents,
- WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_TRUNCATE | WRITE_STRING_FILE_AVOID_NEWLINE);
+ WRITE_STRING_FILE_TRUNCATE | WRITE_STRING_FILE_AVOID_NEWLINE);
if (r < 0)
return log_error_errno(r, "Failed to strip temporary file '%s': %m", e->temp);
diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c
index 996edbf..6f61eb2 100644
--- a/src/shared/exec-util.c
+++ b/src/shared/exec-util.c
@@ -609,5 +609,6 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret
va_end(ap);
execv(path, l);
+ log_error_errno(errno, "Failed to execute %s: %m", path);
_exit(EXIT_FAILURE);
}
diff --git a/src/shared/gpt.c b/src/shared/gpt.c
index d639463..f3e5247 100644
--- a/src/shared/gpt.c
+++ b/src/shared/gpt.c
@@ -143,21 +143,30 @@ const GptPartitionType gpt_partition_type_table[] = {
_GPT_ARCH_SEXTET(ARM64, "aarch64"), /* Alias: must be listed after arm64 */
_GPT_ARCH_SEXTET(IA64, "ia64"),
_GPT_ARCH_SEXTET(LOONGARCH64, "loongarch64"),
+ _GPT_ARCH_SEXTET(LOONGARCH64, "loong64"), /* Alias: must be listed after loongarch64 */
_GPT_ARCH_SEXTET(MIPS, "mips"),
_GPT_ARCH_SEXTET(MIPS64, "mips64"),
_GPT_ARCH_SEXTET(MIPS_LE, "mips-le"),
+ _GPT_ARCH_SEXTET(MIPS_LE, "mipsel"), /* Alias: must be listed after mips-le */
_GPT_ARCH_SEXTET(MIPS64_LE, "mips64-le"),
+ _GPT_ARCH_SEXTET(MIPS64_LE, "mips64el"), /* Alias: must be listed after mips64-le */
_GPT_ARCH_SEXTET(PARISC, "parisc"),
+ _GPT_ARCH_SEXTET(PARISC, "hppa"), /* Alias: must be listed after parisc */
_GPT_ARCH_SEXTET(PPC, "ppc"),
_GPT_ARCH_SEXTET(PPC64, "ppc64"),
_GPT_ARCH_SEXTET(PPC64_LE, "ppc64-le"),
_GPT_ARCH_SEXTET(PPC64_LE, "ppc64le"), /* Alias: must be listed after ppc64-le */
+ _GPT_ARCH_SEXTET(PPC64_LE, "ppc64el"), /* Alias: must be listed after ppc64-le */
_GPT_ARCH_SEXTET(RISCV32, "riscv32"),
_GPT_ARCH_SEXTET(RISCV64, "riscv64"),
_GPT_ARCH_SEXTET(S390, "s390"),
_GPT_ARCH_SEXTET(S390X, "s390x"),
_GPT_ARCH_SEXTET(TILEGX, "tilegx"),
_GPT_ARCH_SEXTET(X86, "x86"),
+ _GPT_ARCH_SEXTET(X86, "i386"), /* Alias: must be listed after x86 */
+ _GPT_ARCH_SEXTET(X86, "i486"), /* Alias: must be listed after x86 */
+ _GPT_ARCH_SEXTET(X86, "i586"), /* Alias: must be listed after x86 */
+ _GPT_ARCH_SEXTET(X86, "i686"), /* Alias: must be listed after x86 */
_GPT_ARCH_SEXTET(X86_64, "x86-64"),
_GPT_ARCH_SEXTET(X86_64, "x86_64"), /* Alias: must be listed after x86-64 */
_GPT_ARCH_SEXTET(X86_64, "amd64"), /* Alias: must be listed after x86-64 */
@@ -339,6 +348,18 @@ bool gpt_partition_type_knows_no_auto(GptPartitionType type) {
PARTITION_SWAP);
}
+bool gpt_partition_type_has_filesystem(GptPartitionType type) {
+ return IN_SET(type.designator,
+ PARTITION_ROOT,
+ PARTITION_USR,
+ PARTITION_HOME,
+ PARTITION_SRV,
+ PARTITION_ESP,
+ PARTITION_XBOOTLDR,
+ PARTITION_TMP,
+ PARTITION_VAR);
+}
+
bool gpt_header_has_signature(const GptHeader *p) {
assert(p);
diff --git a/src/shared/gpt.h b/src/shared/gpt.h
index 21976e5..3d04c19 100644
--- a/src/shared/gpt.h
+++ b/src/shared/gpt.h
@@ -72,6 +72,7 @@ const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type);
bool gpt_partition_type_knows_read_only(GptPartitionType type);
bool gpt_partition_type_knows_growfs(GptPartitionType type);
bool gpt_partition_type_knows_no_auto(GptPartitionType type);
+bool gpt_partition_type_has_filesystem(GptPartitionType type);
typedef struct {
uint8_t partition_type_guid[16];
diff --git a/src/shared/install.c b/src/shared/install.c
index dd2bd5c..53566b7 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1989,7 +1989,9 @@ static int install_info_symlink_alias(
}
broken = r == 0; /* symlink target does not exist? */
- RET_GATHER(ret, create_symlink(lp, alias_target ?: info->path, alias_path, force || broken, changes, n_changes));
+ r = create_symlink(lp, alias_target ?: info->path, alias_path, force || broken, changes, n_changes);
+ if (r != 0 && ret >= 0)
+ ret = r;
}
return ret;
@@ -2012,7 +2014,7 @@ static int install_info_symlink_wants(
UnitNameFlags valid_dst_type = UNIT_NAME_ANY;
const char *n;
- int r = 0, q;
+ int r, q;
assert(info);
assert(lp);
@@ -2083,7 +2085,7 @@ static int install_info_symlink_wants(
return -ENOMEM;
q = create_symlink(lp, info->path, path, /* force = */ true, changes, n_changes);
- if ((q < 0 && r >= 0) || r == 0)
+ if (q != 0 && r >= 0)
r = q;
if (unit_file_exists(scope, lp, dst) == 0) {
@@ -2155,15 +2157,15 @@ static int install_info_apply(
r = install_info_symlink_alias(scope, info, lp, config_path, force, changes, n_changes);
q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->wanted_by, ".wants/", changes, n_changes);
- if (r == 0)
+ if (q != 0 && r >= 0)
r = q;
q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->required_by, ".requires/", changes, n_changes);
- if (r == 0)
+ if (q != 0 && r >= 0)
r = q;
q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->upheld_by, ".upholds/", changes, n_changes);
- if (r == 0)
+ if (q != 0 && r >= 0)
r = q;
return r;
@@ -2282,7 +2284,9 @@ static int install_context_mark_for_removal(
else {
log_debug_errno(r, "Unit %s not found, removing name.", i->name);
r = install_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
- if (r < 0)
+ /* In case there's no unit, we still want to remove any leftover symlink, even if
+ * the unit might have been removed already, hence treating ENOENT as non-fatal. */
+ if (r != -ENOENT)
return r;
}
} else if (r < 0) {
@@ -2874,9 +2878,13 @@ static int do_unit_file_disable(
r = install_info_add(&ctx, *name, NULL, lp->root_dir, /* auxiliary= */ false, &info);
if (r >= 0)
r = install_info_traverse(&ctx, lp, info, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
-
- if (r < 0)
- return install_changes_add(changes, n_changes, r, *name, NULL);
+ if (r < 0) {
+ r = install_changes_add(changes, n_changes, r, *name, NULL);
+ /* In case there's no unit, we still want to remove any leftover symlink, even if
+ * the unit might have been removed already, hence treating ENOENT as non-fatal. */
+ if (r != -ENOENT)
+ return r;
+ }
/* If we enable multiple units, some with install info and others without,
* the "empty [Install] section" warning is not shown. Let's make the behavior
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index c71c868..153a411 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -450,6 +450,9 @@ static void parse_display_realtime(
assert(j);
assert(ret);
+ // FIXME: _SOURCE_MONOTONIC_TIMESTAMP is in CLOCK_BOOTTIME, hence we cannot use it for adjusting realtime.
+ source_monotonic = NULL;
+
/* First, try _SOURCE_REALTIME_TIMESTAMP. */
if (source_realtime && safe_atou64(source_realtime, &t) >= 0 && VALID_REALTIME(t)) {
*ret = t;
@@ -488,6 +491,9 @@ static void parse_display_timestamp(
assert(ret_display_ts);
assert(ret_boot_id);
+ // FIXME: _SOURCE_MONOTONIC_TIMESTAMP is in CLOCK_BOOTTIME, hence we cannot use it for adjusting realtime.
+ source_monotonic = NULL;
+
if (source_realtime && safe_atou64(source_realtime, &t) >= 0 && VALID_REALTIME(t))
source_ts.realtime = t;
diff --git a/src/shared/meson.build b/src/shared/meson.build
index c5106d8..e513c0e 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -358,7 +358,7 @@ libshared = shared_library(
'-Wl,--version-script=' + libshared_sym_path],
link_depends : libshared_sym_path,
link_whole : [libshared_static,
- libbasic,
+ libbasic_static,
libsystemd_static],
dependencies : [libshared_deps,
userspace],
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/resize-fs.h b/src/shared/resize-fs.h
index b40943c..bacaec7 100644
--- a/src/shared/resize-fs.h
+++ b/src/shared/resize-fs.h
@@ -7,9 +7,9 @@
int resize_fs(int fd, uint64_t sz, uint64_t *ret_size);
-#define BTRFS_MINIMAL_SIZE (256U*1024U*1024U)
-#define XFS_MINIMAL_SIZE (300U*1024U*1024U)
-#define EXT4_MINIMAL_SIZE (1024U*1024U)
+#define BTRFS_MINIMAL_SIZE (256U*U64_MB)
+#define XFS_MINIMAL_SIZE (300U*U64_MB)
+#define EXT4_MINIMAL_SIZE (32U*U64_MB)
uint64_t minimal_size_by_fs_magic(statfs_f_type_t magic);
uint64_t minimal_size_by_fs_name(const char *str);
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/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index ce3c5fb..fd91bd6 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -43,16 +43,21 @@ int polkit_agent_open(void) {
xsprintf(notify_fd, "%i", pipe_fd[1]);
r = fork_agent("(polkit-agent)",
- &pipe_fd[1], 1,
+ &pipe_fd[1],
+ 1,
&agent_pid,
POLKIT_AGENT_BINARY_PATH,
- POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL);
+ POLKIT_AGENT_BINARY_PATH,
+ "--notify-fd",
+ notify_fd,
+ "--fallback",
+ NULL);
/* Close the writing side, because that's the one for the agent */
safe_close(pipe_fd[1]);
if (r < 0)
- log_error_errno(r, "Failed to fork TTY ask password agent: %m");
+ log_error_errno(r, "Failed to fork polkit agent: %m");
else
/* Wait until the agent closes the fd */
(void) fd_wait_for_event(pipe_fd[0], POLLHUP, USEC_INFINITY);
diff --git a/src/shared/tests.c b/src/shared/tests.c
index 9169513..a919212 100644
--- a/src/shared/tests.c
+++ b/src/shared/tests.c
@@ -29,6 +29,7 @@
#include "strv.h"
#include "tests.h"
#include "tmpfile-util.h"
+#include "uid-range.h"
char* setup_fake_runtime_dir(void) {
char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p;
@@ -166,6 +167,24 @@ bool have_namespaces(void) {
assert_not_reached();
}
+bool userns_has_single_user(void) {
+ _cleanup_(uid_range_freep) UIDRange *uidrange = NULL, *gidrange = NULL;
+
+ /* Check if we're in a user namespace with only a single user mapped in. We special case this
+ * scenario in a few tests because it's the only kind of namespace that can be created unprivileged
+ * and as such happens more often than not, so we make sure to deal with it so that all tests pass
+ * in such environments. */
+
+ if (uid_range_load_userns(NULL, UID_RANGE_USERNS_INSIDE, &uidrange) < 0)
+ return false;
+
+ if (uid_range_load_userns(NULL, GID_RANGE_USERNS_INSIDE, &gidrange) < 0)
+ return false;
+
+ return uidrange->n_entries == 1 && uidrange->entries[0].nr == 1 &&
+ gidrange->n_entries == 1 && gidrange->entries[0].nr == 1;
+}
+
bool can_memlock(void) {
/* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against
* RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we
diff --git a/src/shared/tests.h b/src/shared/tests.h
index 09fdfd6..f904c0d 100644
--- a/src/shared/tests.h
+++ b/src/shared/tests.h
@@ -76,6 +76,7 @@ void test_setup_logging(int level);
int write_tmpfile(char *pattern, const char *contents);
bool have_namespaces(void);
+bool userns_has_single_user(void);
/* We use the small but non-trivial limit here */
#define CAN_MEMLOCK_SIZE (512 * 1024U)
@@ -217,6 +218,39 @@ static inline int run_test_table(void) {
} \
})
+/* For funtions that return a boolean on success and a negative errno on failure. */
+#define ASSERT_OK_POSITIVE(expr) \
+ ({ \
+ typeof(expr) _result = (expr); \
+ if (_result < 0) { \
+ log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \
+ PROJECT_FILE, __LINE__, #expr); \
+ abort(); \
+ } \
+ if (_result == 0) { \
+ log_error("%s:%i: Assertion failed: expected \"%s\" to be positive, but it is zero.", \
+ PROJECT_FILE, __LINE__, #expr); \
+ abort(); \
+ } \
+ })
+
+#define ASSERT_OK_ZERO(expr) \
+ ({ \
+ typeof(expr) _result = (expr); \
+ if (_result < 0) { \
+ log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \
+ PROJECT_FILE, __LINE__, #expr); \
+ abort(); \
+ } \
+ if (_result != 0) { \
+ char _sexpr[DECIMAL_STR_MAX(typeof(expr))]; \
+ xsprintf(_sexpr, DECIMAL_STR_FMT(_result), _result); \
+ log_error("%s:%i: Assertion failed: expected \"%s\" to be zero, but it is %s.", \
+ PROJECT_FILE, __LINE__, #expr, _sexpr); \
+ abort(); \
+ } \
+ })
+
#define ASSERT_OK_ERRNO(expr) \
({ \
typeof(expr) _result = (expr); \
@@ -227,6 +261,16 @@ static inline int run_test_table(void) {
} \
})
+#define ASSERT_FAIL(expr) \
+ ({ \
+ typeof(expr) _result = (expr); \
+ if (_result >= 0) { \
+ log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to fail, but it succeeded", \
+ PROJECT_FILE, __LINE__, #expr); \
+ abort(); \
+ } \
+ })
+
#define ASSERT_ERROR(expr1, expr2) \
({ \
int _expr1 = (expr1); \
@@ -419,3 +463,30 @@ static inline int run_test_table(void) {
abort(); \
} \
})
+
+
+#define ASSERT_EQ_ID128(expr1, expr2) \
+ ({ \
+ typeof(expr1) _expr1 = (expr1); \
+ typeof(expr2) _expr2 = (expr2); \
+ if (!sd_id128_equal(_expr1, _expr2)) { \
+ log_error("%s:%i: Assertion failed: \"%s == %s\", but \"%s != %s\"", \
+ PROJECT_FILE, __LINE__, \
+ #expr1, #expr2, \
+ SD_ID128_TO_STRING(_expr1), SD_ID128_TO_STRING(_expr2)); \
+ abort(); \
+ } \
+ })
+
+#define ASSERT_NE_ID128(expr1, expr2) \
+ ({ \
+ typeof(expr1) _expr1 = (expr1); \
+ typeof(expr2) _expr2 = (expr2); \
+ if (sd_id128_equal(_expr1, _expr2)) { \
+ log_error("%s:%i: Assertion failed: \"%s != %s\", but \"%s == %s\"", \
+ PROJECT_FILE, __LINE__, \
+ #expr1, #expr2, \
+ SD_ID128_TO_STRING(_expr1), SD_ID128_TO_STRING(_expr2)); \
+ abort(); \
+ } \
+ })
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 87ce53c..9603f18 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -2119,6 +2119,8 @@ int tpm2_create_primary(
/* creationData= */ NULL,
/* creationHash= */ NULL,
/* creationTicket= */ NULL);
+ if (rc == TPM2_RC_BAD_AUTH)
+ return log_debug_errno(SYNTHETIC_ERRNO(EDEADLK), "Authorization failure while attempting to enroll SRK into TPM.");
if (rc != TSS2_RC_SUCCESS)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to generate primary key in TPM: %s",
diff --git a/src/shared/varlink-internal.h b/src/shared/varlink-internal.h
index 715202a..bc30108 100644
--- a/src/shared/varlink-internal.h
+++ b/src/shared/varlink-internal.h
@@ -6,5 +6,45 @@
#include "fdset.h"
#include "varlink.h"
+typedef struct VarlinkServerSocket VarlinkServerSocket;
+
+struct VarlinkServerSocket {
+ VarlinkServer *server;
+
+ int fd;
+ char *address;
+
+ sd_event_source *event_source;
+
+ LIST_FIELDS(VarlinkServerSocket, sockets);
+};
+
+struct VarlinkServer {
+ unsigned n_ref;
+ VarlinkServerFlags flags;
+
+ LIST_HEAD(VarlinkServerSocket, sockets);
+
+ Hashmap *methods; /* Fully qualified symbol name of a method → VarlinkMethod */
+ Hashmap *interfaces; /* Fully qualified interface name → VarlinkInterface* */
+ Hashmap *symbols; /* Fully qualified symbol name of method/error → VarlinkSymbol* */
+ VarlinkConnect connect_callback;
+ VarlinkDisconnect disconnect_callback;
+
+ sd_event *event;
+ int64_t event_priority;
+
+ unsigned n_connections;
+ Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */
+
+ void *userdata;
+ char *description;
+
+ unsigned connections_max;
+ unsigned connections_per_uid_max;
+
+ bool exit_on_idle;
+};
+
int varlink_server_serialize(VarlinkServer *s, FILE *f, FDSet *fds);
int varlink_server_deserialize_one(VarlinkServer *s, const char *value, FDSet *fds);
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
index 034e72b..0a6d2c8 100644
--- a/src/shared/varlink.c
+++ b/src/shared/varlink.c
@@ -210,46 +210,6 @@ struct Varlink {
pid_t exec_pid;
};
-typedef struct VarlinkServerSocket VarlinkServerSocket;
-
-struct VarlinkServerSocket {
- VarlinkServer *server;
-
- int fd;
- char *address;
-
- sd_event_source *event_source;
-
- LIST_FIELDS(VarlinkServerSocket, sockets);
-};
-
-struct VarlinkServer {
- unsigned n_ref;
- VarlinkServerFlags flags;
-
- LIST_HEAD(VarlinkServerSocket, sockets);
-
- Hashmap *methods; /* Fully qualified symbol name of a method → VarlinkMethod */
- Hashmap *interfaces; /* Fully qualified interface name → VarlinkInterface* */
- Hashmap *symbols; /* Fully qualified symbol name of method/error → VarlinkSymbol* */
- VarlinkConnect connect_callback;
- VarlinkDisconnect disconnect_callback;
-
- sd_event *event;
- int64_t event_priority;
-
- unsigned n_connections;
- Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */
-
- void *userdata;
- char *description;
-
- unsigned connections_max;
- unsigned connections_per_uid_max;
-
- bool exit_on_idle;
-};
-
static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
[VARLINK_IDLE_CLIENT] = "idle-client",
[VARLINK_AWAITING_REPLY] = "awaiting-reply",