3

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.

2 Answers 2

2

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)).

1
  • 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, 2018 at 9:23
0

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.

1
  • I just ended up doing stuff like sudo chrt 99 ionice -c1 nice -n -20 sudo -u myuser ./myprogram options...
    – sehe
    May 8, 2021 at 23:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .