1
0
mirror of https://github.com/systemd/systemd synced 2025-09-22 13:24:45 +02:00

Compare commits

..

No commits in common. "0c25f8fd0ba410ed15ab1f31c7dd374f85d86a26" and "c6e6c85f83176fe6082c216aa2eb6621d9bc009d" have entirely different histories.

17 changed files with 236 additions and 498 deletions

View File

@ -480,28 +480,6 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term>log-level</term>
<listitem><para>Controls the log level used by
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
<para>Valid values are <literal>emerg</literal>, <literal>alert</literal>, <literal>crit</literal>,
<literal>err</literal>, <literal>warning</literal>, <literal>notice</literal>,
<literal>info</literal>, and <literal>debug</literal>.</para>
<para>If unspecified, <literal>info</literal> will be used, unless one has already been configured
via an SMBIOS Type 11 string, see
<citerefentry><refentrytitle>smbios-type-11</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
<para>Note that the configured level will only be used after <filename>loader.conf</filename> has
been parsed, so log messages generated before that point may be unaffected by this setting.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -869,31 +869,6 @@
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>TPM2PCRs=</varname></term>
<listitem><para>Configures the list of PCRs to use for LUKS2 volumes configured with
the <varname>Encrypt=tpm2</varname> setting in partition files.
This option take the same parameters as the similary named options to
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and have the same effect on partitions where TPM2 enrollment is requested.
This option will be overridden by the global <varname>--tpm2-pcrs=</varname> option.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>KeyFile=</varname></term>
<listitem><para>Takes a file system path. This path must be absolute, otherwise the option is ignored.
Configures the encryption key to use when setting up LUKS2 volumes configured with the
<varname>Encrypt=key-file</varname> setting in partition files. Please refer to the documentation of
<varname>--key-file=</varname> for more details. This option will be overridden by the global
<varname>--key-file=</varname> option.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>Compression=</varname></term>

View File

@ -80,20 +80,10 @@
<listitem><para>This allows inserting additional entries into the <command>systemd-boot</command>
menu. For details see
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>io.systemd.boot.loglevel=</varname><replaceable>LEVEL</replaceable></term>
<listitem><para>This allows configuration of the log level, and is read by <command>systemd-boot</command>.
For details see
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -640,16 +640,6 @@ uki-url http://example.com/somedir/fooos.efi</programlisting>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>io.systemd.boot.loglevel</varname></term>
<listitem><para>If set, the value of this string is used as log level. Valid values (from most to
least critical) are <literal>emerg</literal>, <literal>alert</literal>, <literal>crit</literal>,
<literal>err</literal>, <literal>warning</literal>, <literal>notice</literal>, <literal>info</literal>,
and <literal>debug</literal>.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -338,9 +338,9 @@
volumes configured with the <varname>Encrypt=key-file</varname> setting in partition files. Should
refer to a regular file containing the key, or an <constant>AF_UNIX</constant> stream socket in the
file system. In the latter case, a connection is made to it and the key read from it. If this switch
is not specified, and no <varname>KeyFile=</varname> is specified in the partition file, the empty
key (i.e. zero length key) is used. This behaviour is useful for setting up encrypted partitions during
early first boot that receive their user-supplied password only in a later setup step.</para>
is not specified, the empty key (i.e. zero length key) is used. This behaviour is useful for setting
up encrypted partitions during early first boot that receive their user-supplied password only in a
later setup step.</para>
<xi:include href="version-info.xml" xpointer="v247"/></listitem>
</varlistentry>

View File

