23

My program is using the Linux system call setpriority() to change the priorities of the threads it creates. It needs to set negative priorities (-10) but, as mentioned on the documentation, this fails when run as a normal user.

The user needs the CAP_SYS_NICE capability to be able to set the priorities as he wants, but I have no idea how to give such capability to the user.

So my question: how to set CAP_SYS_NICE capability to a Linux user?

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
CJlano
  • 1,532
  • 1
  • 12
  • 18

4 Answers4

20

There is a nice handy utility for setting capabilities on a binary: setcap. This needs to be run as root on your application binary, but once set, can be run as a normal user. Example:

$ sudo setcap 'cap_sys_nice=eip' <application>

You can confirm what capabilities are on an application using getcap:

$ getcap <application>
<application> = cap_sys_nice+eip

I'd suggest integrating the capabilities into your makefile in the install line, which is typically run as root anyhow. Note that capabilities cannot be stored in a TAR file or any derivative package formats. If you do package your application later on, you will need a script (postinst for Debian packages) to apply the capability on deploy.

Ryan Armstrong
  • 381
  • 2
  • 9
  • 2
    Your command works, but may I ask where you found that `cap_sys_nice=eip`, especially the `=eip` part? I can't see it neither in `man setcap`nor in `man capabilities`. – elmicha Jun 10 '17 at 21:47
  • 5
    @elmicha On my system at least, the man setcap page contains the following line: _The capabilities are specified in the form described in cap_from_text(3)_. Note that the cap_from_text manpage may not be available by default (even if you have setcap). On CentOS for example, it's available in the libcap-devel package. It describes the extra letters as 'operator flags', where e = effective, i = inheritable and p = permitted, respectively. – Ryan Armstrong Jun 12 '17 at 11:03
  • What does `eip` stand for ? And can I use this for running scripts ? – vbt Sep 02 '22 at 03:56
  • 1
    @vbt, please read the bottom of the previous reply for the meaning of those letters. You can theoretically apply capabilities on scripts, but I don't know what effect it will have. Try it if you need a capability you are missing. – Ryan Armstrong Sep 03 '22 at 12:25
4

Jan Hudec is right that a process can't just give itself a capability, and a setuid wrapper is the obvious way get the capability. Also, keep in mind that you'll need to prctl(PR_SET_KEEPCAPS, ...) when you drop root. (See the prctl man page for details.) Otherwise, you'll drop the capability when you transition to your non-root real user id.

If you really just want to launch user sessions with a different allowed nice level, you might see the pam_limits and limits.conf man pages, as the pam_limits module allows you to change the hard nice limit. It could be a line like:

yourspecialusername hard nice -10
mkj
  • 1,274
  • 11
  • 8
  • 4
    I know this answer is older than dirt but there is the pam_cap.so module which will read in `/etc/security/capability.conf` and set capabilities accordingly – Bratchley May 03 '13 at 19:25
0

AFAIK It's not possible to get a capability. Root processes have all capabilities and can give them up, but once given up, they can't be regained. So you'll need a suid-root wrapper that will give up all other capabilities and run the process.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
-1

Regarding sudo, I added the user like this:

niceuser ALL=NOPASSWD:/usr/bin/nice

And then it worked fine:

niceuser@localhost $ nice
0
niceuser@localhost $ sudo nice -n -10 nice
-10
squeegee
  • 762
  • 8
  • 10
  • 2
    Don't do this. It runs commands as root, which is not what you would normally want, and not what the original question was looking for. – Gregor Feb 10 '21 at 14:18