]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: Don't bypass blkid *_lookup_value() to decide USAGE
authorRodrigo Campos <rodrigo@amutable.com>
Fri, 6 Mar 2026 15:54:02 +0000 (16:54 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 10 Mar 2026 21:33:31 +0000 (22:33 +0100)
After commit "core: reuse existing dm-verity device for single
filesystem images pinned by policy" (0bd766553cbf), when I attach a
portable image (erofs+verity) and try to start a service, it fails with:

  Partition root discovered with policy 'unprotected' but 'verity+read-only-on+growfs-off+erofs' was required, refusing.
  Failed to dissect image: Operation not possible due to RF-kill

The image does have verity, in fact the RootImagePolicy= field was added
automatically.

The inconsistency between what is found at attach vs when starting the
service comes from the fact that dissect_image() is called with a
different policy as parameter and the recent shortcut added.

At attach we do this:

dissect_image(policy="*")
    partition_policy_determine_fstype(policy)
      partition_policy_flags_to_string(...) // mask is 0, returns 0
    -> returns NULL // root_fstype_string is not set
    if (root_fstype_string) // false
      sym_blkid_probe_lookup_value()...

At start, as we do have the policy set, we do:

dissect_image(policy="root=verity+...+erofs:root-verity=...")
    partition_policy_determine_fstype(policy)
      partition_policy_flags_to_string(...) // returns 1
    -> sets root_fstype_string to "erofs"
    if (root_fstype_string) // true
       usage = "filesystem"

Then, the service is blocked to start with the aforementioned error.

It's correct for partition_policy_determine_fstype() to set erofs in
that case, and other callers seem to expect this behavior on similar
cases, but what is not correct is to assume that this means it's a
filesystem. Usage in this case should still be unset.

Let's just always do the lookup, as that gets us the correct answer reliably
and we already did the slow part that is the probe.

The call to `sym_blkid_do_safeprobe()` is a few lines above. The call to
the lookup function isn't very expensive. blkid_probe_lookup_value()[1]
calls __blkid_probe_lookup_value(), which searches on a list[2], IIUC in
memory and no IO is used. It's a linear search of the property.

[1]: https://github.com/util-linux/util-linux/blob/0fd08f19e7a3bc37509491d06a664cfb47be7cd8/libblkid/src/probe.c#L2299
[2]: https://github.com/util-linux/util-linux/blob/0fd08f19e7a3bc37509491d06a664cfb47be7cd8/libblkid/src/probe.c#L2343

src/shared/dissect-image.c

index 9b9c3af2529f5399bc244f261bd18d0bd279380e..6c73a12548caf7af5d6b4d69366534a445c61055 100644 (file)
@@ -1149,10 +1149,7 @@ static int dissect_image(
 
                 /* If flags permit this, also allow using non-partitioned single-filesystem images */
 
-                if (root_fstype_string)
-                        usage = encrypted ? "crypto" : "filesystem";
-                else
-                        (void) sym_blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
+                (void) sym_blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
                 if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
                         _cleanup_free_ char *t = NULL;
                         const char *fstype = NULL;