replace PolicyKit with resmgr

David Zeuthen david at fubar.dk
Sat Jul 22 10:13:11 PDT 2006


Hi,

On Wed, 2006-07-12 at 09:47 +0200, Ludwig Nussel wrote:
> On Tuesday 11 July 2006 00:28, David Zeuthen wrote:
> > On Mon, 2006-06-26 at 15:01 +0200, Ludwig Nussel wrote:
> > [...]
> > > 'temporary', 'restrictions' and any dbus connection related stuff is
> > > not handled by resmgr but I doubt those features are actually needed
> > > anyways. We don't need to 'protect' two processes with the same uid
> > > from each other and all privileges are revoked when the user logs
> > > out anyways. 
> > 
> > For the same reasons that people have a lock on their diary so the
> > adolescent younger sibling of yours in the same household don't mess
> > with it? Hmm.. ok, maybe that's a bad analogy.
> > 
> > In a nutshell it's like this: it's an extra layer of security such that
> > only the process who actually obtained the privilege can use it through
> > the D-BUS connection it obtained it through.
> > 
> > Of course some people say that once that an attacker can execute
> > unprivileged code in a session it's "game over". This extra layer of
> > security, however, basically comes for free.
> 
> I don't see the security benefit. The price is that it forces
> policykit to use a dbus connected daemon.

That's a price I'm willing to pay. The point, really, is that HAL, as a
mechanism, needs to figure out whether some user is privileged to do
something very well-defined. And I want to move that decision out of
HAL. And I don't want to force people on how this decision is made.
Hence, we have an abstraction we can ask. 

And we better provide enough information to that abstraction such as 

 1. What it is the user wants to do. Obviously, since HAL is the
    mechanism this is the privilege and it needs to be the same
    privilege passed every time someone calls e.g. Mount().

 2. What resource HAL wants to do this on. This is why we provide
    a resource identifier, e.g.

     hal:///org/freedesktop/Hal/devices/volume_uuid_44BD_6EF8

 3. What user/process is wanting to do this. Here we just pass the
    unique name of the D-BUS connection the user has on the system
    bus. Given that, e.g. :1.234, the PolicyKit daemon can lookup
    tons of information, e.g. uid, pid.

    (Oh, and, in a future maybe not too far away, the PolicyKit daemon
     might ask the X server via D-BUS "is the user with this pid
     connected to you and are you currently displaying that session?".
     We need this for e.g. fast-user-switching to refuse service for
     desktop sessions not currently displayed. The good news is that
     the X.org people I talked to at OLS agrees this is needed.)

The point is this: we can replace the PolicyKit implemention with stuff
that is a lot smarter than just reading ini-based files. Some day it can
read from LDAP. Or whatever. Also, we can make the "Decision" the
PolicyKit daemon makes a function of the system. We can do all sorts of
really crazy stuff but that is not the point. 

The point is that we want a well-defined abstraction, well-defined API
and then we can change the implementation underneath at our convenience.

Let me ask you this. Assume for a while you share this goal. This goal
of having a well-defined API for the entity making decisions. Given this
goal, does the API look reasonable?

So, yes, I'm very willing to trade off using D-BUS for this. Performance
and security-wise the PolicyKit daemon can use activation on the system
bus (admittedly, D-BUS needs work here but it's feasible) to only start
the daemon when it's used.

The alternative you're suggesting sacrifies all this. And for what? Not
needing to run a D-BUS connected daemon? Complexity?

PolicyKit is already done though and, of course (I would be crazy to not
say this), it needs a lot of review and testing before it's ready for
prime time. So maybe HAL 0.5.8 will optionally depend on PolicyKit, but
later versions will need to depend on this. 

We just cannot add more features to HAL with the "all or nothing"
approach we've been taking this far. It inhibits us.

> Btw, what happens if dbus or polkitd need to be restarted e.g. due
> to a security update while users are logged in?

polkitd can happily be restarted, users having temp privileges will just
lose them. For everything but the synthesized 'desktop-console'
privilege it's not a problem as these privileges are only used for a
short amount of time, e.g. 1) a user auth for the temp priv; 2) the app
carries out whatever it needs to do; 3) the app gives up the temp
privilege. So in reality this is not a problem as when you restart the
users will get the 'desktop-console' privilege anyway as it's
synthesized from files left by pam-polkit-console.

If dbus needs a security update you need to restart the bus _only_ if
the security update applied to the running bus code, e.g. more than
libdbus. 

And the view most of the D-BUS developers (including myself) have on
this, is that instead of teaching apps to cope with bus restarts (adding
lots of complex code to each and every app) you have to restart your
desktop session and/or reboot. This is not really different from how the
kernel or X.org packages work - and only really crazy people (emacs is
the only one I think) add code to make their app handle the X11
connection going away :-)
 
