1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #31181 from fbuihuu/gpt-auto-more-defensive

gpt-auto-generator: be more defensive when checking the presence of E…
This commit is contained in:
Mike Yuan 2024-02-12 19:12:17 +08:00 committed by GitHub
commit 4d0b06d535
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 52 deletions

7
NEWS
View File

@ -13,6 +13,13 @@ CHANGES WITH 256 in spe:
section, then all assigned VLAN IDs on the interface that are not section, then all assigned VLAN IDs on the interface that are not
configured in the .network file are removed. configured in the .network file are removed.
* systemd-gpt-auto-generator will stop generating units for ESP or
XBOOTLDR partitions if it finds mount entries in the /boot/ or /efi/
hierarchies in fstab. This is to prevent the generator from
interfering with systems where ESP is explicitly configured to be
mounted at some path, for example /boot/efi/ (this type of setup is
obsolete but is still commonly found).
Network Management: Network Management:
* systemd-networkd's proxy support gained a new option to configure * systemd-networkd's proxy support gained a new option to configure

View File

@ -32,18 +32,22 @@
<para><filename>systemd-gpt-auto-generator</filename> is a unit generator that automatically discovers <para><filename>systemd-gpt-auto-generator</filename> is a unit generator that automatically discovers
the root partition, <filename>/home/</filename>, <filename>/srv/</filename>, <filename>/var/</filename>, the root partition, <filename>/home/</filename>, <filename>/srv/</filename>, <filename>/var/</filename>,
<filename>/var/tmp/</filename>, the EFI System Partition, the Extended Boot Loader Partition, and swap <filename>/var/tmp/</filename>, the EFI System Partition (ESP), the Extended Boot Loader Partition
partitions and creates mount and swap units for them, based on the partition type GUIDs of GUID partition (XBOOTLDR), and swap partitions and creates mount and swap units for them, based on the partition type
tables (GPT). See <ulink url="https://uefi.org/specifications">UEFI Specification</ulink>, chapter 5 for GUIDs of GUID partition tables (GPT). See <ulink url="https://uefi.org/specifications">UEFI
more details. It implements the <ulink Specification</ulink>, chapter 5 for more details. It implements the <ulink
url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">Discoverable url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">Discoverable
Partitions Specification</ulink>.</para> Partitions Specification</ulink>.</para>
<para>Note that this generator has no effect on non-GPT systems. It will also not create mount point <para>Note that this generator has no effect on non-GPT systems. It will also not create mount point
configuration for directories which already contain files or if the mount point is explicitly configured configuration for directories which already contain files or if the mount point is explicitly configured
in <citerefentry in <citerefentry
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>. If project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Additionally
the units this generator creates are overridden, for example by units in directories with higher no unit will be created for the ESP or the XBOOTLDR partition if mount entries are found in the
<filename>/boot/</filename> or <filename>/efi/</filename> hierarchies in <citerefentry
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>If the units this generator creates are overridden, for example by units in directories with higher
precedence, drop-ins and additional dependencies created by this generator might still be used.</para> precedence, drop-ins and additional dependencies created by this generator might still be used.</para>
<para>This generator will only look for the root partition on the same physical disk where the EFI System <para>This generator will only look for the root partition on the same physical disk where the EFI System

View File

