Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(base): do not change the provided UUID #1650

Merged
merged 1 commit into from
Jan 9, 2022

Conversation

joshuacov1
Copy link
Contributor

This was introduced by
d353297
Bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=2012496

This pull request changes...

Changes

During boot dracut parses the provided UUID to lower case and thus starts an endless loop wating for the devise to appear. The device is actually mapped correctly by the kernel (which doesn't tweak the UUID) but because we are waiting for a name with lower charachters the expeted device never appers which drops us at the emergency shell leaving the system unbootable.
This happens especially on nfts/fat filesystems because technically those don't have a UUID but searial numbers which are used by the linux tools as UUID.

Checklist

  • I have tested it locally
  • I have reviewed and updated any documentation if relevant
  • I am providing new code and test(s) for it

Fixes #
#1635

@github-actions github-actions bot added base Issues related to the base module modules Issue tracker for all modules labels Nov 22, 2021
@johannbg
Copy link
Collaborator

@haraldh what's was/is historic? reason to change everything to lower case to begin with? + There should be no need for the second echo if the string is being used as is, as in echo "/dev/disk/by-uuid/${_dev#UUID=}" should suffice so I must be missing something since you acked his ( previous ) PR.

@joshuacov1
Copy link
Contributor Author

joshuacov1 commented Nov 25, 2021

@haraldh what's was/is historic? reason to change everything to lower case to begin with? + There should be no need for the second echo if the string is being used as is, as in echo "/dev/disk/by-uuid/${_dev#UUID=}" should suffice so I must be missing something since you acked his ( previous ) PR.

I dig around this issue and found the following:
As I said above the problem was caused by commit d353297 which factored out the function label_uuid_to_dev() from the following modules: 01fips, 90dmsquash-live, 91zipl, 95resume, 95rootfs-block, 98dracut-systemd and 98usrmount. All but 95rootfs-block didn’t touch the returned string before so no conversion upper to lower occurred there. Nothing will change here, either.

95rootfs-block: with commit f17c5fa from 24.07.2013 the conversion of the stings was introduced with the following description:


In the kernel comments PARTUUID is shown using uppercase A-F:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/init/do_mounts.c?id=HEAD#n183
However, dracut tries to use the value of PARTUUID directly in /dev/disks/by-partuuid/ which expects the hex to be lowercase. This will cause root to never be found, oops!
Fix dracut so it can, like the Kernel, accept either casing.
Untested but I added a hack on my local system that was similar.


However this assumption is wrong. Looking at the code in
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/init/do_mounts.c?h=v5.16-rc2
one can see that the kernel looks for the provided UUID using the strncasecmp() in Line 83 which is NOT case sensitive (devt_from_partuuid() calls match_dev_by_uuid() which does the matching itself). So the function returns any device matching the provided UUID regardless of upper/lower cases. The kernel is not case sensitive.

However systemd creates the Symlinks using the corresponding value in ENV{ID_PART_ENTRY_UUID} or ENV{ID_PART_ENTRY_UUID} which are both derived from the drive itself and are not touched at all. See https://github.com/systemd/systemd/blob/main/rules.d/60-persistent-storage.rules
So the Links created by systemd are case sensitive.

When dracut parses the provided UUID it calls wait_for_dev() for the device to appear. However this function uses a _name argument that is case sensitive.
So at the end the it looks like this: The kernel will find the device regardless of lower/upper case because it uses strncasecmp() for this which is not case sensitive. Further down the boot process systemd creates symlinks based on the actual values provided by the devices (which are case sensitive) and we wait for the devices to appear looking for those case sensitive names.

That’s the point here: the above reasoning for inserting the conversion upper->lower in 95rootfs-block is wrong because the kernel doesn’t expect any specific characters at all: it just doesn’t care about case sensitivity but dracut does. That’s why the reasoning above “However, dracut tries to use the value of PARTUUID directly in /dev/disks/by-partuuid/ which expects the hex to be lowercase. This will cause root to never be found, oops!” is wrong. Dracut doesn’t expect lowercase but what is provided by the device. And since ABCD != abcd we should correctly state the desired UUID on the command line and the dracut will find that device. Otherwise the devices won’t be visible by dracut and then we end with the emergency shell (as in my case right now).

That’s why we don’t need to tamper the UUID provided by the device… which my patch corrects.

@johannbg
About the second echo: you are right. It was there for the trim to work. Since we don’t touch the provided UUID we don’t need it anymore and can use echo "/dev/disk/by-uuid/${_dev#UUID=}” directly.

I’ll update my PR (hopefully without any more oops, this time).

During boot dracut parses the provided UUID to lower case and thus starts an
endless loop wating for the devise to appear. The device is actually mapped
correctly by the kernel (which doesn't tweak the UUID) but because we are
waiting for a name with lower charachters the expeted device never appers which
drops us at the emergency shell leaving the system unbootable.
This happens especially on nfts/fat filesystems because technically those don't
have a UUID but searial numbers which are used by the linux tools as UUID.
@joshuacov1
Copy link
Contributor Author

The correct patch is ready for review.

@joshuacov1
Copy link
Contributor Author

Is there any update on this issue?

If my reasoning above is wrong I'll amend/edit the comments and/or the proposed fix but this bug still plugs my setup.

@Conan-Kudo Conan-Kudo enabled auto-merge (rebase) December 10, 2021 13:09
@stale
Copy link

stale bot commented Jan 9, 2022

This issue is being marked as stale because it has not had any recent activity. It will be closed if no further activity occurs. If this is still an issue in the latest release of Dracut and you would like to keep it open please comment on this issue within the next 7 days. Thank you for your contributions.

@stale stale bot added the stale communication is stuck label Jan 9, 2022
@johannbg johannbg disabled auto-merge January 9, 2022 18:22
@stale stale bot removed the stale communication is stuck label Jan 9, 2022
@johannbg johannbg merged commit 4e85874 into dracutdevs:master Jan 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
base Issues related to the base module modules Issue tracker for all modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants