Bug 646478 - Replace SETUID in spec file with the correct file capabilities.
Summary: Replace SETUID in spec file with the correct file capabilities.
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: libcgroup
Version: rawhide
Hardware: Unspecified
OS: Unspecified
low
medium
Target Milestone: ---
Assignee: Jan Safranek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: removesetuid
TreeView+ depends on / blocked
 
Reported: 2010-10-25 13:29 UTC by Daniel Walsh
Modified: 2011-04-05 13:10 UTC (History)
6 users (show)

Fixed In Version: libcgroup-0.37-1.fc15
Doc Type: Bug Fix
Doc Text:
Clone Of: 646443
Environment:
Last Closed: 2010-12-13 13:47:58 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description Daniel Walsh 2010-10-25 13:29:12 UTC
+++ This bug was initially created as a clone of Bug #646443 +++

Description of problem:

Please remove setuid setup of files in your package with file capabilities.

This is to satisfy the F15 feature.

https://fedoraproject.org/wiki/Features/RemoveSETUID

An example of how this was done for X is.


%if 0%{?fedora} < 15
%define Xorgperms %attr(4711, root, root)
%else
%define Xorgperms %attr(0711,root,root) %caps(cap_sys_admin,cap_sys_rawio,cap_dac_override=pe)
%endif

Comment 1 Jan Safranek 2010-11-05 12:28:33 UTC
I am not sure, is this bug about generic suid executables or only suid executables owned by root are frowned upon?

libcgroup uses the suid flag in very stupid way: cgexec tool, executed by anybody, must talk to cgred daemon using unix socket /var/run/cgred.socket. The socket and /bin/cgexec is owned by root:root now, but it should not be hard to change their ownership to let's say cgred:cgred. The result would be more secure (no suid to root), but still with suid to (harmless) cgred user.

Of course, I can add proper capability to /bin/cgexec allowing it to connect to anything on the system, but IMHO it's less secure than the proposal above.

Comment 2 Daniel Walsh 2010-11-05 13:41:23 UTC
I would say it is just for suid root, since root gets capabilities.  I would think that suid to a non priv user would not be covered.  But why not just allow apps all UIDs to connect to /var/run/cgred.socket, without using suid?

Comment 3 Jan Safranek 2010-11-09 15:01:40 UTC
public access to /var/run/cgred.socket can be dangerous, it may deny/permit our cgrulesengd to move processes between control groups to anyone. cgexec first checks if the required operation is allowed and only then tells the daemon to do/not to do something using the socket.

We'll remove the suid-to-root, we might end up with suid to non-root when we don't find any better solution.

Comment 4 Daniel Walsh 2010-11-09 15:09:46 UTC
Why not move that logic to the daemon?  It knows the UID of the other end of the socket.

Lots of client server setups, authorize in the server, not in the client.

Comment 5 Jan Safranek 2010-11-10 11:17:28 UTC
The security thing is a bit more complicated. Short overview at the start:

- cgrulesengd (aka cgred) distributues processes among control groups based on some pre-configured rules. It runs in background and whenever a process satisfies a rule, it moves the process to defined control group. The rules can be e.g.:
  - all /usr/bin/firefox processes should be moved to group 'browser' (with e.g. strict memory limit)
  - all jsafrane's processes should be moved to group 'work' (with e.g. reserved 80% of CPU time)

- 'move a process to a control group' means write it's PID to a specific file in cgroup filesystem, kernel handles the rest. *This is the security check*, using standard rwx attributes or ACLs - if admin allows me to write to this file, I can move any process to the group. Every control group has separate file.

- cgrulesengd naturally runs as root and can move anything anywhere.

- cgexec is a tool to start a new process in given control group. I.e. it writes its PID to the right cgroup file and if it is allowed by kernel, it exec()s the desired executable.

Now, sometimes it is necessary to tell cgruleseng to disable the rules check for a specific process - if I cgexec a process in specific group, I do not want cgrulesengd to move it anywhere else. Thus cgexec opens a unix socket and tells the daemon not to mess up with the process. And this is where suid was used for - just to open the socket.

It is not desirable to allow anyone to open the socket - anyone can tell the daemon not to move a process to different group, which is (maybe) not what system admin wants. cgexec does not start anything if the user does not have the rights to move the process to target group - the security check (writing to file in cgroup filesystem) is done by cgexec, not by cgruleseng.

Comment 6 Jan Safranek 2010-11-12 12:24:15 UTC
Hi Steve,

the wiki page in the first comment recommends you as 'great source of information', could you please answer following question?

Do capabilities work with unix sockets? The socket is:
srwxr-xr-x. 1 root root 0 Nov 12 12:13 /var/run/cgred.socket

Cgexec has these capabilities (as I understand the man pages, it should mean it has all of them):
/bin/cgexec =ep

Still, cgexec cannot connect to the socket:
socket(PF_FILE, SOCK_STREAM, 0)         = 3
connect(3, {sa_family=AF_FILE, path="/var/run/cgred.socket"}, 23) = -1 EACCES (Permission denied)

Do I miss something? I admit it is my first experiment with capabilities and I might be doing something wrong.

Comment 7 Daniel Walsh 2010-11-12 14:39:55 UTC
The file capabilities would go on the program not the socket.  So it would need to be applied to cgexec.

It probably needs setuid, and maybe dac_override?  But it should drop capabilities after it connects to the socket.

Comment 8 Jan Safranek 2010-11-12 15:03:38 UTC
As I wrote above, the binary executable *has* all the capabilities, including dac_override, still I get 'EACCES' errors. It's not suid (that's the point, remove the suid flag and find the right capability).

Either the capabilities do not work on unix domain sockets or I am doing something terribly wrong...

I can still go with the 'cgred' user from comment #1, that's proven to work.

Comment 9 Daniel Walsh 2010-11-12 15:13:05 UTC
What does getcap cgred show?

Comment 10 Steve Grubb 2010-11-12 15:37:33 UTC
You should look at pscap when the program is running to see what capabilities you actually have. Even if you have all capabilities, a MAC policy can still override the capabilities. 

And lastly, if a program needs DAC_OVERRIDE, there is a big problem. DAC_OVERRIDE means that the program is unconfinable (except by MAC policy). It can read/write to any file. That would really mean that you would want to look at what its accessing that requires that kind of privilege. It might also be a hint that a setgid app would be a more secure choice.

Comment 11 Steve Grubb 2010-11-12 19:51:46 UTC
Looking at the daemon code, there is no chmod on the socket to restrict access. If the only security concern of cgexec is to write to the daemon socket, then I think in cgrulesengd.c you would do a chgrp() and chmod(660) of the socket. Then you would make cgexec be setgid to the group that you picked. I think this is better than messing with capabilities or worrying about setuid dropping privs.

Comment 12 Jan Safranek 2010-11-15 08:56:49 UTC
(In reply to comment #11)
> Looking at the daemon code, there is no chmod on the socket to restrict access.
> If the only security concern of cgexec is to write to the daemon socket, then I
> think in cgrulesengd.c you would do a chgrp() and chmod(660) of the socket.
> Then you would make cgexec be setgid to the group that you picked. I think this
> is better than messing with capabilities or worrying about setuid dropping
> privs.

Agreed, I'll fix it upstream. Thanks a lot for review!

Comment 13 Jan Safranek 2010-12-13 13:47:58 UTC
/bin/cgexec is now SGID with group 'cred' and the /var/run/cgred.socket is cgred-writeable.


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