Bug 668831 - why is gnome-keyring-daemon setuid root?
Summary: why is gnome-keyring-daemon setuid root?
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: gnome-keyring
Version: rawhide
Hardware: Unspecified
OS: Unspecified
low
medium
Target Milestone: ---
Assignee: Tomáš Bžatek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2011-01-11 18:20 UTC by Daniel Walsh
Modified: 2015-03-03 22:57 UTC (History)
5 users (show)

Fixed In Version: gnome-keyring-2.91.4-3.fc15
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2011-03-18 12:27:19 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
patch attempting to fix problem (5.89 KB, patch)
2011-01-13 14:11 UTC, Steve Grubb
no flags Details | Diff
improved patch addressing capabilities (5.72 KB, patch)
2011-01-13 14:32 UTC, Steve Grubb
no flags Details | Diff
patch removing suid setting (994 bytes, patch)
2011-03-11 14:54 UTC, Tomáš Bžatek
no flags Details | Diff

Description Daniel Walsh 2011-01-11 18:20:16 UTC
We are trying to eliminate these apps, and this one just became setuid.

Comment 1 Tomáš Bžatek 2011-01-12 11:15:27 UTC
This is coming from the following commit: http://git.gnome.org/browse/gnome-keyring/commit/?id=bc2d1d3789368779e6a39bff6ca841188edef6c7

> # The daemon is installed as setuid so as to obtain specialized
> # capabilities, then immediately drops permissions. In other words,
> # it does *not* run as setuid.
> # If installing as non-root, chown+chmod will not succeed but
> # the build will continue.
> install-exec-hook:
>  chown root $(bindir)/gnome-keyring-daemon || true
>  chmod u+s $(bindir)/gnome-keyring-daemon || true

Comment 2 Daniel Walsh 2011-01-12 17:33:55 UTC
From the patch it looks like it is using ipc_lock, can we use file capabilities instead of setuid.  Not sure why they are locking the memory?  Prevent it from swapping?

Comment 3 Steve Grubb 2011-01-12 17:58:14 UTC
Yes, this should be possible to use file system based capabilities. But about the patch, I don't think it does what they think it does. It drops all capabilities and then tries to change the uid. However, we dropped the setuid capability. So, does it really do that? Running as a user with a capability requires using prctl(). This patch would have been correct and only 3 lines long if they used libcap-ng rather than libcap.

Comment 4 Steve Grubb 2011-01-13 10:15:00 UTC
I ran a test of the code in that patch. This is what it does before and after:

before:4325 0
Effective:    00000003, FFFFFFFF
Permitted:    00000003, FFFFFFFF
Inheritable:  00000000, 00000000
Bounding Set: 00000003, FFFFFFFF
after:4325 4325
Effective:    00000000, 00000000
Permitted:    00000000, 00000000
Inheritable:  00000000, 00000000
Bounding Set: 00000003, FFFFFFFF

It did not keep the IPC_LOCK capability, but it was able to change the effective uid away from 0. I then tested the following code based on the libcap-ng library:

 capng_clear(CAPNG_SELECT_CAPS);
 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_IPC_LOCK);
 if (capng_change_id(getuid(), getgid(), 0))
   printf("failed");

Notice how much smaller the code is. :) The same test:

before:4325 0
Effective:    00000003, FFFFFFFF
Permitted:    00000003, FFFFFFFF
Inheritable:  00000000, 00000000
Bounding Set: 00000003, FFFFFFFF
after:4325 4325
Effective:    00000000, 00004000
Permitted:    00000000, 00004000
Inheritable:  00000000, 00000000
Bounding Set: 00000003, FFFFFFFF

Now it has the capability. So, I would say that the code doesn't work right. 

Changing this to file system based capabilities would do the right thing. The program would be running with just the IPC_LOCK capability for normal users. For root it will have all caps. So, you would want the following patch:

capng_get_caps_process();
if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_FULL) {
    capng_clear(CAPNG_SELECT_BOTH);
    capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_IPC_LOCK);
    if (getuid() != geteuid())
        if (capng_change_id(getuid(), getgid(), 0))  //setuid
            exit(1);
    else
        if (capng_apply(CAPNG_SELECT_CAPS))  // root user
            exit(1);
}

And then when it no longer needs capabilities:

 capng_clear(CAPNG_SELECT_CAPS);
 capng_apply(CAPNG_SELECT_CAPS);

