Is it possible to configure Linux capabilities per user? [closed]
Asked Answered
L

4

48

There appears to be support for fine-grained capabilities in Linux kernel, which allows granting privileges to a process to do things like, for example, opening raw sockets or raising thread priority without granting the process root privileges.

However what I'd like to know if there is a way to grant per-user capabilities. That is, allow non-root and non-suid processes to acquire those capabilities.

Linguistic answered 24/12, 2009 at 4:49 Comment(2)
How is this closed? Modern stackoverflow in a nutshellSpittle
I can't answer because it's closed, but the solution (with Linux 4.3+) is Ambient capabilies -- they exactly grant inherited per-user capabilities.Multilateral
H
68

It can sort of be done with libcap - it provides a PAM module pam_cap.so. However it's not quite that simple :)

Each process has three capability sets:

  • Effective (the caps that this process actually has)
  • Permitted (the caps that this process can possibly have - a superset of Effective)
  • Inheritable (the caps that this process can pass to a child process)

Each file has the same capability sets. When a new binary is exec()'d, the capabilities of the process change according to the following rules, where:

  • pI/pP are the process's initial Inheritable/Permitted capabilities
  • pI'/pP'/pE' are the process's new Inheritable/Permitted/Effective capabilities
  • fI/fP/fE are the file's Inheritable/Permitted/Effective capabilities
  • & represents intersection
  • | represents union

    pI' = pI
    pP' = fP | (pI & fI)
    pE' = fE & pP'

