-
Notifications
You must be signed in to change notification settings - Fork 649
snap-bootstrap: add scan-disk subcommand #12006
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
snap-bootstrap: add scan-disk subcommand #12006
Conversation
|
This works with canonical/core-initrd#107 |
mardy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to get the same information just by running blkid instead of using the library?
cmd/snap-bootstrap/cmd_scan_disk.go
Outdated
| } else if part.Name == "ubuntu-data-enc" { | ||
| has_data = true | ||
| data_uuid = part.UUID | ||
| } else if part.Name == "ubuntu-data" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if someone appends unencrypted ubuntu-data to a hard-drive, then it will be mounted instead of ubuntu-data-enc? surely we should try to find -enc paritions, and not search for non-encrypted ones afterwords?
Also I thought udev database already has all of this information inside it's database, which maybe can be queried directly in the udev rule alone without this helper binary? Apart from the LoaderDevicePartUUID bit, which i thought there should be a udev symlink for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if someone appends unencrypted ubuntu-data to a hard-drive, then it will be mounted instead of ubuntu-data-enc? surely we should try to find -enc paritions, and not search for non-encrypted ones afterwords?
Maybe I mixed up, but I think the filesystem labels have "-enc" suffix. But the partition name does not. See for example:
/dev/vda4: UUID="2eeba654-032f-4384-8a46-075be2b415b5" LABEL="ubuntu-save-enc" TYPE="crypto_LUKS" PARTLABEL="ubuntu-save" PARTUUID="a154643d-4398-714a-9704-71335e5ea856"
PARTLABEL is not the same as LABEL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inside ubuntu-save-enc there is ubuntu-save. Outside of ubuntu-save-enc there can be a malicious second partition with an FS ubuntu-save. Does above code handle this fine? As far as I can tell, after scanning and finding ubuntu-data-enc and using it; it will then find unencrypted ubuntu-data and override it.
Somehow this feels odd that after the first one is detected, it can be detected again, and override previously found result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I thought udev database already has all of this information inside it's database, which maybe can be queried directly in the udev rule alone without this helper binary? Apart from the LoaderDevicePartUUID bit, which i thought there should be a udev symlink for.
Good question. I have tried before to use more rules and less code. But there were issues. And I do not remember. I will try again to document why this is not possible.
I am guessing it was the fallback for non-uefi boot that was a bit tricky.
gpt-auto-generator can create a symlink. But it has to be a partition with a specific uuid on the same disk as the booting partition. We do not use that uuid. And we should not use it. It is not made for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inside ubuntu-save-enc there is ubuntu-save. Outside of ubuntu-save-enc there can be a malicious second partition with an FS ubuntu-save.
I am not sure I understood this.
This binary only looks at partition names. Not filesystem labels. If there are other partitions with conflicting filesystem labels, we will not look at them, because we only look at the partition names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today, someone can remove an encrypted ubuntu-save and replace it by a non encrypted one. snap-bootstrap will then fallback to it. What would be the difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I thought udev database already has all of this information inside it's database, which maybe can be queried directly in the udev rule alone without this helper binary? Apart from the LoaderDevicePartUUID bit, which i thought there should be a udev symlink for.
Good question. I have tried before to use more rules and less code. But there were issues. And I do not remember. I will try again to document why this is not possible.
Now I remember. It is possible to not call it on ENV{DEVTYPE}=="partition". Though we need to make sure that IMPORT{builtin}="blkid [...]" has been called yet, so post 60-persistent-storage.rules. Then what we have to do is compare ID_PART_ENTRY_UUID with UBUNTU_SEED (or the 3 others).
However, for ENV{DEVTYPE}=="disk" we do need to scan the partitions and find the booting one. And this we cannot do with just udev rules. We have LoaderDevicePartUUID which points to the boot partition. But we are processing the disk at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gpt-auto-generatorcan create a symlink.
By the way, I was wrong about it. It is in an udev rule that the symlink is created. gpt-auto-generator only makes sysroot.mount and -.mount to use that symlink.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I remember. It is possible to not call it on ENV{DEVTYPE}=="partition". Though we need to make sure that IMPORT{builtin}="blkid [...]" has been called yet, so post 60-persistent-storage.rules. Then what we have to do is compare ID_PART_ENTRY_UUID with UBUNTU_SEED (or the 3 others).
what's the conclusion here? it seemed related to what Alfonso is also asking below. Anyway as Alfonso said this needs a bit of a description of what is the logic/flow and why we went that way in the code itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking back at this thread, I realize that the -enc suffix is only for the luks2 label. Not the partition label. So maybe I can use only udev rules for the partitions.
We cannot list partitions from blkid. |
|
Given SEED is ESP; and we bind the initramfs-mounts unit to the SEED; i am wondering if we can instead turn on / patch the systemd's gpt-auto-generator which can create esp mount in /efi and use that instead? Looking more at this, I actually don't quite like the behaviour of gpt-auto-generator. Because the good bits of it are not what we need here. Ideally we would only read efi_loader_get_device_part_uuid (aka LoaderDevicePartUUID) and generate .device unit for it, and bind initramfs-mounts service unit to it. Before any drives appear. Thus without waiting udev to exec scan-disk to process them all either. |
So almost what I have done, but a symlink on the whole disk rather than the partitions? |
4e7a21e to
999e91c
Compare
49c9437 to
4060872
Compare
ebb8a9b to
7b6adbd
Compare
|
@valentindavid can the description or some comment in the code include the actual udev rules that this will be used from? it's a bit unclear just from the code how things go from the code in scan-disk to have /dev/ubuntu/disk symlinked? What's the plan for testing the cmd_scan_disk code? |
Sure. We could even add the rules to snapd and install them into core-initrd.
I think I will need to mock libblkid somehow to test it. Loop devices need root to be setup, and I do not think there is as this point any nice user land block devices. I think only character devices can be emulated with CUSE. Not block. |
7b6adbd to
71cc643
Compare
I have added tests. I still have to add tests for the changes in |
2f663fa to
05f7751
Compare
42a76f8 to
8b70e59
Compare
|
I suppose this needs to be marked blocked then, also if we need to run that
many go commands are we sure it’s going to be faster than master?
…On Fri, 11 Apr 2025 at 19:52, alfonsosanchezbeato ***@***.***> wrote:
Something that I have been thinking is if we might have race conditions as
it is possible that the partition nodes appear later that the base device
(the kernel will spend a small amount of time reading the partition table
between both events). Should we create the disk symlink after all
partitions that we expect appear? With something like:
1. scan is run for the block devices. It detects the boot device and
reads the expected partitions. It exports booleans for UBUNTU_DISK but
also others, one for each expected partition.
2. Another command is run for the partitions in UBUNTU_DISK, for the
expected partitions (could be just seed, or seed+boot+data, or
seed+boot+data+save). This commands creates the link for the partition it
runs for, then checks if the rest of the links for the expected partitions
are also created (looking at the env it will know which are the expcted
symlinks). If that is the case, it creates the disk symlink.
With this, all devices for partitions that snap-bootstrap wants to mount
must exist when the initramfs-mounts subcommand is run.
—
Reply to this email directly, view it on GitHub
<#12006 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHOHDLAA5XHLQKJ7FR7MX32Y76MHAVCNFSM6AAAAABRD2SSCOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDOOJXGY2DIMBVGM>
.
You are receiving this because your review was requested.Message ID:
***@***.***>
*alfonsosanchezbeato* left a comment (canonical/snapd#12006)
<#12006 (comment)>
Something that I have been thinking is if we might have race conditions as
it is possible that the partition nodes appear later that the base device
(the kernel will spend a small amount of time reading the partition table
between both events). Should we create the disk symlink after all
partitions that we expect appear? With something like:
1. scan is run for the block devices. It detects the boot device and
reads the expected partitions. It exports booleans for UBUNTU_DISK but
also others, one for each expected partition.
2. Another command is run for the partitions in UBUNTU_DISK, for the
expected partitions (could be just seed, or seed+boot+data, or
seed+boot+data+save). This commands creates the link for the partition it
runs for, then checks if the rest of the links for the expected partitions
are also created (looking at the env it will know which are the expcted
symlinks). If that is the case, it creates the disk symlink.
With this, all devices for partitions that snap-bootstrap wants to mount
must exist when the initramfs-mounts subcommand is run.
—
Reply to this email directly, view it on GitHub
<#12006 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHOHDLAA5XHLQKJ7FR7MX32Y76MHAVCNFSM6AAAAABRD2SSCOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDOOJXGY2DIMBVGM>
.
You are receiving this because your review was requested.Message ID:
***@***.***>
|
|
Thanks for checking! Re: waiting on symlinks I think it should be possible if the scan commands provides information to udev on what symlink/partition we want to wait for depending on the mode. And create a symlink on which mount command can wait that could point to different partitions. |
The problem here is that we need to add dependencies in generators. And that would require daemon-reload. And start commands as well. The best way is to split snap-bootstrap so we can add correct dependencies to every part. This branch works fine as is as long as we do not expect to read the symlinks yet... But they will be useful as soon as we move things out. For instance we could move mount of boot and seed as automount units. |
andrewphelpsj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
| // determine what partition the booted kernel came from. If which disk the | ||
| // kernel came from cannot be determined, then it will fallback to mounting via | ||
| // the specified disk label. | ||
| func mountNonDataPartitionMatchingKernelDisk(dir, fallbacklabel string, opts *systemdMountOptions) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc comment here I think could use an update to explain this new flow.
cmd/snap-bootstrap/cmd_scan_disk.go
Outdated
| } | ||
|
|
||
| partitions, err := probe.GetPartitions() | ||
| if partitions == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a normal check on err != nil would be more consistent here.
cmd/snap-bootstrap/cmd_scan_disk.go
Outdated
| * this is not an error. There are plenty of block devices | ||
| * that are not the boot device. | ||
| */ | ||
| return nil; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably need to run gofmt on these files.
| cnode := C.CString(node) | ||
| defer C.free(unsafe.Pointer(cnode)) | ||
| C.blkid_new_probe_from_filename(cnode) | ||
| probe, err := C.blkid_new_probe_from_filename(cnode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding, err will contain some representation of errno, from C. Would it be safer to check both err and probe?
Do we know for sure err != nil when probe == nil?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probe is always nil on error yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Although that is a bit different, I think. I wanted to make sure that errno is always set by these functions on failure, but that isn't mentioned in the docs. I took a look at the code, and I think that errno would be set in all failure paths, but it is hard to tell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed it to use err.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use err, then we're saying that errno will always be set by the C function on failure. Is that definitely true?
cmd/snap-bootstrap/blkid/blkid.go
Outdated
| func newProbeFromFilenameImpl(node string) (AbstractBlkidProbe, error) { | ||
| cnode := C.CString(node) | ||
| defer C.free(unsafe.Pointer(cnode)) | ||
| C.blkid_new_probe_from_filename(cnode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errant/extra call here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep... that was a leak.
513059a to
afe58c2
Compare
|
I have resplit and rebased all the commits for merge. |
pedronis
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, couple minor things
| * is not an error. There are lots of block | ||
| * devices. | ||
| */ | ||
| return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tests don't get here
cmd/snap-bootstrap/cmd_scan_disk.go
Outdated
| return scanDiskNodeFallback(output, node) | ||
| } | ||
|
|
||
| // TODO: split the rest of this function in 2, fallback and non fallback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was taken care afaict
8bf84c5 to
f01a2ca
Compare
This will be needed for snap-boostrap scan-disk
This command is expected to be called from udev. This creates symlinks in `/dev/disk/ubuntu/`. Then we can bind `snap-bootstrap initramfs-mounts` to `dev-disk-ubuntu-disk.device`.
f01a2ca to
247246b
Compare
|
Could I get a forced merge?
This PR is not related to centos.
This looks like nvidia component related. Not related to this.
Download error from package repositories
Serial port suggests it boot correctly. Only ssh fails to connect. That is after mounting disks.
This PR is not related to centos. Also unit-tests-cross-distros, unrelated and already fixed in master. |
This command is expected to be called from udev. This creates
symlinks
/dev/ubuntu/ubuntu-{seed,boot,data,save}.Then we can bind
snap-bootstrap initramfs-mountstodev-ubuntu-ubuntu-seed.device.