Last November I reported that running KDE Partition Manager as non-root user is slowly shaping up. Instead of running the whole application as root, KAuth lets us run GUI parts as unprivileged user and some non-GUI helper running as root.

After another 4 months of development, KAuth support is mostly done. There are still a few things that need to be finished, some cleaning up, fixing bugs but major refactoring is complete. Unlike other KDE Applications, KDE Partition Manager uses root for almost any operation, so the way it uses KAuth is quite different from e.g. Kate where the only task the helper has to do is to copy the file to its destination. KDE Partition Manager might need to execute a lot of different commands to do some task (e.g. move/resize partition) and we don’t want user to authenticate 20 times during partitioning operation.

How it works?

  • When user launches KDE Partition Manager, KAuth helper is immediately started.
  • The Helper opens DBus system bus interface and listens for requests from KDE Partition Manager.
  • When KDE Partition Manager needs to run some command, or copy some data on the disks it sends a requests to KAuth helper over DBus system bus.
  • Only requests from KDE Partition Manager instance that started the helper are accepted. Everything else is ignored.
  • When KDE Partition Manager exits, it sends requests to KAuth helper to exit. Otherwise (e.g. if KDE Partition Manager crashes), the helper would exit after a short amount of time.

What was done

  • KDE Partition Manager had a lot of library calls that required root. In particular libparted was used to manipulate disks. I wrote a new sfdisk (part of util-linux) based backend which called sfdisk executable to manipulate partition table. util-linux is obviously GNU/Linux only but so was libparted. Nevertheless, this backend would be much easier to adapt to e.g. FreeBSD. util-linux 2.32 which was just released is required to have a fully functioning sfdisk backend.
  • While writing a new backend, I redesigned backend, so that its API would not be libparted specific. Since Calamares installer was using some of those calls (and it was not supposed to use them), I worked on porting Calamares away from those and as a result Calamares gained support for manipulating LVM logical volumes. Now Calamares can install into preexisting LVM volume groups.
  • As part of Season of KDE  program Caio J. Carvalho ported away from unmaintained libatasmart to smartmontools. We will require smartmontools 6.7 which is not yet released at the time of this post. This again improves FreeBSD support, as it has smartctl. libatasmart was GUN/Linux only.
  • Each call to external executables (e.g. fsck, btrfs, sfdisk, etc.) was then sent to KAuth helper. So at this stage we had a new KAuth call each time we wanted to run application. This allowed KDE Partition Manager to run without root but with two severe drawbacks:
    • When partitions were moved, coppied, all disk data had to be transefered from KAuth helper to the main application and back via DBus. But DBus is not suitable for transfering big amount of data.
    • Polkit authorization is kept for 5 minutes. So after 5 minutes a new authorization dialog would be shown. It could happen in the middle of operation.
  • In his Season of KDE project, Huzaifa Faruqui moved the data copying code from KPMcore library to KAuth helper. Thus we no longer had to move disk data over DBus. Initially we had some performance issues but those were solved when we switched from using dd to QFile.
  • For the second issue, instead of running a new KAuth helper each time we need to execute command as root, I started KAuth helper as a daemon that listens to requests from the main application. Since helper does not quit and is running all the time, Polkit 5 minute timeout does not apply.

What can be improved

  • All command calls now go through KAuth helper. Some of the commands (such as lsblk) could still be run as unprivileged user.
  • We can delay starting KAuth helper until it is needed. Then in some cases we might be able to postpone authentication until applying operations.
  • Caio J. Carvalho and I are still working on improving helper behaviour in case main application crashes (or is killed).
  • Needs more testing. Feel free to try kauth branches of kpmcore and partitionmanager repositories. I’ll probably release another version before merging this work to master.

While KDE Partition Manager worked on Wayland before, it now works better. If you want to run it via XWayland you no longer need to allow other users to use XWayland server (with xhost +) which is a big security improvement. Previously KDE Partition Manager only ran as a native Wayland client (so you needed QT_QPA_PLATFORM=wayland which Gnome session doesn’t have).

If you think that my work is useful, consider supporting me on

Become a patron Donate using Liberapay Bitcoin: bc1qe2dfqjwgse5v6cl6rhtk352ru90t0hnve45f2c

4 thoughts on “KAuth support in KDE Partition Manager

  1. I’m also not that familiar with the DBus design so I can’t say definitively if the call can be intercepted or monitored. But sending the UUID (which is the shared secret) with every call does increase the attack vector quite a bit.

    But even when using a shared secret you should only transmit this to the other side once, in a very secure way. You can use ideas from symmetric-key encryption for this, applying something like a DH key exchange. At this point you have a shared secret and you can actually encrypt the entire call with symmetric-key algorithms.

    Since you really only need to ensure the identity of the caller, a signature may suffice. In this case you would need asymmetrical cryptography, so a public-private keypair. Of course, you could still encrypt the call with this.

    Reply
    • Well, right now I started implementing RSA signatures (one of the two calls is now converted away from shared secret). Seems to work. Although, there are some other regressions in the codebase that I’ll have to fix. Unfortunately, KPM doesn’t have a proper test suite.

      Reply
  2. Nice work on both Partition Manager and this post explaining it.

    Since this is about improving security, this part caught my eye: “Only requests from KDE Partition Manager instance that started the helper are accepted. Everything else is ignored.”

    I took a look at how this is implemented and (if I understand it correctly) I think the user authentication (providing username and password) happens when the helper is started. Then a UUID is generated and you have to provide this UUID when you want your request to be accepted by the KAuth helper.

    I think this might be a security issue though. The UUID is sent along with every (legitimate) request to the helper so anyone that can see this traffic could then use the helper to execute commands as root. So this helper seems to allow privilege escalation.

    Is this problem mitigated in any way? Possibly by using encryption on the traffic? A more secure way to do this might be to generate a public-private keypair when starting the helper. Then you can sign each request, which should provide better guarantees about the identity of the entity that sent the request. Generating new keypairs would also ensure that any attack would have to succeed within the lifetime of the helper, as a new keypair means that previous analyses would be useless.

    I hope this helps improve security a bit (and that I understood this correctly).

    Reply
    • I was actually thinking about public-private keypair myself too. But so far from what I was reading, non-root users cannot intercept calls to DBus system bus (it’s not session bus). Correct me if this is wrong though. So at least for now I thought it would be quicker to get the whole thing working by just using a shared secret. But maybe for security reasons we should still generate public key.

      Reply

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required

Time limit is exhausted. Please reload CAPTCHA.