@ -463,18 +463,6 @@ static int add_automount(
return generator_add_symlink(arg_dest, SPECIAL_LOCAL_FS_TARGET, "wants", unit); return generator_add_symlink(arg_dest, SPECIAL_LOCAL_FS_TARGET, "wants", unit);
} }
static int slash_boot_in_fstab(void) {
static int cache = -1;
if (cache >= 0)
return cache;
cache = fstab_is_mount_point("/boot");
if (cache < 0)
return log_error_errno(cache, "Failed to parse fstab: %m");
return cache;
}
static int add_partition_xbootldr(DissectedPartition *p) { static int add_partition_xbootldr(DissectedPartition *p) {
_cleanup_free_ char *options = NULL; _cleanup_free_ char *options = NULL;
int r; int r;
@ -486,14 +474,6 @@ static int add_partition_xbootldr(DissectedPartition *p) {
return 0; return 0;
} }
r = slash_boot_in_fstab();
if (r < 0)
return r;
if (r > 0) {
log_debug("/boot/ specified in fstab, ignoring XBOOTLDR partition.");
return 0;
}
r = path_is_busy("/boot"); r = path_is_busy("/boot");
if (r < 0) if (r < 0)
return r; return r;
@ -523,18 +503,6 @@ static int add_partition_xbootldr(DissectedPartition *p) {
} }
#if ENABLE_EFI #if ENABLE_EFI
static int slash_efi_in_fstab(void) {
static int cache = -1;
if (cache >= 0)
return cache;
cache = fstab_is_mount_point("/efi");
if (cache < 0)
return log_error_errno(cache, "Failed to parse fstab: %m");
return cache;
}
static bool slash_boot_exists(void) { static bool slash_boot_exists(void) {
static int cache = -1; static int cache = -1;
@ -574,27 +542,16 @@ static int add_partition_esp(DissectedPartition *p, bool has_xbootldr) {
* Otherwise, if /efi/ is unused and empty (or missing), we'll take that. * Otherwise, if /efi/ is unused and empty (or missing), we'll take that.
* Otherwise, we do nothing. */ * Otherwise, we do nothing. */
if (!has_xbootldr && slash_boot_exists()) { if (!has_xbootldr && slash_boot_exists()) {
r = slash_boot_in_fstab(); r = path_is_busy("/boot");
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) { if (r == 0) {
r = path_is_busy("/boot"); esp_path = "/boot";
if (r < 0) id = "boot";
return r;
if (r == 0) {
esp_path = "/boot";
id = "boot";
}
} }
} }
if (!esp_path) { if (!esp_path) {
r = slash_efi_in_fstab();
if (r < 0)
return r;
if (r > 0)
return 0;
r = path_is_busy("/efi"); r = path_is_busy("/efi");
if (r < 0) if (r < 0)
return r; return r;
@ -781,6 +738,18 @@ static int process_loader_partitions(DissectedPartition *esp, DissectedPartition
assert(esp); assert(esp);
assert(xbootldr); assert(xbootldr);
/* If any paths in fstab look similar to our favorite paths for ESP or XBOOTLDR, we just exit
* early. We also don't bother with cases where one is configured explicitly and the other shall be
* mounted automatically. */
r = fstab_has_mount_point_prefix_strv(STRV_MAKE("/boot", "/efi"));
if (r > 0) {
log_debug("Found mount entries in the /boot/ or /efi/ hierarchies in fstab, not generating ESP or XBOOTLDR mounts.");
return 0;
}
if (r < 0)
log_debug_errno(r, "Failed to check fstab existing paths, ignoring: %m");
if (!is_efi_boot()) { if (!is_efi_boot()) {
log_debug("Not an EFI boot, skipping loader partition UUID check."); log_debug("Not an EFI boot, skipping loader partition UUID check.");
goto mount; goto mount;

View File

@ -105,6 +105,34 @@ static int fstab_is_same_node(const char *what_fstab, const char *path) {
return false; return false;
} }
int fstab_has_mount_point_prefix_strv(char **prefixes) {
_cleanup_endmntent_ FILE *f = NULL;
assert(prefixes);
/* This function returns true if at least one entry in fstab has a mount point that starts with one
* of the passed prefixes. */
if (!fstab_enabled())
return false;
f = setmntent(fstab_path(), "re");
if (!f)
return errno == ENOENT ? false : -errno;
for (;;) {
struct mntent *me;
errno = 0;
me = getmntent(f);
if (!me)
return errno != 0 ? -errno : false;
if (path_startswith_strv(me->mnt_dir, prefixes))
return true;
}
}
int fstab_is_mount_point_full(const char *where, const char *path) { int fstab_is_mount_point_full(const char *where, const char *path) {
_cleanup_endmntent_ FILE *f = NULL; _cleanup_endmntent_ FILE *f = NULL;
int r; int r;

View File

@ -25,6 +25,8 @@ static inline int fstab_has_node(const char *path) {
return fstab_is_mount_point_full(NULL, path); return fstab_is_mount_point_full(NULL, path);
} }
int fstab_has_mount_point_prefix_strv(char **prefixes);
int fstab_filter_options( int fstab_filter_options(
const char *opts, const char *opts,
const char *names, const char *names,