@ -3,7 +3,6 @@
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
@ -32,111 +31,104 @@ int efi_get_variable(
void **ret_value,
size_t *ret_size) {
_cleanup_close_ int fd = -EBADF;
_cleanup_free_ void *buf = NULL;
struct stat st;
usec_t begin = 0; /* Unnecessary initialization to appease gcc */
uint32_t a;
ssize_t n;
assert(variable);
const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
if (!ret_value && !ret_size && !ret_attribute) {
/* If caller is not interested in anything, just check if the variable exists and is
* readable. */
if (access(p, R_OK) < 0)
return -errno;
return 0;
}
if (DEBUG_LOGGING) {
log_debug("Reading EFI variable %s.", p);
begin = now(CLOCK_MONOTONIC);
}
_cleanup_close_ int fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return log_debug_errno(errno, "open(\"%s\") failed: %m", p);
uint32_t attr;
_cleanup_free_ char *buf = NULL;
ssize_t n;
if (fstat(fd, &st) < 0)
return log_debug_errno(errno, "fstat(\"%s\") failed: %m", p);
if (st.st_size < 4)
return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "EFI variable %s is shorter than 4 bytes, refusing.", p);
if (st.st_size > 4*1024*1024 + 4)
return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "EFI variable %s is ridiculously large, refusing.", p);
/* The kernel ratelimits reads from the efivarfs because EFI is inefficient, and we'll occasionally
* fail with EINTR here. A slowdown is better than a failure for us, so retry a few times and
* eventually fail with -EBUSY.
*
* See https://github.com/torvalds/linux/blob/master/fs/efivarfs/file.c#L75 and
* https://github.com/torvalds/linux/commit/bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.
*
* The variable may also be overwritten between the stat and read. If we find out that the new
* contents are longer, try again.
*/
for (unsigned try = 0;; try++) {
struct stat st;
if (ret_value || ret_attribute) {
/* The kernel ratelimits reads from the efivarfs because EFI is inefficient, and we'll
* occasionally fail with EINTR here. A slowdown is better than a failure for us, so
* retry a few times and eventually fail with -EBUSY.
*
* See https://github.com/torvalds/linux/blob/master/fs/efivarfs/file.c#L75
* and
* https://github.com/torvalds/linux/commit/bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.
*/
for (unsigned try = 0;; try++) {
n = read(fd, &a, sizeof(a));
if (n >= 0)
break;
log_debug_errno(errno, "Reading from \"%s\" failed: %m", p);
if (errno != EINTR)
return -errno;
if (try >= EFI_N_RETRIES_TOTAL)
return -EBUSY;
if (fstat(fd, &st) < 0)
return log_debug_errno(errno, "fstat(\"%s\") failed: %m", p);
if (st.st_size == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
"EFI variable %s is uncommitted", p);
if (st.st_size < 4)
return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "EFI variable %s is shorter than 4 bytes, refusing.", p);
if (st.st_size > 4*1024*1024 + 4)
return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "EFI variable %s is ridiculously large, refusing.", p);
if (!ret_attribute && !ret_value) {
/* No need to read anything, return the reported size. */
n = st.st_size;
break;
if (try >= EFI_N_RETRIES_NO_DELAY)
(void) usleep_safe(EFI_RETRY_DELAY);
}
/* We want +1 for the read call, and +3 for the additional terminating bytes added below. */
char *t = realloc(buf, (size_t) st.st_size + MAX(1, 3));
if (!t)
return -ENOMEM;
buf = t;
/* Unfortunately kernel reports EOF if there's an inconsistency between efivarfs var list
* and what's actually stored in firmware, c.f. #34304. A zero size env var is not allowed in
* efi and hence the variable doesn't really exist in the backing store as long as it is zero
* sized, and the kernel calls this "uncommitted". Hence we translate EOF back to ENOENT here,
* as with kernel behavior before
* https://github.com/torvalds/linux/commit/3fab70c165795431f00ddf9be8b84ddd07bd1f8f
*
* If the kernel changes behaviour (to flush dentries on resume), we can drop
* this at some point in the future. But note that the commit is 11
* years old at this point so we'll need to deal with the current behaviour for
* a long time.
*/
if (n == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
"EFI variable %s is uncommitted", p);
const struct iovec iov[] = {
{ &attr, sizeof(attr) },
{ buf, (size_t) st.st_size + 1 },
};
n = readv(fd, iov, 2);
assert(n <= st.st_size + 1);
if (n == st.st_size + 1)
/* We need to try again with a bigger buffer. */
continue;
if (n >= 0)
break;
log_debug_errno(errno, "Reading from \"%s\" failed: %m", p);
if (errno != EINTR)
return -errno;
if (try >= EFI_N_RETRIES_TOTAL)
return -EBUSY;
if (try >= EFI_N_RETRIES_NO_DELAY)
(void) usleep_safe(EFI_RETRY_DELAY);
if (n != sizeof(a))
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Read %zi bytes from EFI variable %s, expected %zu.", n, p, sizeof(a));
}
/* Unfortunately kernel reports EOF if there's an inconsistency between efivarfs var list and
* what's actually stored in firmware, c.f. #34304. A zero size env var is not allowed in EFI
* and hence the variable doesn't really exist in the backing store as long as it is zero
* sized, and the kernel calls this "uncommitted". Hence we translate EOF back to ENOENT
* here, as with kernel behavior before
* https://github.com/torvalds/linux/commit/3fab70c165795431f00ddf9be8b84ddd07bd1f8f.
*
* If the kernel changes behaviour (to flush dentries on resume), we can drop this at some
* point in the future. But note that the commit is 11 years old at this point so we'll need
* to deal with the current behaviour for a long time.
*/
if (n == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
"EFI variable %s is uncommitted", p);
if (n < 4)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Read %zi bytes from EFI variable %s, expected >= 4", n, p);
if (ret_attribute)
*ret_attribute = attr;
if (ret_value) {
assert(buf);
/* Always NUL-terminate (3 bytes, to properly protect UTF-16, even if truncated in
* the middle of a character) */
buf[n - 4] = 0;
buf[n - 4 + 1] = 0;
buf[n - 4 + 2] = 0;
*ret_value = TAKE_PTR(buf);
}
buf = malloc(st.st_size - 4 + 3);
if (!buf)
return -ENOMEM;
n = read(fd, buf, (size_t) st.st_size - 4);
if (n < 0)
return log_debug_errno(errno, "Failed to read value of EFI variable %s: %m", p);
assert(n <= st.st_size - 4);
/* Always NUL-terminate (3 bytes, to properly protect UTF-16, even if truncated in the middle
* of a character) */
((char*) buf)[n] = 0;
((char*) buf)[n + 1] = 0;
((char*) buf)[n + 2] = 0;
} else
/* Assume that the reported size is accurate */
n = st.st_size - 4;
if (DEBUG_LOGGING) {
usec_t end = now(CLOCK_MONOTONIC);
@ -148,8 +140,14 @@ int efi_get_variable(
/* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable
* with a smaller value. */
if (ret_attribute)
*ret_attribute = a;
if (ret_value)
*ret_value = TAKE_PTR(buf);
if (ret_size)
*ret_size = n - 4;
*ret_size = n;
return 0;
}
@ -210,10 +208,10 @@ static int efi_verify_variable(const char *variable, uint32_t attr, const void *
int efi_set_variable(const char *variable, const void *value, size_t size) {
static const uint32_t attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
_cleanup_free_ struct var {
struct var {
uint32_t attr;
char buf[];
} _packed_ *buf = NULL;
} _packed_ * _cleanup_free_ buf = NULL;
_cleanup_close_ int fd = -EBADF;
bool saved_flags_valid = false;
unsigned saved_flags;

View File

@ -361,8 +361,6 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
if (config->console_mode_efivar != CONSOLE_MODE_KEEP)
printf(" console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar);
printf(" log-level: %s\n", log_level_to_string(log_get_max_level()));
if (!ps_continue())
return;
@ -1113,9 +1111,6 @@ static void config_defaults_load_from_file(Config *config, char *content) {
}
config->console_mode = u;
}
} else if (streq8(key, "log-level")) {
if (log_set_max_level_from_string(value) < 0)
log_error("Error parsing 'log-level' config option, ignoring: %s", value);
}
}
@ -2994,9 +2989,6 @@ static EFI_STATUS run(EFI_HANDLE image) {
uint64_t init_usec;
bool menu = false;
/* set loglevel early to simplify debugging before loader.conf is loaded */
log_set_max_level_from_smbios();
init_usec = time_usec();
err = BS->HandleProtocol(image, MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL), (void **) &loaded_image);

View File

@ -35,7 +35,7 @@ static EFI_STATUS load_one_driver(
if (loaded_image->ImageCodeType != EfiBootServicesCode &&
loaded_image->ImageCodeType != EfiRuntimeServicesCode)
return log_error_status(EFI_INVALID_PARAMETER, "Image %ls is not a driver, refusing.", fname);
return log_error("Image %ls is not a driver, refusing.", fname);
err = BS->StartImage(image, NULL, NULL);
if (err != EFI_SUCCESS) {

View File

@ -1,78 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "efi-log.h"
#include "efi-string-table.h"
#include "proto/rng.h"
#include "smbios.h"
#include "util.h"
#include "vmm.h"
static unsigned log_count = 0;
static LogLevel log_max_level = LOG_INFO;
static const uint8_t log_level_color[_LOG_MAX] = {
[LOG_EMERG] = EFI_LIGHTRED,
[LOG_ALERT] = EFI_LIGHTRED,
[LOG_CRIT] = EFI_LIGHTRED,
[LOG_ERR] = EFI_LIGHTRED,
[LOG_WARNING] = EFI_YELLOW,
[LOG_NOTICE] = EFI_WHITE,
[LOG_INFO] = EFI_WHITE,
[LOG_DEBUG] = EFI_LIGHTGRAY,
};
static const char *const log_level_table[_LOG_MAX] = {
[LOG_EMERG] = "emerg",
[LOG_ALERT] = "alert",
[LOG_CRIT] = "crit",
[LOG_ERR] = "err",
[LOG_WARNING] = "warning",
[LOG_NOTICE] = "notice",
[LOG_INFO] = "info",
[LOG_DEBUG] = "debug",
};
DEFINE_STRING_TABLE_LOOKUP(log_level, LogLevel);
LogLevel log_get_max_level(void) {
return log_max_level;
}
int log_set_max_level(LogLevel level) {
assert(level >= 0 && level < _LOG_MAX);
int old = log_max_level;
log_max_level = level;
return old;
}
int log_set_max_level_from_string(const char *e) {
int r;
assert(e);
r = log_level_from_string(e);
if (r < 0)
return r;
log_set_max_level(r);
return 0;
}
void log_set_max_level_from_smbios(void) {
int r;
if (is_confidential_vm())
return; /* Don't consume SMBIOS in Confidential Computing contexts */
const char *level_str = smbios_find_oem_string("io.systemd.boot.loglevel=", /* after= */ NULL);
if (!level_str)
return;
r = log_set_max_level_from_string(level_str);
if (r < 0)
log_warning("Failed to parse log level '%s', ignoring.", level_str);
}
void freeze(void) {
for (;;)
@ -99,18 +31,14 @@ void efi_assert(const char *expr, const char *file, unsigned line, const char *f
freeze();
}
EFI_STATUS log_internal(EFI_STATUS status, LogLevel log_level, const char *format, ...) {
EFI_STATUS log_internal(EFI_STATUS status, uint8_t text_color, const char *format, ...) {
assert(format);
assert(log_level >= 0 && log_level < _LOG_MAX);
if (log_level > log_max_level)
return status;
int32_t attr = ST->ConOut->Mode->Attribute;
if (ST->ConOut->Mode->CursorColumn > 0)
ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n");
ST->ConOut->SetAttribute(ST->ConOut, EFI_TEXT_ATTR(log_level_color[log_level], EFI_BLACK));
ST->ConOut->SetAttribute(ST->ConOut, EFI_TEXT_ATTR(text_color, EFI_BLACK));
va_list ap;
va_start(ap, format);

View File

@ -21,49 +21,17 @@ __attribute__((no_stack_protector, noinline)) void __stack_chk_guard_init(void);
# define __stack_chk_guard_init()
#endif
typedef enum LogLevel {
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG,
_LOG_MAX,
_LOG_INVALID = -1,
} LogLevel;
LogLevel log_level_from_string(const char *s) _pure_;
const char* log_level_to_string(LogLevel l) _const_;
LogLevel log_get_max_level(void) _pure_;
int log_set_max_level(LogLevel level);
int log_set_max_level_from_string(const char *e);
void log_set_max_level_from_smbios(void);
_noreturn_ void freeze(void);
void log_wait(void);
_gnu_printf_(3, 4) EFI_STATUS log_internal(EFI_STATUS status, LogLevel log_level, const char *format, ...);
#define log_full(status, log_level, format, ...) \
log_internal(status, log_level, "%s:%i@%s: " format, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define log_debug(...) log_full(EFI_SUCCESS, LOG_DEBUG, __VA_ARGS__)
#define log_info(...) log_full(EFI_SUCCESS, LOG_INFO, __VA_ARGS__)
#define log_notice(...) log_full(EFI_SUCCESS, LOG_NOTICE, __VA_ARGS__)
#define log_warning(...) log_full(EFI_SUCCESS, LOG_WARNING, __VA_ARGS__)
#define log_error(...) log_full(EFI_SUCCESS, LOG_ERR, __VA_ARGS__)
#define log_emergency(...) log_full(EFI_SUCCESS, LOG_EMERG, __VA_ARGS__)
#define log_debug_status(status, ...) log_full(status, LOG_DEBUG, __VA_ARGS__)
#define log_info_status(status, ...) log_full(status, LOG_INFO, __VA_ARGS__)
#define log_notice_status(status, ...) log_full(status, LOG_NOTICE, __VA_ARGS__)
#define log_warning_status(status, ...) log_full(status, LOG_WARNING, __VA_ARGS__)
#define log_error_status(status, ...) log_full(status, LOG_ERR, __VA_ARGS__)
#define log_emergency_status(status, ...) log_full(status, LOG_EMERG, __VA_ARGS__)
#define log_oom() log_full(EFI_OUT_OF_RESOURCES, LOG_ERR, "Out of memory.")
_gnu_printf_(3, 4) EFI_STATUS log_internal(EFI_STATUS status, uint8_t text_color, const char *format, ...);
#define log_full(status, text_color, format, ...) \
log_internal(status, text_color, "%s:%i@%s: " format, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define log_debug(...) log_full(EFI_SUCCESS, EFI_LIGHTGRAY, __VA_ARGS__)
#define log_info(...) log_full(EFI_SUCCESS, EFI_WHITE, __VA_ARGS__)
#define log_warning_status(status, ...) log_full(status, EFI_YELLOW, __VA_ARGS__)
#define log_error_status(status, ...) log_full(status, EFI_LIGHTRED, __VA_ARGS__)
#define log_error(...) log_full(EFI_INVALID_PARAMETER, EFI_LIGHTRED, __VA_ARGS__)
#define log_oom() log_full(EFI_OUT_OF_RESOURCES, EFI_LIGHTRED, "Out of memory.")
/* Debugging helper — please keep this around, even if not used */
#define log_hexdump(prefix, data, size) \

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "efi-string.h"
#include "macro-fundamental.h"
#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
@ -10,23 +9,5 @@
return name##_table[i]; \
}
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type, scope) \
scope type name##_from_string(const char *s) { \
if (!s) \
return (type) -1; \
for (size_t i = 0; i < ELEMENTSOF(name##_table); ++i) \
if (streq8(name##_table[i], s)) \
return (type) i; \
return (type) -1; \
}
#define _DEFINE_STRING_TABLE_LOOKUP(name, type, scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name, type, scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type, scope)
#define DEFINE_STRING_TABLE_LOOKUP(name, type) _DEFINE_STRING_TABLE_LOOKUP(name, type,)
#define DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,)
#define DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name, type) _DEFINE_STRING_TABLE_LOOKUP(name, type, static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name, type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type, static)

View File

@ -20,6 +20,9 @@
#include "shim.h"
#include "util.h"
#define STUB_PAYLOAD_GUID \
{ 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
typedef struct {
MEMMAP_DEVICE_PATH memmap_path;
EFI_DEVICE_PATH end_path;
@ -53,12 +56,22 @@ static EFI_STATUS load_via_boot_services(
uint32_t compat_entry_point,
const char16_t *cmdline,
const struct iovec *kernel,
const struct iovec *initrd,
KERNEL_FILE_PATH *kernel_file_path) {
const struct iovec *initrd) {
_cleanup_(unload_imagep) EFI_HANDLE kernel_image = NULL;
EFI_LOADED_IMAGE_PROTOCOL* loaded_image = NULL;
EFI_STATUS err;
VENDOR_DEVICE_PATH device_node = {
.Header = {
.Type = MEDIA_DEVICE_PATH,
.SubType = MEDIA_VENDOR_DP,
.Length = sizeof(device_node),
},
.Guid = STUB_PAYLOAD_GUID,
};
_cleanup_free_ EFI_DEVICE_PATH* file_path = device_path_replace_node(parent_loaded_image->FilePath, NULL, &device_node.Header);
/* When running with shim < v16 and booting a UKI directly from it, without a second stage loader,
* the shim verify protocol needs to be called or it will raise a security violation when starting
* the image (e.g.: Fedora Cloud Base UKI). TODO: drop once support for shim < v16 is not needed. */
@ -68,13 +81,13 @@ static EFI_STATUS load_via_boot_services(
&(ValidationContext) {
.addr = kernel->iov_base,
.len = kernel->iov_len,
.device_path = &kernel_file_path->memmap_path.Header,
.device_path = file_path,
});
err = BS->LoadImage(/* BootPolicy= */false,
parent,
&kernel_file_path->memmap_path.Header,
file_path,
kernel->iov_base,
kernel->iov_len,
&kernel_image);
@ -191,27 +204,17 @@ EFI_STATUS linux_exec(
if (err != EFI_SUCCESS)
return log_error_status(err, "Bad kernel image: %m");
/* Re-use the parent_image(_handle) and parent_loaded_image for the kernel image we are about to execute.
* We have to do this, because if kernel stub code passes its own handle to certain firmware functions,
* the firmware could cast EFI_LOADED_IMAGE_PROTOCOL * to a larger struct to access its own private data,
* and if we allocated a smaller struct, that could cause problems.
* This is modeled exactly after GRUB behaviour, which has proven to be functional. */
EFI_LOADED_IMAGE_PROTOCOL *parent_loaded_image;
err = BS->HandleProtocol(
parent_image, MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL), (void **) &parent_loaded_image);
if (err != EFI_SUCCESS)
return log_error_status(err, "Cannot get parent loaded image: %m");
_cleanup_free_ KERNEL_FILE_PATH *kernel_file_path = xnew(KERNEL_FILE_PATH, 1);
*kernel_file_path = (KERNEL_FILE_PATH) {
.memmap_path = {
.Header = {
.Type = HARDWARE_DEVICE_PATH,
.SubType = HW_MEMMAP_DP,
.Length = sizeof(MEMMAP_DEVICE_PATH),
},
.MemoryType = EfiLoaderData,
.StartingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base),
.EndingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base) + kernel->iov_len,
},
.end_path = DEVICE_PATH_END_NODE,
};
/* If shim provides LoadImage, it comes from the new SHIM_IMAGE_LOADER interface added in shim 16,
* and implements the following:
* - shim hashes PE sections of PE binaries it authenticates and stores the hashes in a global
@ -238,8 +241,7 @@ EFI_STATUS linux_exec(
compat_entry_point,
cmdline,
kernel,
initrd,
kernel_file_path);
initrd);
err = pe_kernel_check_no_relocation(kernel->iov_base);
if (err != EFI_SUCCESS)
@ -298,13 +300,26 @@ EFI_STATUS linux_exec(
}
}
/* Patch the parent_image(_handle) and parent_loaded_image for the kernel image we are about to execute.
* We have to do this, because if kernel stub code passes its own handle to certain firmware functions,
* the firmware could cast EFI_LOADED_IMAGE_PROTOCOL * to a larger struct to access its own private data,
* and if we allocated a smaller struct, that could cause problems.
* This is modeled exactly after GRUB behaviour, which has proven to be functional. */
EFI_LOADED_IMAGE_PROTOCOL original_parent_loaded_image = *parent_loaded_image;
parent_loaded_image->FilePath = &kernel_file_path->memmap_path.Header;
_cleanup_free_ KERNEL_FILE_PATH *kernel_file_path = xnew(KERNEL_FILE_PATH, 1);
*kernel_file_path = (KERNEL_FILE_PATH) {
.memmap_path = {
.Header = {
.Type = HARDWARE_DEVICE_PATH,
.SubType = HW_MEMMAP_DP,
.Length = sizeof(MEMMAP_DEVICE_PATH),
},
.MemoryType = EfiLoaderData,
.StartingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base),
.EndingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base) + kernel->iov_len,
},
.end_path = {
.Type = END_DEVICE_PATH_TYPE,
.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
.Length = sizeof(EFI_DEVICE_PATH),
},
};
parent_loaded_image->ImageBase = loaded_kernel;
parent_loaded_image->ImageSize = kernel_size_in_memory;
@ -331,9 +346,6 @@ EFI_STATUS linux_exec(
err = compat_entry(parent_image, ST);
}
/* Restore */
*parent_loaded_image = original_parent_loaded_image;
/* On failure we'll free the buffers. EDK2 requires the memory buffers to be writable and
* non-executable, as in some configurations it will overwrite them with a fixed pattern, so if the
* attributes are not restored FreePages() will crash. */

View File

@ -211,10 +211,10 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
size = info->FileSize;
if (size < RANDOM_MAX_SIZE_MIN)
return log_error_status(EFI_INVALID_PARAMETER, "Random seed file is too short.");
return log_error("Random seed file is too short.");
if (size > RANDOM_MAX_SIZE_MAX)
return log_error_status(EFI_INVALID_PARAMETER, "Random seed file is too large.");
return log_error("Random seed file is too large.");
seed = xmalloc(size);
rsize = size;

View File

@ -169,7 +169,8 @@ static bool arg_size_auto = false;
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
static bool arg_legend = true;
static struct iovec arg_key = {};
static void *arg_key = NULL;
static size_t arg_key_size = 0;
static char *arg_private_key = NULL;
static KeySourceType arg_private_key_source_type = OPENSSL_KEY_SOURCE_FILE;
static char *arg_private_key_source = NULL;
@ -207,7 +208,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
STATIC_DESTRUCTOR_REGISTER(arg_definitions, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_key, iovec_done_erase);
STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep);
STATIC_DESTRUCTOR_REGISTER(arg_private_key, freep);
STATIC_DESTRUCTOR_REGISTER(arg_private_key_source, freep);
STATIC_DESTRUCTOR_REGISTER(arg_certificate, freep);
@ -412,9 +413,6 @@ typedef struct Partition {
OrderedHashmap *subvolumes;
char *default_subvolume;
EncryptMode encrypt;
struct iovec key;
Tpm2PCRValue *tpm2_hash_pcr_values;
size_t tpm2_n_hash_pcr_values;
VerityMode verity;
char *verity_match_key;
MinimizeMode minimize;
@ -678,13 +676,10 @@ static Partition* partition_free(Partition *p) {
strv_free(p->make_symlinks);
ordered_hashmap_free(p->subvolumes);
free(p->default_subvolume);
free(p->tpm2_hash_pcr_values);
free(p->verity_match_key);
free(p->compression);
free(p->compression_level);
iovec_done_erase(&p->key);
copy_files_free_many(p->copy_files, p->n_copy_files);
iovec_done(&p->roothash);
@ -722,13 +717,10 @@ static void partition_foreignize(Partition *p) {
p->make_symlinks = strv_free(p->make_symlinks);
p->subvolumes = ordered_hashmap_free(p->subvolumes);
p->default_subvolume = mfree(p->default_subvolume);
p->tpm2_hash_pcr_values = mfree(p->tpm2_hash_pcr_values);
p->verity_match_key = mfree(p->verity_match_key);
p->compression = mfree(p->compression);
p->compression_level = mfree(p->compression_level);
iovec_done_erase(&p->key);
copy_files_free_many(p->copy_files, p->n_copy_files);
p->copy_files = NULL;
p->n_copy_files = 0;
@ -2475,78 +2467,6 @@ static int config_parse_encrypted_volume(
return 0;
}
static int config_parse_tpm2_pcrs(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Partition *partition = ASSERT_PTR(data);
assert(rvalue);
if (isempty(rvalue)) {
/* Clear existing PCR values if empty */
partition->tpm2_hash_pcr_values = mfree(partition->tpm2_hash_pcr_values);
partition->tpm2_n_hash_pcr_values = 0;
return 0;
}
return tpm2_parse_pcr_argument_append(rvalue, &partition->tpm2_hash_pcr_values,
&partition->tpm2_n_hash_pcr_values);
}
static int parse_key_file(const char *filename, struct iovec *key) {
_cleanup_(erase_and_freep) char *k = NULL;
size_t n = 0;
int r;
r = read_full_file_full(
AT_FDCWD, filename,
/* offset= */ UINT64_MAX,
/* size= */ SIZE_MAX,
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
/* bind_name= */ NULL,
&k, &n);
if (r < 0)
return log_error_errno(r, "Failed to read key file '%s': %m", filename);
iovec_done_erase(key);
*key = IOVEC_MAKE(TAKE_PTR(k), n);
return 0;
}
static int config_parse_key_file(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Partition *partition = ASSERT_PTR(userdata);
assert(rvalue);
if (isempty(rvalue)) {
iovec_done_erase(&partition->key);
return 0;
}
return parse_key_file(rvalue, &partition->key);
}
static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_verity, verity_mode, VerityMode, VERITY_OFF);
static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_minimize, minimize_mode, MinimizeMode, MINIMIZE_OFF);
@ -2652,8 +2572,6 @@ static int partition_read_definition(Partition *p, const char *path, const char
{ "Partition", "VerityHashBlockSizeBytes", config_parse_block_size, 0, &p->verity_hash_block_size },
{ "Partition", "MountPoint", config_parse_mountpoint, 0, p },
{ "Partition", "EncryptedVolume", config_parse_encrypted_volume, 0, p },
{ "Partition", "TPM2PCRs", config_parse_tpm2_pcrs, 0, p },
{ "Partition", "KeyFile", config_parse_key_file, 0, p },
{ "Partition", "Compression", config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, &p->compression },
{ "Partition", "CompressionLevel", config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, &p->compression_level },
{ "Partition", "SupplementFor", config_parse_string, 0, &p->supplement_for_name },
@ -4875,21 +4793,18 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
/* Use partition-specific key if available, otherwise fall back to global key */
struct iovec *iovec_key = arg_key.iov_base ? &arg_key : &p->key;
r = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
NULL,
VOLUME_KEY_SIZE,
strempty(iovec_key->iov_base),
iovec_key->iov_len);
strempty(arg_key),
arg_key_size);
if (r < 0)
return log_error_errno(r, "Failed to add LUKS2 key: %m");
passphrase = strempty(iovec_key->iov_base);
passphrase_size = iovec_key->iov_len;
passphrase = strempty(arg_key);
passphrase_size = arg_key_size;
}
if (IN_SET(p->encrypt, ENCRYPT_TPM2, ENCRYPT_KEY_FILE_TPM2)) {
@ -4900,10 +4815,8 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
ssize_t base64_encoded_size;
int keyslot;
TPM2Flags flags = 0;
Tpm2PCRValue *pcr_values = arg_tpm2_n_hash_pcr_values > 0 ? arg_tpm2_hash_pcr_values : p->tpm2_hash_pcr_values;
size_t n_pcr_values = arg_tpm2_n_hash_pcr_values > 0 ? arg_tpm2_n_hash_pcr_values : p->tpm2_n_hash_pcr_values;
if (n_pcr_values == 0 &&
if (arg_tpm2_n_hash_pcr_values == 0 &&
arg_tpm2_public_key_pcr_mask == 0 &&
!arg_tpm2_pcrlock)
log_notice("Notice: encrypting future partition %" PRIu64 ", locking against TPM2 with an empty policy, i.e. without any state or access restrictions.\n"
@ -4943,7 +4856,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
if (r < 0)
return r;
if (!tpm2_pcr_values_has_all_values(pcr_values, n_pcr_values))
if (!tpm2_pcr_values_has_all_values(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Must provide all PCR values when using TPM2 device key.");
} else {
@ -4951,8 +4864,8 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
if (r < 0)
return r;
if (!tpm2_pcr_values_has_all_values(pcr_values, n_pcr_values)) {
r = tpm2_pcr_read_missing_values(tpm2_context, pcr_values, n_pcr_values);
if (!tpm2_pcr_values_has_all_values(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values)) {
r = tpm2_pcr_read_missing_values(tpm2_context, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values);
if (r < 0)
return log_error_errno(r, "Could not read pcr values: %m");
}
@ -4960,17 +4873,17 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
uint16_t hash_pcr_bank = 0;
uint32_t hash_pcr_mask = 0;
if (n_pcr_values > 0) {
if (arg_tpm2_n_hash_pcr_values > 0) {
size_t hash_count;
r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
r = tpm2_pcr_values_hash_count(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, &hash_count);
if (r < 0)
return log_error_errno(r, "Could not get hash count: %m");
if (hash_count > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR banks selected.");
hash_pcr_bank = pcr_values[0].hash;
r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, hash_pcr_bank, &hash_pcr_mask);
hash_pcr_bank = arg_tpm2_hash_pcr_values[0].hash;
r = tpm2_pcr_values_to_mask(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, hash_pcr_bank, &hash_pcr_mask);
if (r < 0)
return log_error_errno(r, "Could not get hash mask: %m");
}
@ -4983,8 +4896,8 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
/* If both PCR public key unlock and pcrlock unlock is selected, then shard the encryption key. */
r = tpm2_calculate_sealing_policy(
pcr_values,
n_pcr_values,
arg_tpm2_hash_pcr_values,
arg_tpm2_n_hash_pcr_values,
iovec_is_set(&pubkey) ? &public : NULL,
/* use_pin= */ false,
arg_tpm2_pcrlock && !iovec_is_set(&pubkey) ? &pcrlock_policy : NULL,
@ -4994,8 +4907,8 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
if (arg_tpm2_pcrlock && iovec_is_set(&pubkey)) {
r = tpm2_calculate_sealing_policy(
pcr_values,
n_pcr_values,
arg_tpm2_hash_pcr_values,
arg_tpm2_n_hash_pcr_values,
/* public= */ NULL, /* Turn this one off for the 2nd shard */
/* use_pin= */ false,
&pcrlock_policy, /* But turn this one on */
@ -8916,9 +8829,20 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY *
break;
case ARG_KEY_FILE: {
r = parse_key_file(optarg, &arg_key);
_cleanup_(erase_and_freep) char *k = NULL;
size_t n = 0;
r = read_full_file_full(
AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
NULL,
&k, &n);
if (r < 0)
return r;
return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
erase_and_free(arg_key);
arg_key = TAKE_PTR(k);
arg_key_size = n;
break;
}

View File

@ -9,7 +9,6 @@
#include "errno-util.h"
#include "glyph-util.h"
#include "in-addr-util.h"
#include "iovec-util.h"
#include "json-util.h"
#include "resolved-dns-answer.h"
#include "resolved-dns-browse-services.h"
@ -38,8 +37,9 @@ typedef struct LookupParameters {
int ifindex;
uint64_t flags;
int family;
struct iovec address;
const char *name;
union in_addr_union address;
size_t address_size;
char *name;
uint16_t class;
uint16_t type;
} LookupParameters;
@ -62,8 +62,7 @@ typedef struct LookupParamatersBrowseServices {
static void lookup_parameters_destroy(LookupParameters *p) {
assert(p);
iovec_done(&p->address);
free(p->name);
}
static int dns_query_new_for_varlink(
@ -342,10 +341,10 @@ static int parse_as_address(sd_varlink *link, LookupParameters *p) {
static int vl_method_resolve_hostname(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
static const sd_json_dispatch_field dispatch_table[] = {
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX },
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, name), SD_JSON_MANDATORY },
{ "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParameters, family), 0 },
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 },
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX },
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(LookupParameters, name), SD_JSON_MANDATORY },
{ "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParameters, family), 0 },
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 },
{}
};
@ -410,6 +409,42 @@ static int vl_method_resolve_hostname(sd_varlink *link, sd_json_variant *paramet
return 1;
}
static int json_dispatch_address(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
LookupParameters *p = ASSERT_PTR(userdata);
union in_addr_union buf = {};
sd_json_variant *i;
size_t n, k = 0;
assert(variant);
if (!sd_json_variant_is_array(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name));
n = sd_json_variant_elements(variant);
if (!IN_SET(n, 4, 16))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name));
JSON_VARIANT_ARRAY_FOREACH(i, variant) {
int64_t b;
if (!sd_json_variant_is_integer(i))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name));
b = sd_json_variant_integer(i);
if (b < 0 || b > 0xff)
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL),
"Element %zu of JSON field '%s' is out of range 0%s255.",
k, strna(name), glyph(GLYPH_ELLIPSIS));
buf.bytes[k++] = (uint8_t) b;
}
p->address = buf;
p->address_size = k;
return 0;
}
static void vl_method_resolve_address_complete(DnsQuery *query) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
_cleanup_(dns_query_freep) DnsQuery *q = query;
@ -472,10 +507,10 @@ finish:
static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
static const sd_json_dispatch_field dispatch_table[] = {
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX },
{ "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParameters, family), SD_JSON_MANDATORY },
{ "address", SD_JSON_VARIANT_ARRAY, json_dispatch_byte_array_iovec, offsetof(LookupParameters, address), SD_JSON_MANDATORY },
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 },
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX },
{ "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParameters, family), SD_JSON_MANDATORY },
{ "address", SD_JSON_VARIANT_ARRAY, json_dispatch_address, 0, SD_JSON_MANDATORY },
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 },
{}
};
@ -502,15 +537,13 @@ static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *paramete
if (!IN_SET(p.family, AF_INET, AF_INET6))
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family"));
if (FAMILY_ADDRESS_SIZE(p.family) != p.address.iov_len)
if (FAMILY_ADDRESS_SIZE(p.family) != p.address_size)
return sd_varlink_error(link, "io.systemd.Resolve.BadAddressSize", NULL);
if (validate_and_mangle_query_flags(m, &p.flags, /* name = */ NULL, /* ok = */ 0) < 0)
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
union in_addr_union a = IN_ADDR_NULL;
memcpy(&a, p.address.iov_base, p.address.iov_len);
r = dns_question_new_reverse(&question, p.family, &a);
r = dns_question_new_reverse(&question, p.family, &p.address);
if (r < 0)
return r;
@ -522,7 +555,7 @@ static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *paramete
sd_varlink_set_userdata(link, q);
q->request_family = p.family;
q->request_address = a;
q->request_address = p.address;
q->complete = vl_method_resolve_address_complete;
r = dns_query_go(q);
@ -1104,11 +1137,11 @@ finish:
static int vl_method_resolve_record(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
static const sd_json_dispatch_field dispatch_table[] = {
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX },
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, name), SD_JSON_MANDATORY },
{ "class", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, offsetof(LookupParameters, class), 0 },
{ "type", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, offsetof(LookupParameters, type), SD_JSON_MANDATORY },
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 },
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX },
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(LookupParameters, name), SD_JSON_MANDATORY },
{ "class", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, offsetof(LookupParameters, class), 0 },
{ "type", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, offsetof(LookupParameters, type), SD_JSON_MANDATORY },
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 },
{}
};

View File

@ -110,7 +110,7 @@ int umount_recursive_full(const char *prefix, int flags, char **keep) {
return n;
}
#define MS_CONVERTIBLE_FLAGS (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_NOSYMFOLLOW|MS_RELATIME|MS_NOATIME|MS_STRICTATIME|MS_NODIRATIME)
#define MS_CONVERTIBLE_FLAGS (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_NOSYMFOLLOW)
static uint64_t ms_flags_to_mount_attr(unsigned long a) {
uint64_t f = 0;
@ -130,35 +130,6 @@ static uint64_t ms_flags_to_mount_attr(unsigned long a) {
if (FLAGS_SET(a, MS_NOSYMFOLLOW))
f |= MOUNT_ATTR_NOSYMFOLLOW;
if (FLAGS_SET(a, MS_RELATIME))
f |= MOUNT_ATTR_RELATIME;
if (FLAGS_SET(a, MS_NOATIME))
f |= MOUNT_ATTR_NOATIME;
if (FLAGS_SET(a, MS_STRICTATIME))
f |= MOUNT_ATTR_STRICTATIME;
if (FLAGS_SET(a, MS_NODIRATIME))
f |= MOUNT_ATTR_NODIRATIME;
return f;
}
static uint64_t ms_flags_to_mount_attr_clr(unsigned long a) {
uint64_t f = 0;
/* As per documentation, if relatime/noatime/strictatime are set, we need to clear the atime flag
* too, otherwise -EINVAL will be returned by the kernel. */
if (FLAGS_SET(a, MS_RELATIME))
f |= MOUNT_ATTR__ATIME;
if (FLAGS_SET(a, MS_NOATIME))
f |= MOUNT_ATTR__ATIME;
if (FLAGS_SET(a, MS_STRICTATIME))
f |= MOUNT_ATTR__ATIME;
return f;
}
@ -1910,7 +1881,6 @@ int make_fsmount(
return log_full_errno(error_log_level, errno, "Failed to create mount fd for \"%s\" (\"%s\"): %m", what, type);
struct mount_attr ma = {
.attr_clr = ms_flags_to_mount_attr_clr(f),
.attr_set = ms_flags_to_mount_attr(f) | (userns_fd >= 0 ? MOUNT_ATTR_IDMAP : 0),
.userns_fd = userns_fd,
};

View File

@ -2107,8 +2107,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_oom();
_cleanup_free_ char *image_fn = NULL;
r = path_extract_filename(arg_image, &image_fn);
if (r < 0)
if (path_extract_filename(arg_image, &image_fn) < 0)
return log_error_errno(r, "Failed to extract filename from path '%s': %m", image_fn);
_cleanup_free_ char *escaped_image_fn = escape_qemu_value(image_fn);