Comment 5 Steve Grubb 2011-01-13 14:11:02 UTC
Created attachment 473323 [details]
patch attempting to fix problem

The attached patch should allow either setuid or file system based capabilities to work correctly.

Comment 6 Steve Grubb 2011-01-13 14:32:04 UTC
Created attachment 473333 [details]
improved patch addressing capabilities

This patch is a slight improvement in that we really do not need to check if euid != uid. We can just do it regardless.

Comment 7 Tomáš Bžatek 2011-01-13 14:59:48 UTC
Good work, Steve. Notified Stef and Yaron to have their word on this.

Comment 8 Tomáš Bžatek 2011-01-17 15:11:27 UTC
Packaged in gnome-keyring-2.91.4-3.fc15

Used "%attr(0755,root,root) %caps(cap_ipc_lock=ep) %{_bindir}/gnome-keyring-daemon" for gaining required capability. Only not sure about that "ep", judging from CAPNG_EFFECTIVE|CAPNG_PERMITTED from the code above. Please correct me if I'm wrong.

I talked to Stef and agreed to give our users some time to test this.

Comment 9 Steve Grubb 2011-01-17 15:19:44 UTC
Yes, that would be the file system capabilities I would expect. Thanks!

Comment 10 Stef Walter 2011-03-09 15:47:09 UTC
Tomas, I'm getting ready to merge this upstream, could you write up something that I can include in the release notes for packagers on how to package this?

Do you know if packaging file capabilities works with .deb packages?

Comment 11 Stef Walter 2011-03-10 16:04:32 UTC
Pushed this to gnome-keyring master. It looks like however the daemon is still installed as setuid: daemon/Makefile.am is not changed. Is another patch coming for that?

Comment 12 Tomáš Bžatek 2011-03-11 14:41:11 UTC
(In reply to comment #10)
> Tomas, I'm getting ready to merge this upstream, could you write up something
> that I can include in the release notes for packagers on how to package this?
> 
Sure:

Since the 2.91.93 release gnome-keyring-daemon makes use of file capabilities (via libcap-ng), specifically CAP_IPC_LOCK. To actually be able to use the particular capability, the binary executable must be set with corresponding file caps. This can be done several ways:

 1. manually by setcap command

 2. in rpm spec file, just add "%caps(<caps>)" modifier before the packaged file.
    The <caps> argument is a list of file capabilities in a format described in 
    cap_from_text(3) man page.

    So the actual line would look like this:
    %attr(0755,root,root) %caps(cap_ipc_lock=ep) %{_bindir}/gnome-keyring-daemon

> Do you know if packaging file capabilities works with .deb packages?

Couldn't find anything relevant in Google, better to ask Debian/Ubuntu folks directly. An inspiration might be "iputils" package which in Fedora uses filecaps, but not in Debian apparently. FYI, file caps are stored in xattrs and not all filesystems support that. 

Found a whiteboard that might come handy: https://wiki.ubuntu.com/Security/FilesystemCapabilties

Comment 13 Tomáš Bžatek 2011-03-11 14:54:33 UTC
Created attachment 483745 [details]
patch removing suid setting

(In reply to comment #11)
> Pushed this to gnome-keyring master. It looks like however the daemon is still
> installed as setuid: daemon/Makefile.am is not changed. Is another patch coming
> for that?
Yeah, this is not needed anymore.

Comment 14 Stef Walter 2011-03-16 14:32:51 UTC
Thanks Tomas for the write up. I didn't use this patch, because it completely removes the setuid support. Instead I committed something that disables it conditionally based on whether we're using libcapng or not. Let me know if it looks wrong. Here's the commit:


commit b9d69a5751c421cca2bee9bab78c1067e1d1acac
Author: Stef Walter <stefw.uk>
Date:   Wed Mar 16 15:26:44 2011 +0100

    If we're using linux capabilities then use setcap instead of setuid.
    
    Only use setuid when not using linux capabilities. Run this on
    install when we are using caps:
    
    setcap cap_ipc_lock=ep $(DESTDIR)$(bindir)/gnome-keyring-daemon

Comment 15 Tomáš Bžatek 2011-03-18 12:27:19 UTC
(In reply to comment #14)
> Instead I committed something that disables it conditionally
> based on whether we're using libcapng or not.
Looks good, thanks.

I consider this bug as fixed, closing. Feel free to open separate bug reports if anything goes wrong.


Note You need to log in before you can comment on or make changes to this bug.