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

Polkit: Requiring filesystem-mount-system directly after unlock #473

Open
coldfix opened this issue Dec 13, 2017 · 0 comments
Open

Polkit: Requiring filesystem-mount-system directly after unlock #473

coldfix opened this issue Dec 13, 2017 · 0 comments

Comments

@coldfix
Copy link
Contributor

coldfix commented Dec 13, 2017

Hi,

trying to mount a freshly unlocked device via the DBus-API right after InterfacesAdded signal will require org.freedesktop.udisks2.filesystem-mount-system permission most of the time. If waiting a few seconds after the unlock, it requires org.freedesktop.udisks2.filesystem-mount as expected.

(Therefore, if you don't have this permission, it either fails with GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation; or if you have e.g. polkit-gnome running, it shows an authentication dialog instead of failing directly. If a password is entered into the dialog, it mounts, otherwise fails with GLib.Error: g-io-error-quark: GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedDismissed: The authentication dialog was dismissed (36).)

I encountered the issue while running udiskie in a window manager. Inside a DE, everything seems to work as was reported by someone else in coldfix/udiskie#153 (could be due to the permission being granted there, not sure).

It's reproducible without udiskie with the following simplified python script that waits for new filesystems and mounts as soon as they are added:

(you need python-gobject to run it)

from gi.repository import Gio, GLib

BUS_NAME = 'org.freedesktop.UDisks2'
ROOT_OBJ = '/org/freedesktop/UDisks2'
INTERFACE_FILESYSTEM = 'org.freedesktop.UDisks2.Filesystem'
INTERFACE_MANAGER    = 'org.freedesktop.DBus.ObjectManager'


def get_proxy(flags, bus_name, object_path, interface_name, callback):
    def finish(proxy, result, *user_data):
        callback(Gio.DBusProxy.new_for_bus_finish(result))
    info = cancellable = user_data = None
    Gio.DBusProxy.new_for_bus(
        Gio.BusType.SYSTEM,
        Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES |
        Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS,
        info,
        bus_name,
        object_path,
        interface_name,
        cancellable,
        finish,
        user_data,
    )

def get_device(object_path, callback):
    get_proxy(
        Gio.DBusProxyFlags.NONE,
        BUS_NAME,
        object_path,
        INTERFACE_FILESYSTEM,
        callback)


def get_manager(callback):
    get_proxy(
        Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES |
        Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS,
        BUS_NAME,
        ROOT_OBJ,
        INTERFACE_MANAGER,
        callback)


def mount(object_path):
    def mount_dev(dev):
        print("mounting", object_path)
        dev.Mount('(a{sv})', {})
    get_device(object_path, mount_dev)


def interfaces_added(object_path, interfaces_and_properties):
    print("New interfaces on {}: {}".format(
        object_path, list(interfaces_and_properties)))
    if 'org.freedesktop.UDisks2.Filesystem' in interfaces_and_properties:
        # seems to work if waiting before trying to mount..:
        # import time; time.sleep(1.0)
        mount(object_path)


PROXIES = []
def connect(proxy, event, handler):
    PROXIES.append(proxy) # prevent garbage collection
    def callback(connection, sender_name, object_path,
                 interface_name, signal_name, parameters):
        return handler(*GLib.Variant.unpack(parameters))
    return proxy.get_connection().signal_subscribe(
        proxy.get_name(),
        proxy.get_interface_name(),
        event,
        proxy.get_object_path(),
        None,
        Gio.DBusSignalFlags.NONE,
        callback,
    )


if __name__ == '__main__':
    get_manager(lambda m: connect(m, 'InterfacesAdded', interfaces_added))
    mainloop = GLib.MainLoop()
    mainloop.run()

After starting this script, unlock your device with udisksctl unlock -b /dev/sdb1 and observe the issue. It doesn't happen every time, particularly if the device has warmed up.

Curiously, udisksctl unlock -b /dev/sdb1 && udisksctl mount -b /dev/dm-6 seems to mount every time.

Furthermore, if waiting a few seconds (1s seems to be enough) before attempting to mount, everything works as expected without having to enter a password.

Note that I know from running udisksctl monitor at the same time that InterfacesAdded is the only signal received, there is no PropertiesChanged afterwards, so it seems to be impossible to detect when the device is ready to be mounted without filesystem-mount-system permission.

Note that I run journalctl -n 20 -f -u polkit.service with the following polkit rule in /etc/polkit-1/rules.d/50-udisks.rules to see which permissions are queried:

polkit.addRule(function(action, subject) {
  var prefix = "org.freedesktop.udisks";
  if (action.id.slice(0, prefix.length) == prefix)
    polkit.log(action.id);
}

This behaviour seems to be new since maybe 1-6 months (don't know exactly, sorry).

Any ideas how to fix this?

Best, Thomas

@vojtechtrefny vojtechtrefny added this to the udisks-2.8.0 milestone Jul 3, 2018
@vojtechtrefny vojtechtrefny modified the milestones: udisks-2.8.0, udisks-2.8.1 Aug 29, 2018
@tbzatek tbzatek changed the title Requiring filesystem-mount-system directly after unlock Polkit: Requiring filesystem-mount-system directly after unlock Nov 28, 2019
@tbzatek tbzatek removed this from the udisks-2.8.1 milestone Nov 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants