Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPERM running chrt from shell with positive niceness #359

Closed
glangshaw opened this issue Sep 27, 2016 · 7 comments
Closed

EPERM running chrt from shell with positive niceness #359

glangshaw opened this issue Sep 27, 2016 · 7 comments

Comments

@glangshaw
Copy link

Found in util-linux-2.28.2, linux-4.4.22 (slackware current 2016-9-26)

'chrt -b' run from a non-root shell with positive niceness results in an EPERM:

sched_setattr(9555, {size=48, sched_policy=SCHED_BATCH, sched_flags=0, sched_nice=0,sched_priority=0, sched_runtime=0, sched_deadline=0, sched_period=0}, 0) = -1 EPERM (Operation not permitted)

Example usage:

test@ws1:~$ chrt -v -b 0 date
pid 10037's new scheduling policy: SCHED_BATCH
pid 10037's new scheduling priority: 0
Tue 27 Sep 10:34:31 BST 2016
test@ws1:~$ renice -n 19 -p $$
10031 (process ID) old priority 0, new priority 19
test@ws1:~$ nice
19
test@ws1:~$ chrt -v -b 0 date
chrt: failed to set pid 0's policy: Operation not permitted
test@ws1:~$ 

@karelzak
Copy link
Collaborator

karelzak commented Sep 30, 2016

This is kernel feature, you can't de-increment priority:

$ renice -n 5 -p $$
3109 (process ID) old priority 5, new priority 5

$ renice -n 4 -p $$
renice: failed to set priority for 3109 (process ID): Permission denied

man renice:
Users other than the superuser may only alter the priority of processes they own, and can only monotonically increase their ``nice value'' (for security reasons)...

@glangshaw
Copy link
Author

Yes, I'm aware of that, but I wasn't asking 'chrt' to re-increase the niceness, merely put an already niced job into SCHED_BATCH. It used to work in previous versions of 'chrt', I'm assuming this is because chrt is using sched_setattr() which takes a niceness as a parameter, rather than sched_setscheduler() which doesn't..

@karelzak karelzak reopened this Sep 30, 2016
@karelzak
Copy link
Collaborator

Ah, see... will fix it.

@karelzak
Copy link
Collaborator

Well, both syscalls have priority as argument and it should be zero for SCHED_BATCH. It's strange and inconsistent API that sched_setattr() interprets zero priority as attempt to change task priority. It makes the syscall useless... I'll ask kernel developers.

@glangshaw
Copy link
Author

Both have a sched_priority field and as I understand it that should always be 0 (zero) for SCHED_BATCH/OTHER, however the struct for sched_setattr also has a sched_nice field, and I'm guessing that is the one that is causing the problem when encountering inherited niceness.

Thank you for following this up.

@karelzak
Copy link
Collaborator

Good point, thanks. Seems that something like:

diff --git a/schedutils/chrt.c b/schedutils/chrt.c
index edae0d9..f832d5b 100644
--- a/schedutils/chrt.c
+++ b/schedutils/chrt.c
@@ -26,6 +26,8 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>

 #include "c.h"
 #include "nls.h"
@@ -364,7 +366,8 @@ static int set_sched_one(struct chrt_ctl *ctl, pid_t pid)
                .sched_priority = ctl->priority,
                .sched_runtime  = ctl->runtime,
                .sched_period   = ctl->period,
-               .sched_deadline = ctl->deadline
+               .sched_deadline = ctl->deadline,
+               .sched_nice     = getpriority(PRIO_PROCESS, pid)
        };
        int rc;

fixes the problem (but not well tested yet).

@glangshaw
Copy link
Author

glangshaw commented Oct 1, 2016

Or maybe use sched_getattr() to return the current state in a struct sched_attr, change only the desired member(s) and pass it back into sched_setattr() ? Whether that's cleaner than your solution above I'll leave with you.

I did try to do some testing on this here, but was somewhat discouraged when I found that these syscalls and the struct don't actually seem to be defined in sched.h (at least not on the current Slackware - not sure whether that's a fault in slackware or not.) and needed to be implemented manually. That kind of makes me want to shy away from the interface entirely and just stick with sched_setscheduler() and setpriority()/nice().

Anyway, whichever way you decide to fix it, thanks for your time. It's appreciated.

karelzak added a commit that referenced this issue Oct 3, 2016
* do not reset 'nice' setting by sched_setattr(), if 'nice' setting
  is not zero then chrt ends with EPERM for non-root users:

  $ renice -n 5 -p $$; chrt -v -b 0 date
  12475 (process ID) old priority 0, new priority 5
  chrt: failed to set pid 0's policy: Operation not permitted

* it seems more elegant to always use old sched_setscheduler() API for
  non-deadline policies; in this case we do not need getpriority()
  to keep 'nice' unchanged.

Addresses: #359
Signed-off-by: Karel Zak <kzak@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants