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

Allow specifying qvm-block device by UUID #2272

Open
andrewdavidwong opened this issue Aug 27, 2016 · 11 comments
Open

Allow specifying qvm-block device by UUID #2272

andrewdavidwong opened this issue Aug 27, 2016 · 11 comments
Labels
C: core help wanted This issue will probably not get done in a timely fashion without help from community contributors. P: major Priority: major. Between "default" and "critical" in severity. security This issue pertains to the security of Qubes OS. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.

Comments

@andrewdavidwong
Copy link
Member

On 2016-08-25 18:06, johnyjukya@[...].org wrote:

Most standard Linux utilities that refer to block devices, allow you to
specify by uuid as well (mount, cryptsetup are two examples).

The documentation for qvm-block is sparse, but probably because it's a
striaght-forward utility.

There's no support in qvm-block to assign a device to a VM by UUID, is there?

Could be handy for some of the automation I'd like to put in place on
firing up the system.

One can always lsblk|grep|sed|cut|whatever in a sh script, and then use
the resulting block device for qvm-block, but it'd be a lot cleaner and
less error-prone if one could say

"qvm-block -a Florp UUID=kasdjflaksjdfaklsdf"
or "qvm-block -a FLorp --uid asdfkasjdlfkajsd"

Just a suggestion. (And for any other qvm-* that refer to block devices,
perhaps.)

Cheers.

JJ

@andrewdavidwong andrewdavidwong added T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality. C: core P: minor Priority: minor. The lowest priority, below "default." labels Aug 27, 2016
@andrewdavidwong andrewdavidwong added this to the Release 4.0 milestone Aug 27, 2016
@marmarek marmarek modified the milestones: Far in the future, Release 4.0 Jul 13, 2017
@marmarek marmarek added the help wanted This issue will probably not get done in a timely fashion without help from community contributors. label Jul 13, 2017
@easydozen
Copy link

easydozen commented Feb 26, 2020

I'm seeking for a way to a more robust association between removable device and VM.
The following workaround in /usr/lib/qubes/udev-block-add-change seems like the first step:

# prepare own uuid, based on serial and partition numbers
QUUID="`uuidgen -s -n @oid -N "${ID_SERIAL} ${PARTN}"`"
# crop uuid to match regular expression (qubes/ext/block.py)
NAME="${QUUID:(-12)}"
# make a link to the device
ln -sf ${DEVNAME} /dev/${NAME}

qvm-block output:

BACKEND:DEVID DESCRIPTION USED BY
sys-usb:52fd0105f711 DataTraveler_2.0 (/dev/sda1) sys-net (read-only=no, frontend-dev=xvdi)
sys-usb:81ca47a85fd3 DataTraveler_2.0 (/dev/sda)

Is it worth a PR?

@35609902357
Copy link

Can this be solved by using /dev/disk/by-uuid/XXXXXXXXXXXX instead of /dev/sdX?

@easydozen
Copy link

easydozen commented Oct 13, 2020

Can this be solved by using /dev/disk/by-uuid/XXXXXXXXXXXX instead of /dev/sdX?

I introduced my very own cropped version of UUID due to xenstore' path limitations.

@marmarek
Copy link
Member

marmarek commented Nov 6, 2020

There are two conflicting requirements here:

  1. qvm-block requires unique identifiers
  2. any identifier based solely on a device properties may not be unique (if you plug two identical devices for example, or one pretending to be the other)

To see it yourself, you can easily do that with loop block devices: simply attach the same file as both /dev/loop0 and /dev/loop1. The same will happen if you have two USB sticks with the same filesystem UUID.

I think a solution here could be to add extra device property - a "stable identifier", that can be used to attach the device, especially with --persistent, but qvm-block (and in fact other qvm-device too - the same applies to qvm-usb) can then enumerate the devices looking for specific stable ID. But also it detect duplicates and handle them somehow (refuse attach? attach first? ask the user?).

@marmarek
Copy link
Member

