-
-
Notifications
You must be signed in to change notification settings - Fork 187
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
USB portal (cont.) #1354
base: main
Are you sure you want to change the base?
USB portal (cont.) #1354
Conversation
cb66d92
to
f28ffdf
Compare
ce2b214
to
4907506
Compare
After a painful rebasing. |
74f9508
to
761f0a9
Compare
Feature is linked to flatpak/flatpak#5620 I think this is ready for review. |
69843ce
to
4dcfc94
Compare
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.
Checked the bits outside of usb.c
so far.
src/xdp-app-info-flatpak.c
Outdated
|
||
enumerable_devices = g_key_file_get_string_list (app_info_flatpak->flatpak_info, | ||
"USB Devices", | ||
"allowed-devices", |
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.
enumerable-devices/hidden-devices
Might want to use defines for those constants.
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.
fixed the literal.
src/xdp-utils.c
Outdated
void | ||
xdp_usb_query_free (XdpUsbQuery *query) | ||
{ | ||
if (!query) |
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.
Same 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.
no, we dereference query.
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.
Don't pass in invalid pointers then. Functions can have pre-conditions.
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.
when pre-conditions are NOT checked with any tool then they are just footguns. I know the tooling suck here, it's not a justification for dangerous practices. It should be safe with a NULL pointer.
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.
Bunch of comments on the interface definition. Mostly about documentation but I'm a bit worried about what device removal means and how we should deal with udev properties.
<!-- | ||
CreateSession: | ||
@options: Vardict with optional further information | ||
@handle: Object path for the :ref:`org.freedesktop.portal.Request` object representing this call |
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.
Something is wrong with this API description. Does it return a Request, as indicated here, or does it return a session, as indicated in the session_handle
out argument?
|
||
<!-- | ||
EnumerateDevices: | ||
@options: Vardict with optional further information |
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.
Should document that no options are currently supported. There are a few more of those cases in here.
|
||
* ``properties`` (``a{sv}``) | ||
|
||
A list of udev properties that this device has. These properties |
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'm really worried about this. It essentially makes udev a stable API even though it really is not.
This method can only be called once, and only after calling | ||
org.freedesktop.portal.Usb.AcquireDevices(). |
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.
Should mention the #org.freedesktop.portal.Request::Response
signal
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 the response signal should carry an id that should be passed to FinishAcquireDevices
. That way there is no problem with calling AcquireDevices
multiple times before calling FinishAcquireDevices
.
|
||
There are no supported keys in the @options vardict. | ||
--> | ||
<method name="ReleaseDevices"> |
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.
Should probably say something about the relation to the session and connection. I assume closing the session or connection implicitly also releases all devices?
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.
Eh, there is no session involved with acquiring and releasing devices, only a connection. The question still remains: what happens when the connection is closed. Same as release? Nothing?
|
||
* ``action`` (``s``) | ||
|
||
Type of event that occurred. One of "add", "change", or "remove". |
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.
What happens when one has acquired a device and it got removed? Is the fd still usable? Only sometimes?
We don't have a mechanism for revoking the fd so a real device unplug will result in a remove with the fd becoming unusable but when the user wants to revoke a device, we can't do anything with the existing fd on the client and so it won't be.
@devices: Array of device identifiers | ||
@options: Vardict with optional further information | ||
|
||
Releases previously acquired devices. |
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.
What does it mean to release a device? Is the fd still usable?
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.
Looked through the usb.c file now. Mostly nickpicks but also a few actual issues we have to work out.
property = g_udev_device_get_property (device, "ID_MODEL_ID"); | ||
if (property) | ||
{ | ||
g_string_append_printf (permission_id, "%s%s", count > 0 ? "/" : "", property); |
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 don't add slashes always, one could have confusion between the vendor, model and serial id. E.g. VENDOR
and SERIAL
could be the same, whereas with the slashes, they would be VENDOR//
and //SERIAL
which are different.
g_string_append_printf (permission_id, "%s%s", count > 0 ? "/" : "", property); | ||
count++; | ||
} | ||
|
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.
We could end up with the string device:
here.
g_dbus_method_invocation_return_error (invocation, | ||
XDG_DESKTOP_PORTAL_ERROR, | ||
XDG_DESKTOP_PORTAL_ERROR_FAILED, | ||
"Cannot call AcquireDevices() with an unfinished " |
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.
Why not? The interface description doesn't mention this restriction at all.
This method can only be called once, and only after calling | ||
org.freedesktop.portal.Usb.AcquireDevices(). |
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 the response signal should carry an id that should be passed to FinishAcquireDevices
. That way there is no problem with calling AcquireDevices
multiple times before calling FinishAcquireDevices
.
owned_device = g_hash_table_lookup (sender_info->owned_devices, access_data->device_id); | ||
if (!owned_device) | ||
{ | ||
fd = open (device_file, access_data->writable ? O_RDWR : O_RDONLY); |
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.
Why would opening the file fail? Is udev already telling us that we should be able to open the device node (i.e. we have permission to do it) or is do we discover about bad permissions just 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.
many reason. It's IO nothing is guaranteed. The device could have disappear, could be unitialized. If it can go wrong it will go wrong.
a258338
to
b40ccee
Compare
(I haven't addressed everything yet) |
05c6d37
to
b0b5cf7
Compare
The USB portal is the middleman between sandboxed apps, and the devices connected and available to the host system. This is the first version of the portal. Device filtering ================ Sandboxed apps must declare which USB devices they support ahead of time. This information is read by the XDG Desktop Portal and used to determine which USB devices will be exposed to requesting apps. On Flatpak, these enumerable and hidden devices are set by the "--usb" and "--nousb" arguments against "flatpak build-finish" and "flatpak run". Neither "--devices=all" nor "--device=usb" do influence the portal. Hidding a device always take precedence over making them enumerable, even when a blanket permission ("--usb=all") is set. Individual devices are assigned a unique identifier by the portal, which is used for all further interactions. This unique identifier is completely random and independent of the device. Permission checks are in place to not allow apps to try and guess device ids without having permission to access then. Permissions =========== There are 2 dynamic permissions managed by the USB portal in the permission store: 1. Blanket USB permission: per-app permission to use any methods of the USB portal. Without this permission, apps must not be able to do anything - enumerate, monitor, or acquire - with the USB portal. [1] 2. Specific device permission: per-app permission to acquire a specific USB device, down to the serial number. Enumerating devices =================== There are 2 ways for apps to learn about devices: - Apps can call the EnumerateDevices() method, which gives a snapshot of the current devices to the app. - Apps can create a device monitoring session with CreateSession() which sends the list of available devices on creation, and also notifies the app about connected and disconnected devices. Only devices that the app is allowed to see are reported in both cases. The udev properties exposed by device enumeration is limited to a well known subset of properties. [2] Device acquisition & release ============================ Once an app has determined which devices it wants to access, the app can call the AcquireDevices() method. This method may prompt a dialog for the user to allow or deny the app from accessing specific devices. If permission is granted, XDG Desktop Portal tries to open the device file on the behalf of the requesting app, and pass down the file descriptor to that file. [3] --- [1] Exceptionally, apps can release previously acquired devices, even when this permission is disabled. This is so because we don't yet have kernel-sided USB revoking. With USB revoking in place, it would be possible to hard-cut app access right when the app permission changes. [2] This patch uses a hardcoded list. There is no mechanism for apps to influence which other udev properties are fetched. This approach is open to suggestions - it may be necessary to expose more information more liberally through the portal. [3] This is clearly not ideal. The ideal approach is to go through logind's TakeDevice() method. However, that will add significant complexity to the portal, since this logind method can only be called by the session controller (i.e. the only executable capable of calling TakeControl() in the session - usually the compositor). This can and probably should be implemented in a subsequent round of improvements to the USB portal. Co-Authored By: Georges Basile Stavracas Neto <[email protected]> Co-Authored-By: Ryan Gonzalez <[email protected]> Signed-off-by: Hubert Figuière <[email protected]>
Signed-off-by: Hubert Figuière <[email protected]>
b0b5cf7
to
bdaa78e
Compare
This supercede #1238
Close #1238