> > > I don't understand what 'resources' are supposed to be
> > > so I just used them for the devices that are associated with
> > > classes.
> > 
> > Resources were meant to be a finer granularity of privileges so you
> > could be privileged only on e.g. certain resources, e.g. devices
> > specified by HAL Unique Device Identifiers (UDI's). For example you
> > would be privileged to be able to mount only "dave's usb key" but not
> > anything but that.
> > 
> > I think I'm going to remove the concept of resources from PolicyKit: it
> > turned out to be a lot more confusing for very little benefit (it's
> > trivial to spoof e.g. file system UUID's). It will also make the code
> > significantly simpler to read and audit when I've removed the resource
> > stuff in PolicyKit.
> 
> Good. If you want to treat "dave's usb key" different you could just
> as well introduce a different privilege for it, eg
> hal-storage-mount-daves-usb-key instead of
> hal-storage-removable-mount :-)

So I was thinking a bit more about this. And that's, btw, partly why I
so slow in replying - this is new stuff and I keep going back and forth
around design decisions.

I think we still want HAL to pass the resource for "Dave's USB key",
e.g. the PolicyKit resource identifier such as 

 hal:///org/freedesktop/Hal/devices/volume_uuid_44BD_6EF8

to the PolicyKit daemon. But I'm probably going to change the
implementation such that the PolicyKit daemon ignores it. If we have a
need for it (e.g. when we want the Policy Decision to be more complex)
we can always add it later. Because our API's should be future proof.

> > > So what about using the already working resmgr as replacement for
> > > polkit (and pam_console)?
> > 
> > I'm just not sold on the idea; to mention a few concerns
> > 
> >  1. There needs to be a way for applications to install privilege
> >     descriptors, a'la what is on page 35 of [1]
> 
> Sure.

Oh, and please note that privilege descriptors right now are tied to the
implementation we're using. And that's fine. Future back-end's of the
PolicyKit daemon might not use them because they read settings from
elsewhere. And they can communicate through the D-BUS API what settings
they use, e.g. CanGrant, CanObtain etc. is all abstracted in the D-BUS
API.

> >  2. In the privilege descriptor it should be easy to specify what
> >     processes/users automatically receive what privileges. For example
> >     if I have a process running in a specific SELinux security context
> >     I really want it to have the privilege 'punch-hole-in-firewall'.
> >     See page 47 of [1] for the example.
> 
> Hmm, that idea somehow causes me itching.
> 
> >  3. "gnomesu resmgr grant $USER $PRIVILEGE" just looks like a hack to
> >     me. It doesn't give the UI integration you really want, e.g.
> 
> [insert gnomesu disclaimer from above here] The GUI runs
> unprivileged, you can use a custom one for a specific purpose.
> 
> >                 +----------------------------------------------------+
> >                 | You need to authenticate to access the storage     |
> >                 | device "Dave's USB Key".                           |
> >                 |                                                    |
> >                 |       User: [Dave___________]                      |
> >                 |   Password: [_______________]                      |
> >                 |                                                    |
> >                 |   Would you also like to automatically allow       |
> >                 |                                                    |
> >                 | ( ) This user to mount a removable storage device  |
> >                 | ( ) Any user to mount a removable storage device   |
> >                 |                                                    |
> >                 | [<- Drives and Media Preferences]          [Mount] |
> >                 +----------------------------------------------------+
> 
> What would happen next if the user checks one of the radio buttons
> and clicks 'mount'?
> 
> The radio buttons refer to different privileges than what the dialog
> is authenticating. So if you want to allow 'Any user to mount a
> removable storage device' PAM might want to ask different questions
> as policy applies different rules. Like for example only accept root
> authentication for the privileges referred to by the radio buttons
> whereas mounting one specific device only requires user
> authentication. I don't think you want to bother users with such a
> dialog in practice.

No, we've just make the decision to say this is not possible. If you
specifiy that a privilege can be granted, e.g. CanGrant in

 http://webcvs.freedesktop.org/hal/PolicyKit/doc/spec/polkit-spec.html?revision=1.7#id2988375

then it just means that the user can grant this privilege to whomeever
he wants. So one have to be careful about using CanGrant but in reality
this is hardly a problem. 

It's a tradeoff we're doing and, really, CanGrant is only there for the
"one-time-pain" dialogs for casual stuff for making sure that home users
can easily get to their fixed Windows and Mac OS X partitions.

Note that we still need a) API in libpolkit-grant to do this, e.g.

 gboolean libpolkit_grant_can_grant_privilege()
 gboolean libpolkit_grant_permanent_grant_of_privilege(uid_t users[],
                                                       gid_t groups[])

and b) implementation in polkitd to create sidecar files. This isn't a
lot of work, I just haven't gotten any patches for it yet. Hint hint
notch notch :-)

Of course, since this whole thing is D-BUS based, nothing prevents
someone from providing patches that enables uid 0 (or someone with the
right PolicyKit privilege!) to call into the PolicyKit daemons to edit
exactly what users are allowed to do what they want, e.g. write UI
applications with this UI

        +------------------------------------------------+
        | ( ) No user can mount fixed drives             |
        | ( ) Any user can mount fixed drives            |
        | (*) Restrict mounting of fixed drives to       |
        |      the following users and groups:           |
        |      +-------------------------------+         |
        |      | U davidz                     ^|         |
        |      | U dilbert                    ||         |
        |      | G admins                     ||         |
        |      | G releng                     V|         |
        |      +-------------------------------+         |
        |       [Delete] [Add Group] [Add User]          |
        |                                                |
        | ( ) No one can mount removable drives          |
        | ( ) Any user can mount removable drives        |
        | (*) Restrict mounting of removable drives to   |
        |      the following users and groups:           |
        |      +-------------------------------+         |
        |      | U jane                       ^|         |
        |      | U john                       ||         |
        |      | G admins                     ||         |
        |      | G secretaries                V|         |
        |      +-------------------------------+         |
        |       [Delete] [Add Group] [Add User]          |
        |                                                |
        |                                        [Close] |
        +------------------------------------------------+
        
and this is indeed what we want to do in the future. Of course, the
PolicyKit daemon might refuse this if the back-end it is using is not
based on text files or if it's reading from the network etc. That's
fine.

Again, it's about providing a future proof API that _completely_
separates mechanism (obtaining the Decision) from policy (figuring out
what the Decision is). 

I submit this is a lot easier using D-BUS. Do you disagree? Or do you
simply think there are diminishing returns for the extra complexity?
Remember that the code _is already there_, I've already written this
stuff.

So, I hope this mail clarifies why the design of PolicyKit is what it is
and why I think this is important. I'd also love to see patches and
contributions and I hope we can work together on this.

Cheers,
David




More information about the hal mailing list