mirror of
https://git.proxmox.com/git/systemd
synced 2025-08-11 01:34:46 +00:00
New upstream version 252.2
This commit is contained in:
parent
b7785f44d2
commit
c1e08e516e
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
@ -0,0 +1 @@
|
||||
systemd.io
|
@ -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
|
||||
|
@ -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])
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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" },
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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")) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user