marmarek commented Nov 6, 2020

The stable id implementation I'd see like this:

  1. define property name and its constraints (allowed characters, length etc), document at https://www.qubes-os.org/doc/admin-api/
  2. (backend vm side) calculate the stable id from device and store it besides other device properties: https://github.com/QubesOS/qubes-linux-utils/tree/master/udev
  3. (dom0 side): add optional property to the base DeviceInfo class (core-admin/qubes/devices.py), set it where appropriate (core-admin/qubes/ext/block.py, possibly also in app-linux-usb-proxy too)
  4. (dom0 side): add attaching by stable id - especially for persistent attach during vm startup, I think that would be device-get:block handler in core-admin/qubes/ext/block.py, but I may be missing something
  5. (dom0/GUI domain side): add displaying stable id in qvm-device tool; add option to choose which id to use (based on --persistent?) - core-admin-client repo

@easydozen
Copy link

easydozen commented Feb 10, 2021

What if we'll use an existing device description in the role of stable id?

User operates on qvm-device like the following: qvm-block a testvm sys-usb:device_description --persistent. Qvm-device uses description to find ident and stores it in qubes.xml along with an option alias. On processing qubes.xml device ident will be determined by previously saved alias.

I've made working concept based on this idea, but still have a few doubts:

  1. whether it's safe to temporarily enable events in load_extras();

  2. should description be additionally sanitized, strictly checked at the dom0 side or it's enough to simply assume that it was cooked by our scripts at the backend domain.

@marmarek, When you have a moment, please take a look and let me know what you think.

@DemiMarie DemiMarie added P: major Priority: major. Between "default" and "critical" in severity. security This issue pertains to the security of Qubes OS. and removed P: minor Priority: minor. The lowest priority, below "default." labels Jan 12, 2022
@DemiMarie
Copy link

Is there a potential security problem here? UUIDs of block devices may very well be attacker-controlled in some cases.

@marmarek
Copy link
Member

marmarek commented Apr 3, 2022

Moving discussion from QubesOS/qubes-core-admin#447

I believe that works for virtual devices, but it is probably spoofable for physical devices.

A sample of one:

lrwxrwxrwx 1 root root  9 Apr  3 22:36 usb-SanDisk_Ultra_USB_3.0_4C530001270426103372-0:0 -> ../../sda
lrwxrwxrwx 1 root root 10 Apr  3 22:36 usb-SanDisk_Ultra_USB_3.0_4C530001270426103372-0:0-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 Apr  3 22:36 usb-SanDisk_Ultra_USB_3.0_4C530001270426103372-0:0-part2 -> ../../sda2

