How to have persistent Unix File Descriptors between sandbox and host?

Hello there, first post here.

Wasn’t able to find anything which answers my question in the level of detail I’d wish.

I know that Flatpak uses Portals to access files outside of the sandbox and that these files are mapped into the sandbox at /run/user/$UID/doc/$HASH/$FILE which isn’t available on the host.

However I work on an application which also works with DBUS to send unix file descriptors to a dbus interface. To do this the following happens:

  1. User selects file via the file portal
  2. File is propagated to the sandbox
  3. File is opened inside the sandbox
  4. File Descriptor (int) is received
  5. dbus interface is called with the file descriptor attached to it
  6. Host service can’t open file and thinks it has been “deleted”

Therefore I concluded the FD (file descriptor) is unknown to the host and do not seem to be identical between host and sandbox. Despite being already an abstract representation as they are only integers.

Is there a way to have persistent FD’s between sandbox and host? Or is this already supported and I just receive the file descriptor the wrong way?

In order to open the file I use:

Python:

fd = os.open(file_path)

However file_path is the property of GLocalFile.get_path() and is the sandbox path located at /run/user/$UID/doc/$HASH/$FILEof that file.

Is there a way to get the file descriptor directly from the host (without –filesystem=home or similar) as it will be passed back to the host anyway?

To circumvent this issue I just allowed my app to access xdg-downloads and the same code works as expected. (As long as the file in question is located in the users Downloads directory.)

My app gets the “real” path and running os.open on it returns a fd which also the host knowns and I can send over dbus to the external service which then can access that file just fine.

The document portal recently added an API to retrieve the path on the host for an file opened over the file chooser portal.

If I’m correct, this would the the API in the portal:

Though some libraries may offer other methods to query this information. For GLib and GTK, look here for example:

That being said, this API is fairly new, only added at the start of this year. So if your app runs on a system with an old XDG desktop portal, the API will not be available.

So the easiest way is still to give broader filesystem permissions for now. Or you could implement a check for the API version and, if on a too old version, ask the user to provide the necessary permission.

1 Like

Many thanks that was exactly what I was looking for and solved my issue. Well at least on systems supporting xdg-desktop-portal as of version 1.20 (1.19 only had this attribute for directory not files)

Code example for future readers:

    file_path = file.get_path() # Sandbox path, as fallback
    try:
        # Get FileInfo for File
        file_info = file.query_info("xattr::document-portal.host-path", FileQueryInfoFlags.NONE, None)

        # Query file attribute for real path
        real_path = file_info.get_attribute_string("xattr::document-portal.host-path")
        if real_path is not None: # Attribute does not exist if None
            file_path = real_path
        else:
            pass # TODO: Throw error dialog to request user to broaden sandbox permissions.
    except GLib.Error:
        print("Can not get real path. Stuck with sandbox")
    fd = os.open(file_path, os.O_RDONLY)

This topic was automatically closed after 35 hours. New replies are no longer allowed.