views:

128

answers:

1

On the 2.6.28-11 Linux kernel, I am using setpriority to bias the amount of cpu time different user processes receive. User 1 is to receive double the CPU power of user 2. Using Linux's setpriority, I have assigned user 2 a lower priority (higher in terms of nice values). When I run the exact same program via the shell with the computer under load, user 2's execution takes twice as long as user 1's. However, if I run the program as root, and then use setuid, seteuid, setgid, setegid, and setgroups to become user 2 (once again the computer is under load with the exact same program being run by user 1 in the same manner), the programs take the exact same amount of time to execute; User 2's process was not being scheduled any less than user 1's. How can I get around this? Do I need to set anything else for the scheduler to realize that the process is now part of a different user?

The program being run is in Python.

+1  A: 

Right, this is the designed behavior, even if it's not what you want. You can update your own priority to match what you should have inherited, if you were started normally:

/* C */
#include <sys/resource.h>
int proc_prio = getpriority(PRIO_PROCESS, getpid()),
    pgrp_prio = getpriority(PRIO_PGRP, getpgrp()),
    user_prio = getpriority(PRIO_USER, getuid());
setpriority(PRIO_PROCESS, getpid(),
    proc_prio < pgrp_prio ? pgrp_prio < user_prio ? user_prio
                                                  : pgrp_prio
                          : proc_prio < user_prio ? user_prio
                                                  : proc_prio);

# Python
import ctypes
import os
PRIO_PROCESS, PRIO_PGRP, PRIO_USER = 0, 1, 2
libc = ctypes.CDLL('libc.so.6')
libc.setpriority(PRIO_PROCESS, os.getpid(),
    max(libc.getpriority(PRIO_PROCESS, os.getpid()),
        libc.getpriority(PRIO_PGRP, os.getpgrp()),
        libc.getpriority(PRIO_USER, os.getuid())))

Or of course you could fix another process's priority, with appropriate privileges.

ephemient
Thanks for the clarification. Do you have any good reading material that covers how Linux handles and prioritizes priorities? Given your solution above, which does work, it seems that it is not possible to ensure that all of user 1's processes only use up x% of the cpu if they have any processes that come from a fork-ed root process that was setuid-ed. Is this true?
BrainCore
don't have any good reading material, but the only thing checked by `setuid` is "am I root* and does the target UID have less than `RLIMIT_NPROC` processes?". Other resource limits and priority are not checked or touched. *(actually the check is "unless forbidden by LSM, do I have `CAP_SETUID` and if I'm actually changing real UID does the target have less than `RLIMIT_NPROC` processes, or is the specified UID equal to current real UID or saved UID?")
ephemient
To an extent, you can watch the netlink connector for `PROC_EVENT_UID` events to apply these fixes, but it I think what you really want are UID-based cpusets and cgroup-based scheduling.
ephemient
I had already implemented my desired system using the process events connector via netlink as you suggested. When I discovered that there was reliable user group scheduling in the CFS (Completely Fair Scheduler), I figured it was worth further examination. I'll be sure to check out cgroup-based scheduling. Thanks again.
BrainCore