It looks to depend on just device characteristics, not data on it (well, partition table is part of the data, but the id for whole device is not depending on it). This isn't ideal because there may be cases where it isn't unique (I've seen some devices where vendor was lazy and serial number was all-zero...), but in most cases it should be good enough. And definitely better than the current approach.

I still thing a solution is a separate "stable id" device property - that is used to lookup the device, but the actual connection is done with temporary unique identifier (the current one is probably fine, but something based on hardware topology could work too). If collision is detected, it can be handled by either refusing the operation, or asking the user to resolve it.

An ID that is spoofable by the device (or its firmware) is not ideal, but I think it's acceptable trade-off. Similarly you need to trust that sys-usb will actually attach the device you ask it for.

@DemiMarie
Copy link

I still thing a solution is a separate "stable id" device property - that is used to lookup the device, but the actual connection is done with temporary unique identifier (the current one is probably fine, but something based on hardware topology could work too). If collision is detected, it can be handled by either refusing the operation, or asking the user to resolve it.

An ID that is spoofable by the device (or its firmware) is not ideal, but I think it's acceptable trade-off. Similarly you need to trust that sys-usb will actually attach the device you ask it for.

Perhaps the best answer is to have both. Right now, any device connected to sys-usb must be assumed to be able to compromise it, but that will not be the case once sys-usb becomes a unikernel.

@andrewdavidwong andrewdavidwong removed this from the Release TBD milestone Aug 13, 2023
@marmarta marmarta moved this to Backend in Device UX Redesign Sep 19, 2023
@mzpqnxow
Copy link

mzpqnxow commented Nov 17, 2024

I still thing a solution is a separate "stable id" device property - that is used to lookup the device, but the actual connection is done with temporary unique identifier (the current one is probably fine, but something based on hardware topology could work too). If collision is detected, it can be handled by either refusing the operation, or asking the user to resolve it.
An ID that is spoofable by the device (or its firmware) is not ideal, but I think it's acceptable trade-off. Similarly you need to trust that sys-usb will actually attach the device you ask it for.

Perhaps the best answer is to have both. Right now, any device connected to sys-usb must be assumed to be able to compromise it, but that will not be the case once sys-usb becomes a unikernel.

With regard to having both - I think you're on the right track there - go beyond both, though - this is how I'm thinking about it, after stealing ideas from this thread and other existing solutions in other products. Maybe this has already been hashed out or doesn't really fit the bill, but I'll defer to those who have been more engaged in this to decide on that

So, to the point of "having both" - the way VMWare Workstation does this seems to be by supporting practically anything that the underlying OS supports under the /dev filesystem - upon initial persistent assignment, the user chooses a suitable representation from some node under /dev which can be some of the ones mentioned already, and probably some more esoteric ones (and some that actually aren't reliable, if you really want to use them):

/dev/sdc
/dev/sdc1
/dev/mapper/sdc_crypt
/dev/disk/by-id/scsi-SomeVendor-model-and-serial-number-etc
/dev/disk/by-uuid/aaaaaa-bbbb-...

The drawback (which could also be seen as a benefit - flexibility) is that it puts the burden on the user to know which identifier is most specific and appropriate for their situation. If they're non-technical, they need to know to choose /dev/disk/by-[uu]id over /dev/sdc - they could be offered hints, if the implementation enumerates all of the common options in an order that is generally considered to be the most reliable and specific, and present it to them to choose from

I don't know how palatable (read: time-consuming) that is from an implementation standpoint but it seems like the best experience for both technical and non-technical users. I had to check how it actually worked in VMWare Workstation because I had forgotten- due to it never causing me any problems over ~3-4 years, despite heavy use of plugged-and-played USB block devices

I don't know enough about how the device is actually plumbed and what the backend bit would look like (I assume udev and qrpc) but it seems that if you started with a function that could convert any /dev node (by-uuid, by-id, mapper name, etc) into the unique identifier stored in the qubesdb then that bit of the problem would be solved

Maybe I'm missing something and there's some hidden complexity or problems with this approach, but it seems (relatively) simple

BTW, I really appreciate the work everyone is doing on this and am really looking forward to having it working. I'm currently implementing it with hacky hard-coded udev rules in sys-usb (serial + GPT UUID) that use qrpc to ask dom0 to confirm and then attach. It's mostly stolen from one of the solutions mentioned in one of the linked issues above, with additional logic for certain cases and some sanitization. It requires hand-editing the sys-usb template each time I have a new drive that I need to be persistently and reliably mapped

Thanks again!

@Atrate
Copy link

Atrate commented Nov 21, 2024

I would add that such a solution would be very useful for LUKS devices. I decrypt 2 additional LUKS devices in /etc/crypttab and the order in which they are decrypted seems to be completely random (that is, the order in which the password prompts are presented). This means that one device is sometimes dm-4, sometimes dm-3. This makes it very difficult to attach such dm devices to AppVMs persistently, I have to fail the password prompts on purpose if the order is wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: core help wanted This issue will probably not get done in a timely fashion without help from community contributors. P: major Priority: major. Between "default" and "critical" in severity. security This issue pertains to the security of Qubes OS. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.
Projects
Status: Backend
Development

No branches or pull requests

7 participants