New upstream version 252.2

This commit is contained in:
Luca Boccassi 2022-11-28 22:25:21 +00:00
parent b7785f44d2
commit c1e08e516e
49 changed files with 552 additions and 476 deletions

1
docs/CNAME Normal file
View File

@ -0,0 +1 @@
systemd.io

View File

@ -73,13 +73,9 @@ All tools:
(relevant in particular for the system manager and `systemd-hostnamed`).
Must be a valid hostname (either a single label or a FQDN).
* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
method. Defaults to `auto`. Behavior is defined as follows:
`auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
on `/`. If both conditions meet, then it's in initrd.
`lenient`: Similar to `auto`, but the rootfs check is skipped.
`0|1`: Simply overrides initrd detection. This is useful for debugging and
testing initrd-only programs in the main system.
* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
This is useful for debugging and testing initrd-only programs in the main
system.
* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
completion. If no time unit is specified, assumes seconds. The usual other units

View File

@ -1474,11 +1474,14 @@ if want_tpm2 != 'false' and not skip_deps
tpm2 = dependency('tss2-esys tss2-rc tss2-mu',
required : want_tpm2 == 'true')
have = tpm2.found()
have_esys3 = tpm2.version().version_compare('>= 3.0.0')
else
have = false
have_esys3 = false
tpm2 = []
endif
conf.set10('HAVE_TPM2', have)
conf.set10('HAVE_TSS2_ESYS3', have_esys3)
want_elfutils = get_option('elfutils')
if want_elfutils != 'false' and not skip_deps
@ -3838,7 +3841,7 @@ exe = custom_target(
install_dir : bindir)
public_programs += exe
if want_tests != 'false'
if want_tests != 'false' and want_kernel_install
test('test-kernel-install',
test_kernel_install_sh,
args : [exe.full_path(), loaderentry_install])

View File

@ -174,12 +174,35 @@ int fd_cloexec(int fd, bool cloexec) {
return RET_NERRNO(fcntl(fd, F_SETFD, nflags));
}
int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec) {
int ret = 0, r;
assert(n_fds == 0 || fds);
for (size_t i = 0; i < n_fds; i++) {
if (fds[i] < 0) /* Skip gracefully over already invalidated fds */
continue;
r = fd_cloexec(fds[i], cloexec);
if (r < 0 && ret >= 0) /* Continue going, but return first error */
ret = r;
else
ret = 1; /* report if we did anything */
}
return ret;
}
_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
assert(n_fdset == 0 || fdset);
for (size_t i = 0; i < n_fdset; i++)
for (size_t i = 0; i < n_fdset; i++) {
if (fdset[i] < 0)
continue;
if (fdset[i] == fd)
return true;
}
return false;
}
@ -252,6 +275,10 @@ static int close_all_fds_special_case(const int except[], size_t n_except) {
if (!have_close_range)
return 0;
if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid,
* we got none */
n_except = 0;
switch (n_except) {
case 0:

View File

@ -56,6 +56,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec);
int get_max_fd(void);

View File

@ -1372,6 +1372,14 @@ int safe_fork_full(
}
}
if (flags & FORK_CLOEXEC_OFF) {
r = fd_cloexec_many(except_fds, n_except_fds, false);
if (r < 0) {
log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
_exit(EXIT_FAILURE);
}
}
/* When we were asked to reopen the logs, do so again now */
if (flags & FORK_REOPEN_LOG) {
log_open();

View File

@ -150,6 +150,7 @@ typedef enum ForkFlags {
FORK_STDOUT_TO_STDERR = 1 << 11, /* Make stdout a copy of stderr */
FORK_FLUSH_STDIO = 1 << 12, /* fflush() stdout (and stderr) before forking */
FORK_NEW_USERNS = 1 << 13, /* Run child in its own user namespace */
FORK_CLOEXEC_OFF = 1 << 14, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);

View File

@ -721,7 +721,7 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
}
if (!m) {
m = new0(char, 1);
m = new0(char, 2);
if (!m)
return -ENOMEM;
n = 1;
@ -730,11 +730,9 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
m[n] = '\0';
assert(n > 0);
*ret = m;
*ret = TAKE_PTR(m);
*ret_size = n - 1;
m = NULL;
return 0;
}

View File

@ -45,7 +45,7 @@ static inline int strv_extend(char ***l, const char *value) {
return strv_extend_with_size(l, NULL, value);
}
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
int strv_extendf(char ***l, const char *format, ...) _printf_(2,3);
int strv_extend_front(char ***l, const char *value);
int strv_push_with_size(char ***l, size_t *n, char *value);

View File

@ -52,59 +52,25 @@ int prot_from_flags(int flags) {
bool in_initrd(void) {
int r;
const char *e;
bool lenient = false;
if (saved_in_initrd >= 0)
return saved_in_initrd;
/* We have two checks here:
*
* 1. the flag file /etc/initrd-release must exist
* 2. the root file system must be a memory file system
*
* The second check is extra paranoia, since misdetecting an
* initrd can have bad consequences due the initrd
* emptying when transititioning to the main systemd.
*
* If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
* both checks are used. If it's set to "lenient", only check
* 1 is used. If set to a boolean value, then the boolean
* value is returned.
/* If /etc/initrd-release exists, we're in an initrd.
* This can be overridden by setting SYSTEMD_IN_INITRD=0|1.
*/
e = secure_getenv("SYSTEMD_IN_INITRD");
if (e) {
if (streq(e, "lenient"))
lenient = true;
else if (!streq(e, "auto")) {
r = parse_boolean(e);
if (r >= 0) {
saved_in_initrd = r > 0;
return saved_in_initrd;
}
log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
}
}
if (!lenient) {
r = path_is_temporary_fs("/");
if (r < 0)
log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
r = getenv_bool_secure("SYSTEMD_IN_INITRD");
if (r < 0 && r != -ENXIO)
log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
if (r >= 0)
saved_in_initrd = r > 0;
}
r = access("/etc/initrd-release", F_OK);
if (r >= 0) {
if (saved_in_initrd == 0)
log_debug("/etc/initrd-release exists, but it's not an initrd.");
else
saved_in_initrd = 1;
} else {
if (errno != ENOENT)
log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
saved_in_initrd = 0;
else {
r = access("/etc/initrd-release", F_OK);
if (r < 0 && errno != ENOENT)
log_debug_errno(r, "Failed to check if /etc/initrd-release exists, assuming it does not: %m");
saved_in_initrd = r >= 0;
}
return saved_in_initrd;

View File

@ -585,12 +585,16 @@ static int print_efi_option(uint16_t id, int *n_printed, bool in_order) {
assert(n_printed);
r = efi_get_boot_option(id, &title, &partition, &path, &active);
if (r == -ENOENT) {
log_debug_errno(r, "Boot option 0x%04X referenced but missing, ignoring: %m", id);
return 0;
}
if (r < 0)
return log_error_errno(r, "Failed to read boot option %u: %m", id);
return log_error_errno(r, "Failed to read boot option 0x%04X: %m", id);
/* print only configured entries with partition information */
if (!path || sd_id128_is_null(partition)) {
log_debug("Ignoring boot entry %u without partition information.", id);
log_debug("Ignoring boot entry 0x%04X without partition information.", id);
return 0;
}

View File

@ -471,7 +471,6 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
_cleanup_free_ char16_t *device_part_uuid = NULL;
assert(config);
assert(loaded_image_path);
clear_screen(COLOR_NORMAL);
console_query_mode(&x_max, &y_max);
@ -619,7 +618,6 @@ static bool menu_run(
assert(config);
assert(chosen_entry);
assert(loaded_image_path);
EFI_STATUS err;
UINTN visible_max = 0;
@ -1478,7 +1476,7 @@ static void config_entry_add_type1(
entry->loader = xstra_to_path(value);
/* do not add an entry for ourselves */
if (loaded_image_path && strcaseeq16(entry->loader, loaded_image_path)) {
if (strcaseeq16(entry->loader, loaded_image_path)) {
entry->type = LOADER_UNDEFINED;
break;
}
@ -1908,12 +1906,11 @@ static ConfigEntry *config_entry_add_loader_auto(
assert(root_dir);
assert(id);
assert(title);
assert(loader || loaded_image_path);
if (!config->auto_entries)
return NULL;
if (loaded_image_path) {
if (!loader) {
loader = L"\\EFI\\BOOT\\BOOT" EFI_MACHINE_TYPE_NAME ".efi";
/* We are trying to add the default EFI loader here,
@ -2562,7 +2559,6 @@ static void export_variables(
char16_t uuid[37];
assert(loaded_image);
assert(loaded_image_path);
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
@ -2591,7 +2587,6 @@ static void config_load_all_entries(
assert(config);
assert(loaded_image);
assert(loaded_image_path);
assert(root_dir);
config_load_defaults(config, root_dir);
@ -2650,7 +2645,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
_cleanup_(file_closep) EFI_FILE *root_dir = NULL;
_cleanup_(config_free) Config config = {};
char16_t *loaded_image_path;
_cleanup_free_ char16_t *loaded_image_path = NULL;
EFI_STATUS err;
uint64_t init_usec;
bool menu = false;
@ -2676,9 +2671,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
if (err != EFI_SUCCESS)
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
err = device_path_to_str(loaded_image->FilePath, &loaded_image_path);
if (err != EFI_SUCCESS)
return log_error_status_stall(err, L"Error getting loaded image path: %m");
(void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
export_variables(loaded_image, loaded_image_path, init_usec);

View File

@ -51,25 +51,23 @@ static EFI_STATUS load_one_driver(
}
EFI_STATUS reconnect_all_drivers(void) {
_cleanup_free_ EFI_HANDLE *handles = NULL;
UINTN n_handles = 0;
EFI_STATUS err;
_cleanup_free_ EFI_HANDLE *handles = NULL;
size_t n_handles = 0;
EFI_STATUS err;
/* Reconnects all handles, so that any loaded drivers can take effect. */
/* Reconnects all handles, so that any loaded drivers can take effect. */
err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
if (err != EFI_SUCCESS)
return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
if (err != EFI_SUCCESS)
return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
for (UINTN i = 0; i < n_handles; i++) {
err = BS->ConnectController(handles[i], NULL, NULL, true);
if (err == EFI_NOT_FOUND) /* No drivers for this handle */
continue;
if (err != EFI_SUCCESS)
log_error_status_stall(err, L"Failed to reconnect handle %" PRIuN L", ignoring: %r", i, err);
}
for (size_t i = 0; i < n_handles; i++)
/* Some firmware gives us some bogus handles (or they might become bad due to
* reconnecting everything). Security policy may also prevent us from doing so too.
* There is nothing we can realistically do on errors anyways, so just ignore them. */
(void) BS->ConnectController(handles[i], NULL, NULL, true);
return EFI_SUCCESS;
return EFI_SUCCESS;
}
EFI_STATUS load_drivers(

View File

@ -20,35 +20,26 @@
#define STUB_PAYLOAD_GUID \
{ 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
static EFIAPI EFI_STATUS security_hook(
const SecurityOverride *this, uint32_t authentication_status, const EFI_DEVICE_PATH *file) {
typedef struct {
const void *addr;
size_t len;
const EFI_DEVICE_PATH *device_path;
} ValidationContext;
assert(this);
assert(this->hook == security_hook);
static bool validate_payload(
const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
if (file == this->payload_device_path)
return EFI_SUCCESS;
const ValidationContext *payload = ASSERT_PTR(ctx);
return this->original_security->FileAuthenticationState(
this->original_security, authentication_status, file);
}
if (device_path != payload->device_path)
return false;
static EFIAPI EFI_STATUS security2_hook(
const SecurityOverride *this,
const EFI_DEVICE_PATH *device_path,
void *file_buffer,
size_t file_size,
BOOLEAN boot_policy) {
/* Security arch (1) protocol does not provide a file buffer. Instead we are supposed to fetch the payload
* ourselves, which is not needed as we already have everything in memory and the device paths match. */
if (file_buffer && (file_buffer != payload->addr || file_size != payload->len))
return false;
assert(this);
assert(this->hook == security2_hook);
if (file_buffer == this->payload && file_size == this->payload_len &&
device_path == this->payload_device_path)
return EFI_SUCCESS;
return this->original_security2->FileAuthentication(
this->original_security2, device_path, file_buffer, file_size, boot_policy);
return true;
}
static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len, EFI_HANDLE *ret_image) {
@ -79,19 +70,13 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
/* We want to support unsigned kernel images as payload, which is safe to do under secure boot
* because it is embedded in this stub loader (and since it is already running it must be trusted). */
SecurityOverride security_override = {
.hook = security_hook,
.payload = source,
.payload_len = len,
.payload_device_path = &payload_device_path.payload.Header,
}, security2_override = {
.hook = security2_hook,
.payload = source,
.payload_len = len,
.payload_device_path = &payload_device_path.payload.Header,
};
install_security_override(&security_override, &security2_override);
install_security_override(
validate_payload,
&(ValidationContext) {
.addr = source,
.len = len,
.device_path = &payload_device_path.payload.Header,
});
EFI_STATUS ret = BS->LoadImage(
/*BootPolicy=*/false,
@ -101,7 +86,7 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
len,
ret_image);
uninstall_security_override(&security_override, &security2_override);
uninstall_security_override();
return ret;
}

View File

@ -127,69 +127,91 @@ out_deallocate:
return err;
}
static EFI_STATUS install_security_override_one(EFI_GUID guid, SecurityOverride *override) {
EFI_STATUS err;
static struct SecurityOverride {
EFI_SECURITY_ARCH_PROTOCOL *security;
EFI_SECURITY2_ARCH_PROTOCOL *security2;
EFI_SECURITY_FILE_AUTHENTICATION_STATE original_hook;
EFI_SECURITY2_FILE_AUTHENTICATION original_hook2;
assert(override);
security_validator_t validator;
const void *validator_ctx;
} security_override;
_cleanup_free_ EFI_HANDLE *handles = NULL;
size_t n_handles = 0;
static EFIAPI EFI_STATUS security_hook(
const EFI_SECURITY_ARCH_PROTOCOL *this,
uint32_t authentication_status,
const EFI_DEVICE_PATH *file) {
err = BS->LocateHandleBuffer(ByProtocol, &guid, NULL, &n_handles, &handles);
if (err != EFI_SUCCESS)
/* No security arch protocol around? */
return err;
assert(security_override.validator);
assert(security_override.security);
assert(security_override.original_hook);
/* There should only ever be one security arch protocol instance, but let's be paranoid here. */
assert(n_handles == 1);
if (security_override.validator(security_override.validator_ctx, file, NULL, 0))
return EFI_SUCCESS;
void *security = NULL;
err = BS->LocateProtocol(&guid, NULL, &security);
if (err != EFI_SUCCESS)
return log_error_status_stall(err, u"Error getting security arch protocol: %r", err);
err = BS->ReinstallProtocolInterface(handles[0], &guid, security, override);
if (err != EFI_SUCCESS)
return log_error_status_stall(err, u"Error overriding security arch protocol: %r", err);
override->original = security;
override->original_handle = handles[0];
return EFI_SUCCESS;
return security_override.original_hook(security_override.security, authentication_status, file);
}
/* This replaces the platform provided security arch protocols (defined in the UEFI Platform Initialization
* Specification) with the provided override instances. If not running in secure boot or the protocols are
* not available nothing happens. The override instances are provided with the necessary info to undo this
* in uninstall_security_override(). */
void install_security_override(SecurityOverride *override, SecurityOverride *override2) {
assert(override);
assert(override2);
static EFIAPI EFI_STATUS security2_hook(
const EFI_SECURITY2_ARCH_PROTOCOL *this,
const EFI_DEVICE_PATH *device_path,
void *file_buffer,
size_t file_size,
BOOLEAN boot_policy) {
assert(security_override.validator);
assert(security_override.security2);
assert(security_override.original_hook2);
if (security_override.validator(security_override.validator_ctx, device_path, file_buffer, file_size))
return EFI_SUCCESS;
return security_override.original_hook2(
security_override.security2, device_path, file_buffer, file_size, boot_policy);
}
/* This replaces the platform provided security arch protocols hooks (defined in the UEFI Platform
* Initialization Specification) with our own that uses the given validator to decide if a image is to be
* trusted. If not running in secure boot or the protocols are not available nothing happens. The override
* must be removed with uninstall_security_override() after LoadImage() has been called.
*
* This is a hack as we do not own the security protocol instances and modifying them is not an official part
* of their spec. But there is little else we can do to circumvent secure boot short of implementing our own
* PE loader. We could replace the firmware instances with our own instance using
* ReinstallProtocolInterface(), but some firmware will still use the old ones. */
void install_security_override(security_validator_t validator, const void *validator_ctx) {
EFI_STATUS err;
assert(validator);
if (!secure_boot_enabled())
return;
(void) install_security_override_one((EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, override);
(void) install_security_override_one((EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, override2);
security_override = (struct SecurityOverride) {
.validator = validator,
.validator_ctx = validator_ctx,
};
EFI_SECURITY_ARCH_PROTOCOL *security = NULL;
err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, NULL, (void **) &security);
if (err == EFI_SUCCESS) {
security_override.security = security;
security_override.original_hook = security->FileAuthenticationState;
security->FileAuthenticationState = security_hook;
}
EFI_SECURITY2_ARCH_PROTOCOL *security2 = NULL;
err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, NULL, (void **) &security2);
if (err == EFI_SUCCESS) {
security_override.security2 = security2;
security_override.original_hook2 = security2->FileAuthentication;
security2->FileAuthentication = security2_hook;
}
}
void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2) {
assert(override);
assert(override2);
/* We use assert_se here to guarantee the system is not in a weird state in the unlikely case of an
* error restoring the original protocols. */
if (override->original_handle)
assert_se(BS->ReinstallProtocolInterface(
override->original_handle,
&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
override,
override->original) == EFI_SUCCESS);
if (override2->original_handle)
assert_se(BS->ReinstallProtocolInterface(
override2->original_handle,
&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
override2,
override2->original) == EFI_SUCCESS);
void uninstall_security_override(void) {
if (security_override.original_hook)
security_override.security->FileAuthenticationState = security_override.original_hook;
if (security_override.original_hook2)
security_override.security2->FileAuthentication = security_override.original_hook2;
}

View File

@ -17,23 +17,11 @@ SecureBootMode secure_boot_mode(void);
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path);
typedef struct {
void *hook;
typedef bool (*security_validator_t)(
const void *ctx,
const EFI_DEVICE_PATH *device_path,
const void *file_buffer,
size_t file_size);
/* End of EFI_SECURITY_ARCH(2)_PROTOCOL. The rest is our own protocol instance data. */
EFI_HANDLE original_handle;
union {
void *original;
EFI_SECURITY_ARCH_PROTOCOL *original_security;
EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
};
/* Used by the stub to identify the embedded image. */
const void *payload;
size_t payload_len;
const EFI_DEVICE_PATH *payload_device_path;
} SecurityOverride;
void install_security_override(SecurityOverride *override, SecurityOverride *override2);
void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2);
void install_security_override(security_validator_t validator, const void *validator_ctx);
void uninstall_security_override(void);

View File

@ -23,7 +23,7 @@
#endif
struct ShimLock {
EFI_STATUS __sysv_abi__ (*shim_verify) (void *buffer, uint32_t size);
EFI_STATUS __sysv_abi__ (*shim_verify) (const void *buffer, uint32_t size);
/* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
* see shim.c/shim.h and PeHeader.h in the github shim repo */
@ -41,79 +41,45 @@ bool shim_loaded(void) {
return BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) == EFI_SUCCESS;
}
static bool shim_validate(void *data, uint32_t size) {
struct ShimLock *shim_lock;
if (!data)
return false;
if (BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) != EFI_SUCCESS)
return false;
if (!shim_lock)
return false;
return shim_lock->shim_verify(data, size) == EFI_SUCCESS;
}
static EFIAPI EFI_STATUS security2_hook(
const SecurityOverride *this,
const EFI_DEVICE_PATH *device_path,
void *file_buffer,
UINTN file_size,
BOOLEAN boot_policy) {
assert(this);
assert(this->hook == security2_hook);
if (shim_validate(file_buffer, file_size))
return EFI_SUCCESS;
return this->original_security2->FileAuthentication(
this->original_security2, device_path, file_buffer, file_size, boot_policy);
}
static EFIAPI EFI_STATUS security_hook(
const SecurityOverride *this,
uint32_t authentication_status,
const EFI_DEVICE_PATH *device_path) {
static bool shim_validate(
const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
EFI_STATUS err;
_cleanup_free_ char *file_buffer_owned = NULL;
assert(this);
assert(this->hook == security_hook);
if (!file_buffer) {
if (!device_path)
return false;
if (!device_path)
return this->original_security->FileAuthenticationState(
this->original_security, authentication_status, device_path);
EFI_HANDLE device_handle;
EFI_DEVICE_PATH *file_dp = (EFI_DEVICE_PATH *) device_path;
err = BS->LocateDevicePath(&FileSystemProtocol, &file_dp, &device_handle);
if (err != EFI_SUCCESS)
return false;
EFI_HANDLE device_handle;
EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) device_path;
err = BS->LocateDevicePath(&FileSystemProtocol, &dp, &device_handle);
_cleanup_(file_closep) EFI_FILE *root = NULL;
err = open_volume(device_handle, &root);
if (err != EFI_SUCCESS)
return false;
_cleanup_free_ char16_t *dp_str = NULL;
err = device_path_to_str(file_dp, &dp_str);
if (err != EFI_SUCCESS)
return false;
err = file_read(root, dp_str, 0, 0, &file_buffer_owned, &file_size);
if (err != EFI_SUCCESS)
return false;
file_buffer = file_buffer_owned;
}
struct ShimLock *shim_lock;
err = BS->LocateProtocol((EFI_GUID *) SHIM_LOCK_GUID, NULL, (void **) &shim_lock);
if (err != EFI_SUCCESS)
return err;
return false;
_cleanup_(file_closep) EFI_FILE *root = NULL;
err = open_volume(device_handle, &root);
if (err != EFI_SUCCESS)
return err;
_cleanup_free_ char16_t *dp_str = NULL;
err = device_path_to_str(dp, &dp_str);
if (err != EFI_SUCCESS)
return err;
char *file_buffer;
size_t file_size;
err = file_read(root, dp_str, 0, 0, &file_buffer, &file_size);
if (err != EFI_SUCCESS)
return err;
if (shim_validate(file_buffer, file_size))
return EFI_SUCCESS;
return this->original_security->FileAuthenticationState(
this->original_security, authentication_status, device_path);
return shim_lock->shim_verify(file_buffer, file_size) == EFI_SUCCESS;
}
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image) {
@ -122,20 +88,14 @@ EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path
bool have_shim = shim_loaded();
SecurityOverride security_override = {
.hook = security_hook,
}, security2_override = {
.hook = security2_hook,
};
if (have_shim)
install_security_override(&security_override, &security2_override);
install_security_override(shim_validate, NULL);
EFI_STATUS ret = BS->LoadImage(
/*BootPolicy=*/false, parent, (EFI_DEVICE_PATH *) device_path, NULL, 0, ret_image);
if (have_shim)
uninstall_security_override(&security_override, &security2_override);
uninstall_security_override();
return ret;
}

View File

@ -772,19 +772,51 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text;
EFI_STATUS err;
_cleanup_free_ char16_t *str = NULL;
assert(dp);
assert(ret);
err = BS->LocateProtocol(&(EFI_GUID) EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, NULL, (void **) &dp_to_text);
if (err != EFI_SUCCESS)
return err;
if (err != EFI_SUCCESS) {
/* If the device path to text protocol is not available we can still do a best-effort attempt
* to convert it ourselves if we are given filepath-only device path. */
char16_t *str = dp_to_text->ConvertDevicePathToText(dp, false, false);
size_t size = 0;
for (const EFI_DEVICE_PATH *node = dp; !IsDevicePathEnd(node);
node = NextDevicePathNode(node)) {
if (DevicePathType(node) != MEDIA_DEVICE_PATH ||
DevicePathSubType(node) != MEDIA_FILEPATH_DP)
return err;
size_t path_size = DevicePathNodeLength(node);
if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t))
return EFI_INVALID_PARAMETER;
path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName);
_cleanup_free_ char16_t *old = str;
str = xmalloc(size + path_size);
if (old) {
memcpy(str, old, size);
str[size / sizeof(char16_t) - 1] = '\\';
}
memcpy(str + (size / sizeof(char16_t)),
((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName),
path_size);
size += path_size;
}
*ret = TAKE_PTR(str);
return EFI_SUCCESS;
}
str = dp_to_text->ConvertDevicePathToText(dp, false, false);
if (!str)
return EFI_OUT_OF_RESOURCES;
*ret = str;
*ret = TAKE_PTR(str);
return EFI_SUCCESS;
}

View File

@ -897,7 +897,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
}
_cleanup_free_ void *sig = malloc(ss);
if (!ss) {
if (!sig) {
r = log_oom();
goto finish;
}

View File

@ -113,9 +113,9 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
if (r >= 0) {
if (type == SELINUX_AVC)
audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, getuid());
else if (type == SELINUX_ERROR)
audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, 0);
audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, getuid());
return 0;
}

View File

@ -948,11 +948,11 @@ static int activation_details_timer_append_env(ActivationDetails *details, char
if (!dual_timestamp_is_set(&t->last_trigger))
return 0;
r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=%" USEC_FMT, t->last_trigger.realtime);
r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=" USEC_FMT, t->last_trigger.realtime);
if (r < 0)
return r;
r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=%" USEC_FMT, t->last_trigger.monotonic);
r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=" USEC_FMT, t->last_trigger.monotonic);
if (r < 0)
return r;
@ -974,7 +974,7 @@ static int activation_details_timer_append_pair(ActivationDetails *details, char
if (r < 0)
return r;
r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.realtime);
r = strv_extendf(strv, USEC_FMT, t->last_trigger.realtime);
if (r < 0)
return r;
@ -982,7 +982,7 @@ static int activation_details_timer_append_pair(ActivationDetails *details, char
if (r < 0)
return r;
r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.monotonic);
r = strv_extendf(strv, USEC_FMT, t->last_trigger.monotonic);
if (r < 0)
return r;

View File

@ -55,7 +55,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
size_t sw_alloc = MAX(h->sw_alloc, 1u);
buf2 = malloc(sw_alloc);
if (!buf) {
if (!buf2) {
log_oom();
return 0;
}

View File

@ -158,7 +158,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_head(j));
assert_ret(sd_journal_previous(j) == 0);
assert_ret(sd_journal_next(j));
test_check_numbers_down(j, 4);
sd_journal_close(j);
@ -167,7 +166,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_tail(j));
assert_ret(sd_journal_next(j) == 0);
assert_ret(sd_journal_previous(j));
test_check_numbers_up(j, 4);
sd_journal_close(j);
@ -176,7 +174,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_tail(j));
assert_ret(sd_journal_next(j) == 0);
assert_ret(r = sd_journal_previous_skip(j, 4));
assert_se(r == 4);
test_check_numbers_down(j, 4);
@ -186,7 +183,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_head(j));
assert_ret(sd_journal_previous(j) == 0);
assert_ret(r = sd_journal_next_skip(j, 4));
assert_se(r == 4);
test_check_numbers_up(j, 4);

View File

@ -158,8 +158,9 @@ if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-info ]; then
[ -n "$MACHINE_ID" ] && \
log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-info"
fi
if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-id ]; then
if [ -z "$MACHINE_ID" ] && [ -s /etc/machine-id ]; then
read -r MACHINE_ID </etc/machine-id
[ "$MACHINE_ID" = "uninitialized" ] && unset MACHINE_ID
[ -n "$MACHINE_ID" ] && \
log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-id"
fi

View File

@ -3529,7 +3529,7 @@ static int bus_add_match_full(
s);
if (r < 0)
return r;
goto finish;
/* Make the slot of the match call floating now. We need the reference, but we don't
* want that this match pins the bus object, hence we first create it non-floating, but

View File

@ -606,9 +606,9 @@ static int find_location_for_match(
/* FIXME: missing: find by monotonic */
if (j->current_location.type == LOCATION_HEAD)
return direction == DIRECTION_DOWN ? journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset) : 0;
return journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset);
if (j->current_location.type == LOCATION_TAIL)
return direction == DIRECTION_UP ? journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset) : 0;
return journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset);
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum_for_data(f, d, j->current_location.seqnum, direction, ret, offset);
if (j->current_location.monotonic_set) {
@ -701,9 +701,9 @@ static int find_location_with_matches(
/* No matches is simple */
if (j->current_location.type == LOCATION_HEAD)
return direction == DIRECTION_DOWN ? journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset) : 0;
return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset);
if (j->current_location.type == LOCATION_TAIL)
return direction == DIRECTION_UP ? journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset) : 0;
return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset);
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
if (j->current_location.monotonic_set) {

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/if_arp.h>
#include <net/if.h> /* IFF_LOOPBACK */
#include <net/if_arp.h> /* ARPHRD_ETHER */
#include "sd-dhcp-client.h"
#include "sd-ipv4acd.h"

View File

@ -1178,7 +1178,7 @@ static int link_get_network(Link *link, Network **ret) {
return -ENOENT;
}
static int link_reconfigure_impl(Link *link, bool force) {
int link_reconfigure_impl(Link *link, bool force) {
Network *network = NULL;
NetDev *netdev = NULL;
int r;

View File

@ -234,6 +234,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
int link_reconfigure_impl(Link *link, bool force);
int link_reconfigure(Link *link, bool force);
int link_reconfigure_after_sleep(Link *link);

View File

@ -269,6 +269,18 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
if (link->wlan_iftype == NL80211_IFTYPE_STATION && link->ssid)
log_link_info(link, "Connected WiFi access point: %s (%s)",
link->ssid, ETHER_ADDR_TO_STR(&link->bssid));
/* Sometimes, RTM_NEWLINK message with carrier is received earlier than NL80211_CMD_CONNECT.
* To make SSID= or other WiFi related settings in [Match] section work, let's try to
* reconfigure the interface. */
if (link->ssid && link_has_carrier(link)) {
r = link_reconfigure_impl(link, /* force = */ false);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
link_enter_failed(link);
return 0;
}
}
break;
}
case NL80211_CMD_DISCONNECT:

View File

@ -88,6 +88,7 @@ static int add_syscall_filters(
{ 0, "sched_getparam" },
{ 0, "sched_getscheduler" },
{ 0, "sched_rr_get_interval" },
{ 0, "sched_rr_get_interval_time64" },
{ 0, "sched_yield" },
{ 0, "seccomp" },
{ 0, "sendfile" },

View File

@ -164,7 +164,7 @@ int oomd_fetch_cgroup_oom_preference(OomdCGroupContext *ctx, const char *prefix)
if (r < 0)
return log_debug_errno(r, "Failed to get owner/group from %s: %m", ctx->path);
if (uid == prefix_uid) {
if (uid == prefix_uid || uid == 0) {
/* Ignore most errors when reading the xattr since it is usually unset and cgroup xattrs are only used
* as an optional feature of systemd-oomd (and the system might not even support them). */
r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, ctx->path, "user.oomd_avoid");

View File

@ -475,9 +475,9 @@ static void test_oomd_fetch_cgroup_oom_preference(void) {
/* Assert that avoid/omit are not set if the cgroup and prefix are not
* owned by the same user.*/
if (test_xattrs && !empty_or_root(ctx->path)) {
if (test_xattrs && !empty_or_root(cgroup)) {
ctx = oomd_cgroup_context_free(ctx);
assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 65534, 0) >= 0);
assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 61183, 0) >= 0);
assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
assert_se(oomd_fetch_cgroup_oom_preference(ctx, NULL) == 0);

View File

@ -4387,13 +4387,15 @@ static int context_write_partition_table(
log_info("Wiped block device.");
r = context_discard_range(context, 0, context->total);
if (r == -EOPNOTSUPP)
log_info("Storage does not support discard, not discarding entire block device data.");
else if (r < 0)
return log_error_errno(r, "Failed to discard entire block device: %m");
else if (r > 0)
log_info("Discarded entire block device.");
if (arg_discard) {
r = context_discard_range(context, 0, context->total);
if (r == -EOPNOTSUPP)
log_info("Storage does not support discard, not discarding entire block device data.");
else if (r < 0)
return log_error_errno(r, "Failed to discard entire block device: %m");
else if (r > 0)
log_info("Discarded entire block device.");
}
}
r = fdisk_get_partitions(context->fdisk_context, &original_table);

View File

@ -1131,7 +1131,7 @@ static int attach_unit_file(
(void) mkdir_parents(where, 0755);
if (mkdir(where, 0755) < 0) {
if (errno != EEXIST)
return -errno;
return log_debug_errno(errno, "Failed to create attach directory %s: %m", where);
} else
(void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, where, NULL);
@ -1145,7 +1145,7 @@ static int attach_unit_file(
if (mkdir(dropin_dir, 0755) < 0) {
if (errno != EEXIST)
return -errno;
return log_debug_errno(errno, "Failed to create drop-in directory %s: %m", dropin_dir);
} else
(void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, dropin_dir, NULL);
@ -1392,7 +1392,7 @@ int portable_attach(
r = attach_unit_file(&paths, image->path, image->type, extension_images,
item, profile, flags, changes, n_changes);
if (r < 0)
return r;
return sd_bus_error_set_errnof(error, r, "Failed to attach unit '%s': %m", item->name);
}
/* We don't care too much for the image symlink, it's just a convenience thing, it's not necessary for proper

View File

@ -424,7 +424,7 @@ static int dns_scope_socket(
return r;
}
if (s->link) {
if (ifindex != 0) {
r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
if (r < 0)
return r;

View File

@ -648,6 +648,11 @@ int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeature
int dns_server_ifindex(const DnsServer *s) {
assert(s);
/* For loopback addresses, go via the loopback interface, regardless which interface this is linked
* to. */
if (in_addr_is_localhost(s->family, &s->address))
return LOOPBACK_IFINDEX;
/* The link ifindex always takes precedence */
if (s->link)
return s->link->ifindex;

View File

@ -14,6 +14,19 @@
#include "resolved-dnstls.h"
#include "resolved-manager.h"
static char *dnstls_error_string(int ssl_error, char *buf, size_t count) {
assert(buf || count == 0);
if (ssl_error == SSL_ERROR_SSL)
ERR_error_string_n(ERR_get_error(), buf, count);
else
snprintf(buf, count, "SSL_get_error()=%d", ssl_error);
return buf;
}
#define DNSTLS_ERROR_BUFSIZE 256
#define DNSTLS_ERROR_STRING(error) \
dnstls_error_string((error), (char[DNSTLS_ERROR_BUFSIZE]){}, DNSTLS_ERROR_BUFSIZE)
static int dnstls_flush_write_buffer(DnsStream *stream) {
ssize_t ss;
@ -97,26 +110,18 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
if (server->server_name) {
r = SSL_set_tlsext_host_name(s, server->server_name);
if (r <= 0) {
char errbuf[256];
error = ERR_get_error();
ERR_error_string_n(error, errbuf, sizeof(errbuf));
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", errbuf);
}
if (r <= 0)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to set server name: %s", DNSTLS_ERROR_STRING(SSL_ERROR_SSL));
}
ERR_clear_error();
stream->dnstls_data.handshake = SSL_do_handshake(s);
if (stream->dnstls_data.handshake <= 0) {
error = SSL_get_error(s, stream->dnstls_data.handshake);
if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) {
char errbuf[256];
ERR_error_string_n(error, errbuf, sizeof(errbuf));
if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE))
return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
"Failed to invoke SSL_do_handshake: %s", errbuf);
}
"Failed to invoke SSL_do_handshake: %s", DNSTLS_ERROR_STRING(error));
}
stream->encrypted = true;
@ -177,12 +182,8 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) {
} else if (error == SSL_ERROR_SYSCALL) {
if (errno > 0)
log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m");
} else {
char errbuf[256];
ERR_error_string_n(error, errbuf, sizeof(errbuf));
log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf);
}
} else
log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(error));
}
stream->dnstls_events = 0;
@ -206,14 +207,10 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) {
return r;
return -EAGAIN;
} else {
char errbuf[256];
ERR_error_string_n(error, errbuf, sizeof(errbuf));
} else
return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
"Failed to invoke SSL_do_handshake: %s",
errbuf);
}
DNSTLS_ERROR_STRING(error));
}
stream->dnstls_events = 0;
@ -275,12 +272,8 @@ int dnstls_stream_shutdown(DnsStream *stream, int error) {
} else if (ssl_error == SSL_ERROR_SYSCALL) {
if (errno > 0)
log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m");
} else {
char errbuf[256];
ERR_error_string_n(ssl_error, errbuf, sizeof(errbuf));
log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf);
}
} else
log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(ssl_error));
}
stream->dnstls_events = 0;
@ -307,10 +300,7 @@ static ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t co
stream->dnstls_events = 0;
ss = 0;
} else {
char errbuf[256];
ERR_error_string_n(error, errbuf, sizeof(errbuf));
log_debug("Failed to invoke SSL_write: %s", errbuf);
log_debug("Failed to invoke SSL_write: %s", DNSTLS_ERROR_STRING(error));
stream->dnstls_events = 0;
ss = -EPIPE;
}
@ -375,10 +365,7 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
stream->dnstls_events = 0;
ss = 0;
} else {
char errbuf[256];
ERR_error_string_n(error, errbuf, sizeof(errbuf));
log_debug("Failed to invoke SSL_read: %s", errbuf);
log_debug("Failed to invoke SSL_read: %s", DNSTLS_ERROR_STRING(error));
stream->dnstls_events = 0;
ss = -EPIPE;
}

View File

@ -994,6 +994,12 @@ static int boot_config_find(const BootConfig *config, const char *id) {
if (!id)
return -1;
if (id[0] == '@') {
if (!strcaseeq(id, "@saved"))
return -1;
id = config->entry_selected;
}
for (size_t i = 0; i < config->n_entries; i++)
if (fnmatch(id, config->entries[i].id, FNM_CASEFOLD) == 0)
return i;

View File

@ -1010,19 +1010,13 @@ static int dissect_image(
log_debug("No root partition found of the native architecture, falling back to a root "
"partition of the secondary architecture.");
m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
zero(m->partitions[PARTITION_ROOT_SECONDARY]);
m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG];
zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY]);
m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
zero(m->partitions[PARTITION_USR_SECONDARY]);
m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_ROOT_OTHER].found = false;
m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
@ -1044,19 +1038,13 @@ static int dissect_image(
"falling back to a root partition of a non-native architecture (%s).",
architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_OTHER];
zero(m->partitions[PARTITION_ROOT_OTHER]);
m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_OTHER_VERITY];
zero(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG];
zero(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER]);
m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
zero(m->partitions[PARTITION_USR_OTHER]);
m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
}
/* Hmm, we found a signature partition but no Verity data? Something is off. */
@ -1083,12 +1071,9 @@ static int dissect_image(
"partition of the secondary architecture.");
/* Upgrade secondary arch to primary */
m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
zero(m->partitions[PARTITION_USR_SECONDARY]);
m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR_OTHER].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
@ -1105,12 +1090,9 @@ static int dissect_image(
architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
/* Upgrade other arch to primary */
m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
zero(m->partitions[PARTITION_USR_OTHER]);
m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
}
/* Hmm, we found a signature partition but no Verity data? Something is off. */
@ -1327,11 +1309,11 @@ static int is_loop_device(const char *path) {
return true;
}
static int run_fsck(const char *node, const char *fstype) {
static int run_fsck(int node_fd, const char *fstype) {
int r, exit_status;
pid_t pid;
assert(node);
assert(node_fd >= 0);
assert(fstype);
r = fsck_exists_for_fstype(fstype);
@ -1340,16 +1322,20 @@ static int run_fsck(const char *node, const char *fstype) {
return 0;
}
if (r == 0) {
log_debug("Not checking partition %s, as fsck for %s does not exist.", node, fstype);
log_debug("Not checking partition %s, as fsck for %s does not exist.", FORMAT_PROC_FD_PATH(node_fd), fstype);
return 0;
}
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO, &pid);
r = safe_fork_full(
"(fsck)",
&node_fd, 1, /* Leave the node fd open */
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOEXEC_OFF,
&pid);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
if (r == 0) {
/* Child */
execl("/sbin/fsck", "/sbin/fsck", "-aT", node, NULL);
execl("/sbin/fsck", "/sbin/fsck", "-aT", FORMAT_PROC_FD_PATH(node_fd), NULL);
log_open();
log_debug_errno(errno, "Failed to execl() fsck: %m");
_exit(FSCK_OPERATIONAL_ERROR);
@ -1439,7 +1425,7 @@ static int mount_partition(
rw = m->rw && !(flags & DISSECT_IMAGE_MOUNT_READ_ONLY);
if (FLAGS_SET(flags, DISSECT_IMAGE_FSCK) && rw) {
r = run_fsck(node, fstype);
r = run_fsck(m->mount_node_fd, fstype);
if (r < 0)
return r;
}

View File

@ -40,6 +40,12 @@ struct DissectedPartition {
.architecture = _ARCHITECTURE_INVALID, \
.mount_node_fd = -1, \
})
#define TAKE_PARTITION(p) \
({ \
DissectedPartition *_pp = &(p), _p = *_pp; \
*_pp = DISSECTED_PARTITION_NULL; \
_p; \
})
typedef enum PartitionDesignator {
PARTITION_ROOT,

View File

@ -165,59 +165,65 @@ static int verify_esp_udev(
r = sd_device_get_devname(d, &node);
if (r < 0)
return log_error_errno(r, "Failed to get device node: %m");
return log_device_error_errno(d, r, "Failed to get device node: %m");
r = sd_device_get_property_value(d, "ID_FS_TYPE", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_error_errno(d, r, "Failed to get device property: %m");
if (!streq(v, "vfat"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" is not FAT.", node );
return log_device_full_errno(d,
searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" is not FAT.", node );
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_full_errno(d,
searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
"Failed to get device property: %m");
if (!streq(v, "gpt"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" is not on a GPT partition table.", node);
return log_device_full_errno(d,
searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" is not on a GPT partition table.", node);
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_error_errno(d, r, "Failed to get device property: %m");
if (sd_id128_string_equal(v, SD_GPT_ESP) <= 0)
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
return log_device_full_errno(d,
searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
r = sd_device_get_property_value(d, "ID_PART_ENTRY_UUID", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_error_errno(d, r, "Failed to get device property: %m");
r = sd_id128_from_string(v, &uuid);
if (r < 0)
return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v);
return log_device_error_errno(d, r, "Partition \"%s\" has invalid UUID \"%s\".", node, v);
r = sd_device_get_property_value(d, "ID_PART_ENTRY_NUMBER", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_error_errno(d, r, "Failed to get device property: %m");
r = safe_atou32(v, &part);
if (r < 0)
return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.");
return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_NUMBER field.");
r = sd_device_get_property_value(d, "ID_PART_ENTRY_OFFSET", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_error_errno(d, r, "Failed to get device property: %m");
r = safe_atou64(v, &pstart);
if (r < 0)
return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.");
return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_OFFSET field.");
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SIZE", &v);
if (r < 0)
return log_error_errno(r, "Failed to get device property: %m");
return log_device_error_errno(d, r, "Failed to get device property: %m");
r = safe_atou64(v, &psize);
if (r < 0)
return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.");
return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_SIZE field.");
if (ret_part)
*ret_part = part;
@ -572,10 +578,11 @@ static int verify_xbootldr_blkid(
else if (r != 0)
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "%s: Failed to probe file system: %m", node);
errno = 0;
r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &type, NULL);
if (r != 0)
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "%s: Failed to probe PART_ENTRY_SCHEME: %m", node);
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(EIO),
"%s: Failed to probe PART_ENTRY_SCHEME: %m", node);
if (streq(type, "gpt")) {
errno = 0;
@ -634,11 +641,14 @@ static int verify_xbootldr_udev(
r = sd_device_get_devname(d, &node);
if (r < 0)
return log_error_errno(r, "Failed to get device node: %m");
return log_device_error_errno(d, r, "Failed to get device node: %m");
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &type);
if (r < 0)
return log_device_error_errno(d, r, "Failed to query ID_PART_ENTRY_SCHEME: %m");
return log_device_full_errno(d,
searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
"Failed to query ID_PART_ENTRY_SCHEME: %m");
if (streq(type, "gpt")) {

View File

@ -32,7 +32,6 @@ int switch_root(const char *new_root,
_cleanup_free_ char *resolved_old_root_after = NULL;
_cleanup_close_ int old_root_fd = -1;
bool old_root_remove;
int r;
assert(new_root);
@ -42,12 +41,16 @@ int switch_root(const char *new_root,
return 0;
/* Check if we shall remove the contents of the old root */
old_root_remove = in_initrd();
if (old_root_remove) {
old_root_fd = open("/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
if (old_root_fd < 0)
return log_error_errno(errno, "Failed to open root directory: %m");
}
old_root_fd = open("/", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (old_root_fd < 0)
return log_error_errno(errno, "Failed to open root directory: %m");
r = fd_is_temporary_fs(old_root_fd);
if (r < 0)
return log_error_errno(r, "Failed to stat root directory: %m");
if (r > 0)
log_debug("Root directory is on tmpfs, will do cleanup later.");
else
old_root_fd = safe_close(old_root_fd);
/* Determine where we shall place the old root after the transition */
r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL);
@ -117,9 +120,8 @@ int switch_root(const char *new_root,
struct stat rb;
if (fstat(old_root_fd, &rb) < 0)
log_warning_errno(errno, "Failed to stat old root directory, leaving: %m");
else
(void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
return log_error_errno(errno, "Failed to stat old root directory: %m");
(void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
}
return 0;

View File

@ -152,8 +152,19 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
if (r < 0)
return log_error_errno(r, "TPM2 support not installed: %m");
if (!device)
if (!device) {
device = secure_getenv("SYSTEMD_TPM2_DEVICE");
if (device)
/* Setting the env var to an empty string forces tpm2-tss' own device picking
* logic to be used. */
device = empty_to_null(device);
else
/* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
* driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
* might be used and we really don't want that, since it is a system service and that creates
* various ordering issues/deadlocks during early boot. */
device = "device:/dev/tpmrm0";
}
if (device) {
const char *param, *driver, *fn;
@ -163,15 +174,27 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
param = strchr(device, ':');
if (param) {
/* Syntax #1: Pair of driver string and arbitrary parameter */
driver = strndupa_safe(device, param - device);
if (isempty(driver))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
param++;
} else {
} else if (path_is_absolute(device) && path_is_valid(device)) {
/* Syntax #2: TPM device node */
driver = "device";
param = device;
}
} else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
fn = strjoina("libtss2-tcti-", driver, ".so.0");
/* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
if (!filename_is_valid(fn))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
dl = dlopen(fn, RTLD_NOW);
if (!dl)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
@ -1094,7 +1117,13 @@ static int tpm2_make_policy_session(
ESYS_TR_NONE,
NULL,
&pubkey_tpm2,
#if HAVE_TSS2_ESYS3
/* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
* hierarchy, older versions need TPM2_RH_* instead. */
ESYS_TR_RH_OWNER,
#else
TPM2_RH_OWNER,
#endif
&pubkey_handle);
if (rc != TSS2_RC_SUCCESS) {
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),

View File

@ -642,9 +642,46 @@ static int device_is_power_sink(sd_device *device) {
return found_sink || !found_source;
}
static bool battery_is_discharging(sd_device *d) {
const char *val;
int r;
assert(d);
r = sd_device_get_sysattr_value(d, "scope", &val);
if (r < 0) {
if (r != -ENOENT)
log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
} else if (streq(val, "Device")) {
log_device_debug(d, "The power supply is a device battery, ignoring device.");
return false;
}
r = device_get_sysattr_bool(d, "present");
if (r < 0)
log_device_debug_errno(d, r, "Failed to read 'present' sysfs attribute, assuming the battery is present: %m");
else if (r == 0) {
log_device_debug(d, "The battery is not present, ignoring the power supply.");
return false;
}
/* Possible values: "Unknown", "Charging", "Discharging", "Not charging", "Full" */
r = sd_device_get_sysattr_value(d, "status", &val);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to read 'status' sysfs attribute, assuming the battery is discharging: %m");
return true;
}
if (!streq(val, "Discharging")) {
log_device_debug(d, "The battery status is '%s', assuming the battery is not used as a power source of this machine.", val);
return false;
}
return true;
}
int on_ac_power(void) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
bool found_ac_online = false, found_battery = false;
bool found_ac_online = false, found_discharging_battery = false;
sd_device *d;
int r;
@ -686,17 +723,10 @@ int on_ac_power(void) {
}
if (streq(val, "Battery")) {
r = sd_device_get_sysattr_value(d, "scope", &val);
if (r < 0) {
if (r != -ENOENT)
log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
} else if (streq(val, "Device")) {
log_device_debug(d, "The power supply is a device battery, ignoring device.");
continue;
if (battery_is_discharging(d)) {
found_discharging_battery = true;
log_device_debug(d, "The power supply is a battery and currently discharging.");
}
found_battery = true;
log_device_debug(d, "The power supply is battery.");
continue;
}
@ -713,11 +743,11 @@ int on_ac_power(void) {
if (found_ac_online) {
log_debug("Found at least one online non-battery power supply, system is running on AC.");
return true;
} else if (found_battery) {
log_debug("Found battery and no online power sources, assuming system is running from battery.");
} else if (found_discharging_battery) {
log_debug("Found at least one discharging battery and no online power sources, assuming system is running from battery.");
return false;
} else {
log_debug("No power supply reported online and no battery, assuming system is running on AC.");
log_debug("No power supply reported online and no discharging battery found, assuming system is running on AC.");
return true;
}
}

View File

@ -2207,9 +2207,10 @@ int verb_show(int argc, char *argv[], void *userdata) {
if (!arg_states && !arg_types) {
if (show_mode == SYSTEMCTL_SHOW_PROPERTIES)
r = show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
else
r = show_system_status(bus);
/* systemctl show --all → show properties of the manager */
return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
r = show_system_status(bus);
if (r < 0)
return r;

View File

@ -622,7 +622,8 @@ tests += [
[files('test-journal-importer.c')],
[files('test-utmp.c')],
[files('test-utmp.c'),
[], [], [], 'ENABLE_UTMP'],
[files('test-udev.c'),
[libudevd_core,

View File

@ -961,22 +961,34 @@ shortcut:
return label_fix_full(fd, /* inode_path= */ NULL, /* label_path= */ path, 0);
}
static int path_open_parent_safe(const char *path) {
static int path_open_parent_safe(const char *path, bool allow_failure) {
_cleanup_free_ char *dn = NULL;
int r, fd;
if (!path_is_normalized(path))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to open parent of '%s': path not normalized.", path);
return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
SYNTHETIC_ERRNO(EINVAL),
"Failed to open parent of '%s': path not normalized%s.",
path,
allow_failure ? ", ignoring" : "");
r = path_extract_directory(path, &dn);
if (r < 0)
return log_error_errno(r, "Unable to determine parent directory of '%s': %m", path);
return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
r,
"Unable to determine parent directory of '%s'%s: %m",
path,
allow_failure ? ", ignoring" : "");
r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd);
r = chase_symlinks(dn, arg_root, allow_failure ? CHASE_SAFE : CHASE_SAFE|CHASE_WARN, NULL, &fd);
if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */
return r;
if (r < 0)
return log_error_errno(r, "Failed to open path '%s': %m", dn);
return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
r,
"Failed to open path '%s'%s: %m",
dn,
allow_failure ? ", ignoring" : "");
return fd;
}
@ -1431,7 +1443,7 @@ static int write_one_file(Item *i, const char *path, CreationMode creation) {
/* Validate the path and keep the fd on the directory for opening the file so we're sure that it
* can't be changed behind our back. */
dir_fd = path_open_parent_safe(path);
dir_fd = path_open_parent_safe(path, i->allow_failure);
if (dir_fd < 0)
return dir_fd;
@ -1481,7 +1493,7 @@ static int create_file(Item *i, const char *path) {
/* Validate the path and keep the fd on the directory for opening the file so we're sure that it
* can't be changed behind our back. */
dir_fd = path_open_parent_safe(path);
dir_fd = path_open_parent_safe(path, i->allow_failure);
if (dir_fd < 0)
return dir_fd;
@ -1549,7 +1561,7 @@ static int truncate_file(Item *i, const char *path) {
/* Validate the path and keep the fd on the directory for opening the file so we're sure that it
* can't be changed behind our back. */
dir_fd = path_open_parent_safe(path);
dir_fd = path_open_parent_safe(path, i->allow_failure);
if (dir_fd < 0)
return dir_fd;
@ -1628,7 +1640,7 @@ static int copy_files(Item *i) {
/* Validate the path and use the returned directory fd for copying the target so we're sure that the
* path can't be changed behind our back. */
dfd = path_open_parent_safe(i->path);
dfd = path_open_parent_safe(i->path, i->allow_failure);
if (dfd < 0)
return dfd;
@ -1664,6 +1676,7 @@ static int create_directory_or_subvolume(
const char *path,
mode_t mode,
bool subvol,
bool allow_failure,
struct stat *ret_st,
CreationMode *ret_creation) {
@ -1679,7 +1692,7 @@ static int create_directory_or_subvolume(
if (r < 0)
return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
pfd = path_open_parent_safe(path);
pfd = path_open_parent_safe(path, allow_failure);
if (pfd < 0)
return pfd;
@ -1720,7 +1733,11 @@ static int create_directory_or_subvolume(
/* Then look at the original error */
if (r < 0)
return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", path);
return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
r,
"Failed to create directory or subvolume \"%s\"%s: %m",
path,
allow_failure ? ", ignoring" : "");
return log_error_errno(errno, "Failed to open directory/subvolume we just created '%s': %m", path);
}
@ -1748,7 +1765,7 @@ static int create_directory(Item *i, const char *path) {
assert(i);
assert(IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY));
fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, &st, &creation);
fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, i->allow_failure, &st, &creation);
if (fd == -EEXIST)
return 0;
if (fd < 0)
@ -1766,7 +1783,7 @@ static int create_subvolume(Item *i, const char *path) {
assert(i);
assert(IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA));
fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, &st, &creation);
fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, i->allow_failure, &st, &creation);
if (fd == -EEXIST)
return 0;
if (fd < 0)
@ -1845,7 +1862,7 @@ static int create_device(Item *i, mode_t file_type) {
/* Validate the path and use the returned directory fd for copying the target so we're sure that the
* path can't be changed behind our back. */
dfd = path_open_parent_safe(i->path);
dfd = path_open_parent_safe(i->path, i->allow_failure);
if (dfd < 0)
return dfd;
@ -1947,7 +1964,7 @@ static int create_fifo(Item *i) {
if (r == O_DIRECTORY)
return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
pfd = path_open_parent_safe(i->path);
pfd = path_open_parent_safe(i->path, i->allow_failure);
if (pfd < 0)
return pfd;
@ -2032,7 +2049,7 @@ static int create_symlink(Item *i) {
if (r == O_DIRECTORY)
return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
pfd = path_open_parent_safe(i->path);
pfd = path_open_parent_safe(i->path, i->allow_failure);
if (pfd < 0)
return pfd;

View File

@ -120,14 +120,14 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
#if defined(SD_GPT_ROOT_NATIVE) && ENABLE_EFI
_cleanup_free_ char *root_id = NULL, *root_label = NULL;
bool found_esp = false;
bool found_esp_or_xbootldr = false;
int r;
assert(pr);
/* Iterate through the partitions on this disk, and see if the
* EFI ESP we booted from is on it. If so, find the first root
* disk, and add a property indicating its partition UUID. */
/* Iterate through the partitions on this disk, and see if the UEFI ESP or XBOOTLDR partition we
* booted from is on it. If so, find the first root disk, and add a property indicating its partition
* UUID. */
errno = 0;
blkid_partlist pl = blkid_probe_get_partitions(pr);
@ -157,21 +157,20 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
if (sd_id128_from_string(stype, &type) < 0)
continue;
if (sd_id128_equal(type, SD_GPT_ESP)) {
sd_id128_t id, esp;
if (sd_id128_in_set(type, SD_GPT_ESP, SD_GPT_XBOOTLDR)) {
sd_id128_t id, esp_or_xbootldr;
/* We found an ESP, let's see if it matches
* the ESP we booted from. */
/* We found an ESP or XBOOTLDR, let's see if it matches the ESP/XBOOTLDR we booted from. */
if (sd_id128_from_string(sid, &id) < 0)
continue;
r = efi_loader_get_device_part_uuid(&esp);
r = efi_loader_get_device_part_uuid(&esp_or_xbootldr);
if (r < 0)
return r;
if (sd_id128_equal(id, esp))
found_esp = true;
if (sd_id128_equal(id, esp_or_xbootldr))
found_esp_or_xbootldr = true;
} else if (sd_id128_equal(type, SD_GPT_ROOT_NATIVE)) {
unsigned long long flags;
@ -195,9 +194,9 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
}
}
/* We found the ESP on this disk, and also found a root
* partition, nice! Let's export its UUID */
if (found_esp && root_id)
/* We found the ESP/XBOOTLDR on this disk, and also found a root partition, nice! Let's export its
* UUID */
if (found_esp_or_xbootldr && root_id)
udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id);
#endif