I have some code which uses sched_setscheduler from sched.h

sched_param sched;
sched.sched_priority = 70;
sched_setscheduler(getpid(), SCHED_FIFO, &sched);

However, this function will fail unless I run the application with sudo. I'd rather not run the application with root privileges.

Is there a way for me to grant a user or process access to this function without granting full root permissions?

-- Edit --

derobert gave a great answer about using capabilities. In postinst, I simply add:

setcap cap_sys_nice+ep /path/to/myapp

The problem here is:

bin$ ./myapp
./myapp error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory

The program loses the ability to dynamically load libraries from $LD_LIBRARY_PATH or (in my case) other libraries pointed by rpath. This appears to be intended behaviour. Is there a way around this?

I've tried setcap cap_setpcap+ep myapp then using prctl(PR_CAPBSET_DROP, CAP_SETPCAP); before I do any of the dynamic loading, but that doesn't seem to help.


Changing your scheduler & priority should only need the CAP_SYS_NICE capability; see the sched(7)'s Privileges and resource limits. You'll probably also want to look at the manpage for sched_setscheduler, which mentions sched(7).

There are a few ways to give your program that capability; the easiest is probably setcap:

# setcap cap_sys_nice=ep /usr/local/bin/your-program

That works similarly to set-user-id, but is much more limited (as it only gives the one capability). Of course, CAP_SYS_NICE effectively gives the program permission to hang the system (by eating all CPU time with realtime tasks).

Other ways include using a runs-as-root wrapper (that drops all other permissions) or elevation using, e.g., RealtimeKit/PolicyKit.

(For more information on capabilities, I suggest starting with capabilities(7)).

  • When I use setcap, My program ignores its custom rpath and can't load some specific *.sofiles. This seems to be intentional. How can I drop these capabilities when I am done with them so I can dynamically load the appropriate *.so files after that? – Stewart Jul 16 '18 at 9:23

I have a solution, though it's a little weird and exposes a hole in the OS.

During postinst, I:

cp $(which chrt) bin/chrt
setcap cap_sys_nice+ep bin/chrt

Then in the code, I launch a process with:

bin/chrt -o -p 70 getpid()

The hole we just exposed is that anyone who uses this version of chrt can do it without admin privileges. Since I'm running this is a very controlled target environment, I'm okay with that hole, but I wouldn't recommend it who doesn't have control over their target environment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.