From 1d8659dce1cb63d059a9875625d7b483d0fb7dcc Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 1 May 2005 08:59:00 -0700 Subject: [PATCH] --- yaml --- r: 707 b: refs/heads/master c: e43379f10b42194b8a6e1de342cfb44463c0f6da h: refs/heads/master i: 705: ff78abb8ba679821557f335a4aeef549e14eb93f 703: ba53a08f499bd8ef777207c4f2fa1b5b563ff648 v: v3 --- [refs] | 2 +- trunk/include/asm-generic/resource.h | 7 ++++++- trunk/include/linux/sched.h | 1 + trunk/kernel/sched.c | 25 +++++++++++++++++++------ trunk/kernel/sys.c | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/[refs] b/[refs] index 322dd5d231ec..53b6328ffc6d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9fc1427a01a9df3605e219c6de0c59c4639209a1 +refs/heads/master: e43379f10b42194b8a6e1de342cfb44463c0f6da diff --git a/trunk/include/asm-generic/resource.h b/trunk/include/asm-generic/resource.h index b1fcda9eac23..cfe3692b23e5 100644 --- a/trunk/include/asm-generic/resource.h +++ b/trunk/include/asm-generic/resource.h @@ -41,8 +41,11 @@ #define RLIMIT_LOCKS 10 /* maximum file locks held */ #define RLIMIT_SIGPENDING 11 /* max number of pending signals */ #define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */ +#define RLIMIT_NICE 13 /* max nice prio allowed to raise to + 0-39 for nice level 19 .. -20 */ +#define RLIMIT_RTPRIO 14 /* maximum realtime priority */ -#define RLIM_NLIMITS 13 +#define RLIM_NLIMITS 15 /* * SuS says limits have to be unsigned. @@ -81,6 +84,8 @@ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \ [RLIMIT_SIGPENDING] = { 0, 0 }, \ [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \ + [RLIMIT_NICE] = { 0, 0 }, \ + [RLIMIT_RTPRIO] = { 0, 0 }, \ } #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 1cced971232c..8960f99ea128 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -845,6 +845,7 @@ extern void sched_idle_next(void); extern void set_user_nice(task_t *p, long nice); extern int task_prio(const task_t *p); extern int task_nice(const task_t *p); +extern int can_nice(const task_t *p, const int nice); extern int task_curr(const task_t *p); extern int idle_cpu(int cpu); extern int sched_setscheduler(struct task_struct *, int, struct sched_param *); diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 9bb7489ee645..5dadcc6df7dd 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -3223,6 +3223,19 @@ void set_user_nice(task_t *p, long nice) EXPORT_SYMBOL(set_user_nice); +/* + * can_nice - check if a task can reduce its nice value + * @p: task + * @nice: nice value + */ +int can_nice(const task_t *p, const int nice) +{ + /* convert nice value [19,-20] to rlimit style value [0,39] */ + int nice_rlim = 19 - nice; + return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur || + capable(CAP_SYS_NICE)); +} + #ifdef __ARCH_WANT_SYS_NICE /* @@ -3242,12 +3255,8 @@ asmlinkage long sys_nice(int increment) * We don't have to worry. Conceptually one call occurs first * and we have a single winner. */ - if (increment < 0) { - if (!capable(CAP_SYS_NICE)) - return -EPERM; - if (increment < -40) - increment = -40; - } + if (increment < -40) + increment = -40; if (increment > 40) increment = 40; @@ -3257,6 +3266,9 @@ asmlinkage long sys_nice(int increment) if (nice > 19) nice = 19; + if (increment < 0 && !can_nice(current, nice)) + return -EPERM; + retval = security_task_setnice(current, nice); if (retval) return retval; @@ -3372,6 +3384,7 @@ int sched_setscheduler(struct task_struct *p, int policy, struct sched_param *pa return -EINVAL; if ((policy == SCHED_FIFO || policy == SCHED_RR) && + param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur && !capable(CAP_SYS_NICE)) return -EPERM; if ((current->euid != p->euid) && (current->euid != p->uid) && diff --git a/trunk/kernel/sys.c b/trunk/kernel/sys.c index df2ddcc6863b..7f43d6e62c7a 100644 --- a/trunk/kernel/sys.c +++ b/trunk/kernel/sys.c @@ -227,7 +227,7 @@ static int set_one_prio(struct task_struct *p, int niceval, int error) error = -EPERM; goto out; } - if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) { + if (niceval < task_nice(p) && !can_nice(p, niceval)) { error = -EACCES; goto out; }