(simplified from http://www.friedhoff.org/posixfilecaps.html)

In most scenarios, pE' is the only result we care about. Programs that are linked against libcap can call setcap() to change their Effective caps (as long as the caps they try to request are in the Permitted set), but the vast majority of programs don't explicitly touch their caps so we have to arrange for the cap to be effective post-exec().

Having a concrete example will help understanding here... I got fed up with having to 'su' to run openvpn, so I wanted to grant myself the CAP_NET_ADMIN capability to allow the setting of routes and such.

Looking at the last rule (pE' = fE & pP') it's clear that to have CAP_NET_ADMIN in the process's Effective set, CAP_NET_ADMIN must be in the file's Effective set. So, the capabilities system doesn't allow us to simply say "grant CAP_NET_ADMIN to user sqweek" - the program's capabilities are always important.

Being in the file's Effective set isn't enough though, the cap also needs to be in the process's new Permitted set. Lets look at that rule: pP' = fP | (pI & fI). So there's two ways we can get the cap in pP', either we add CAP_NET_ADMIN to the file's Permitted set, or we add it to the file's Inheritable set and make sure it is in the process's Inheritable set.

If we add it to the file's Permitted set, then the process's initial capabilities become irrelevant - openvpn will get CAP_NET_ADMIN every time it runs, regardless of who runs it. This is similar to setuid, but provides a more fine-grained approach. Still, it is not a per-user granularity, so lets look at the other option.

Note the first rule, pI' = pI. The process's Inheritable capabilities are unaffected by exec(). What this means is, all we need is a single libcap aware program to set CAP_NET_ADMIN as an Inheritable cap, and every process spawned from there will also have CAP_NET_ADMIN Inheritable. This is the role the pam module plays - it modifies the Inheritable set during login, which is then inherited for all of that user's processes.

To summarise:

  1. Install libcap
  2. Configure the pam_cap module (add the line cap_net_admin sqweek to /etc/security/capability.conf. If the file did not previously exist, add another line none * for a sensible default.
  3. Enable the PAM module during login (add auth required pam_cap.so to /etc/pam.d/login). Make sure to test your login in a separate terminal BEFORE logging out when making PAM changes so you don't lock yourself out!
  4. Add CAP_NET_ADMIN to the Effective and Inheritable sets for openvpn (setcap cap_net_admin+ie /usr/sbin/openvpn)
  5. openvpn calls ip to change the routing table and such, so that needs the same treatment (setcap cap_net_admin+ie /sbin/ip)

Note that /etc/pam.d/login only governs local logins - you might want to give eg. /etc/pam.d/sshd similar treatment. Also, any capabilities you add via setcap will be blown away when your package manager installs a new version of the target binary so you'll have to re-add them.

Hoodmanblind answered 16/7, 2013 at 19:22 Comment(17)
Still, it's not much use to us, so lets look at the other option. Why is that not much use? In a multi-user system I could see the limitation, that it grants the capability to all users, so if you want to do it on a per-user basis it's not of much use. But most Linux machines today are de facto single user machines, so I don't see the problem. (Well, there might be some service running as different user.)Crib
I'm not really sure what to say, as you've answered your own question. The OP was asking how to set capabilities per user, and adding caps to the file's permitted set controls them on a per binary basis (which, to be clear, is still useful functionality). I agree it's a moot point on many systems, but even so explaining how to set capabilities for a specific binary is not answering the question being asked.Hoodmanblind
You are of course correct. I had already forgotten the original question when studying your answer. I have clarified the reasoning now, let's see whether my edit gets approved.Crib
Looks like they were. Btw I have to retract my statement "I agree it's a moot point on many systems", I must have been feeling very agreeable yesterday :P. Even on a single user system different accounts have applications. For example while I'm the only user of my laptop, I run my web browser under a separate user account so that a vulnerability in the browser cannot, by itself, expose my personal data. Obviously I don't want to let this account modify my network routes :PHoodmanblind
If you run your Web browser in a different account, then you have no longer a single user machine. Well, user as in human in front of the keyboard yes. but user as in uid no. The latter might be useful but (with very minor exceptions) it's not the way distros are delivered today (at least none I know of). But I think we agree on how the capabilities work.Crib
One question. I don't understand why you need libcap installed to do that. Can someone please explain to me why. ThanksOysterman
@John libcap provides an interface to fiddle with linux capabilities. Presumably you could achieve the same outcome with direct syscalls, but the utilities mentioned in the answer (setcap, pam_cap.so) all depend on libcap (on my system they're even distributed in the same package).Hoodmanblind
@Hoodmanblind : If a capability is only present only in the inheritable set, does it change Something or not having them at all create the same result ? https://mcmap.net/q/507427/-what-does-it-means-to-have-a-capability-only-in-the-inheritable-setRaouf
If I want to call "schedtool -F binary" from a script, what is the advisable way to do so? Should I add the inheritable+permissible bit to bash and schedtool?Frizz
I'm not familiar with schedtool or the capabilities it needs, but there's no need to touch /bin/bash. As long as you've done the PAM setup, the caps will be inheritable from your environment so setcap cap_XXX+ie on the schedtool binary is all that is required for it to pick them up. Note that you'll need to redo the setcap whenever you upgrade schedtool, as reinstalling it blows away your customisations.Hoodmanblind
@sqweek: I'm trying to use your method to run rsync with cap_dac_read_search in order to make full system backups (read the entire filesystem) using a certain user. I've created /etc/security/capability.conf with cap_dac_read_search username and added auth required pam_cap.so to /etc/pam.d/login. And: getcap /usr/bin/rsync shows /usr/bin/rsync = cap_dac_read_search+ei. After I open a new shell via ssh, rsync still can't access the entire filesystem - why? Adding cap_dac_read_search+ei to capsh and running it in a new shell also shows no capabilities in "Current:".Cakewalk
Okay, I was able to solve the problem by myself. For anyone else who stumbles upon this, here the solution: Of couse, /etc/pam.d/login only gets sourced for logins, where the login binary is called. That means, local logins. For this setting to apply to ssh logins as well, either include the auth required pam_cap.so to /etc/pam.d/sshd as well, or use it in some meta file like /etc/pam.d/system-login or similiar (although I don't know if this might have other implications). But then it works!Cakewalk
Thanks @LukeLR! I've added a note that /etc/pam.d/sshd will also need changing to affect ssh logins.Hoodmanblind
For Debian users: you will have to install package "libpam-cap". The better part is it creates /etc/security/capability.conf and automatically configs pam_cap.so for you.Ockeghem
With Linux 4.3, this can be done with ambient capabilitiesMultilateral
None of this seems to work in Debian 11 (kernel 5.16.x). Have added cap_setfcap for my user in /etc/security/capability.conf -- capsh still shows empty for current capabilities, and I need to sudo whenever I want to grant a program some capabilities. (Those don't seem to work either; getcap shows the caps were granted, but when the program tries to exercise it's permissible capabilities (using cap_set_proc()), it's always "permission denied" all the way down, past the turtles).Seagoing
@houneusto did you see LukeLR's comment regarding pam.d config? Editing capability.conf is not enough by itselfHoodmanblind
P
9

Yes, you can use setcap to specify a capability set for an executable, which can grant specific capabilities when that executable is run.

From the capabilities(7) man page:

File Capabilities Since kernel 2.6.24, the kernel supports associating capability sets with an executable file using setcap(8). The file capability sets are stored in an extended attribute (see setxattr(2)) named security.capability. Writing to this extended attribute requires the CAP_SETFCAP capability. The file capability sets, in conjunction with the capability sets of the thread, determine the capabilities of a thread after an execve(2).


The way to grant capabilities per-user (or even per-group) would be with a PAM module. sqweek's answer shows how to do this using pam_cap.

Pillow answered 25/12, 2009 at 23:19 Comment(1)
Yes, I know you can set capabilities per executable. My question, however, is if you can set the capabilities per-user, that is, all executables run under the user are granted certain capabilities.Linguistic
M
5

I've not confirmed, but I think that this aspect of SELinux may be your answer:

http://www.lurking-grue.org/writingselinuxpolicyHOWTO.html#userpol5.1

Mainstream answered 24/12, 2009 at 4:56 Comment(3)
+1 for SELinux. It solves this problem nicely.Triphylite
Thanks, I will consider it, however changing over to SELinux may be quite burdensome for existing infrastructure.Linguistic
link expired and original post should have contained a summary of its content relevant to this question.Pneumograph
C
3

Have a look at CapOver - it should do what you want.

Note: I haven't used this as it's not (yet?) been ported to the 2.6.30ish kernel API.

Christianchristiana answered 4/5, 2011 at 7:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.