diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 789d7bf4fef3..13a2ad1ac021 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -103,7 +103,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
 	if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
-	retval = security_task_setscheduler(p);
+	retval = security_task_setscheduler(p, current_cred());
 	if (retval)
 		goto out_unlock;
 
@@ -169,7 +169,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
 	p = find_process_by_pid(pid);
 	if (!p)
 		goto out_unlock;
-	retval = security_task_getscheduler(p);
+	retval = security_task_getscheduler(p, current_cred());
 	if (retval)
 		goto out_unlock;
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index cbba490543e2..3f87cef3b5c1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2345,6 +2345,8 @@ static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
 					size_t count, loff_t *offset)
 {
 	struct inode *inode = file_inode(file);
+	struct luid *opener_privunit =
+		((struct seq_file *)file->private_data)->private;
 	struct task_struct *p;
 	u64 slack_ns;
 	int err;
@@ -2357,13 +2359,13 @@ static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
 	if (!p)
 		return -ESRCH;
 
-	if (p != current) {
-		if (!capable(CAP_SYS_NICE)) {
+	if (!luid_eq(&p->privunit, opener_privunit)) {
+		if (!file_ns_capable(file, &init_user_ns, CAP_SYS_NICE)) {
 			count = -EPERM;
 			goto out;
 		}
 
-		err = security_task_setscheduler(p);
+		err = security_task_setscheduler(p, file->f_cred);
 		if (err) {
 			count = err;
 			goto out;
@@ -2385,7 +2387,9 @@ static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
 
 static int timerslack_ns_show(struct seq_file *m, void *v)
 {
-	struct inode *inode = m->private;
+	struct inode *inode = file_inode(m->file);
+	struct luid *opener_privunit = m->private;
+
 	struct task_struct *p;
 	int err = 0;
 
@@ -2393,13 +2397,12 @@ static int timerslack_ns_show(struct seq_file *m, void *v)
 	if (!p)
 		return -ESRCH;
 
-	if (p != current) {
-
-		if (!capable(CAP_SYS_NICE)) {
+	if (!luid_eq(&p->privunit, opener_privunit)) {
+		if (!file_ns_capable(m->file, &init_user_ns, CAP_SYS_NICE)) {
 			err = -EPERM;
 			goto out;
 		}
-		err = security_task_getscheduler(p);
+		err = security_task_getscheduler(p, m->file->f_cred);
 		if (err)
 			goto out;
 	}
@@ -2416,7 +2419,21 @@ static int timerslack_ns_show(struct seq_file *m, void *v)
 
 static int timerslack_ns_open(struct inode *inode, struct file *filp)
 {
-	return single_open(filp, timerslack_ns_show, inode);
+	struct luid *privunit = kmalloc(sizeof(*privunit), GFP_KERNEL);
+
+	if (!privunit)
+		return -ENOMEM;
+	*privunit = current->privunit;
+	return single_open(filp, timerslack_ns_show, privunit);
+}
+
+static int timerslack_ns_release(struct inode *inode, struct file *file)
+{
+	struct luid *opener_privunit =
+		((struct seq_file *)file->private_data)->private;
+
+	kfree(opener_privunit);
+	return single_release(inode, file);
 }
 
 static const struct file_operations proc_pid_set_timerslack_ns_operations = {
@@ -2424,7 +2441,7 @@ static const struct file_operations proc_pid_set_timerslack_ns_operations = {
 	.read		= seq_read,
 	.write		= timerslack_ns_write,
 	.llseek		= seq_lseek,
-	.release	= single_release,
+	.release	= timerslack_ns_release,
 };
 
 static int proc_pident_instantiate(struct inode *dir,
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 26f260c24f31..c84c92a52386 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -640,15 +640,15 @@
  *	Return 0 if permission is granted.
  * @task_setscheduler:
  *	Check permission before setting scheduling policy and/or parameters of
- *	process @p based on @policy and @lp.
+ *	process @p on behalf of subject @cred.
  *	@p contains the task_struct for process.
- *	@policy contains the scheduling policy.
- *	@lp contains the scheduling parameters.
+ *	@cred contains the credentials of the caller.
  *	Return 0 if permission is granted.
  * @task_getscheduler:
  *	Check permission before obtaining scheduling information for process
- *	@p.
+ *	@p on behalf of subject @cred.
  *	@p contains the task_struct for process.
+ *	@cred contains the credentials of the caller.
  *	Return 0 if permission is granted.
  * @task_movememory
  *	Check permission before moving memory owned by process @p.
@@ -1503,8 +1503,10 @@ union security_list_options {
 	int (*task_getioprio)(struct task_struct *p);
 	int (*task_setrlimit)(struct task_struct *p, unsigned int resource,
 				struct rlimit *new_rlim);
-	int (*task_setscheduler)(struct task_struct *p);
-	int (*task_getscheduler)(struct task_struct *p);
+	int (*task_setscheduler)(struct task_struct *p,
+				 const struct cred *cred);
+	int (*task_getscheduler)(struct task_struct *p,
+				 const struct cred *cred);
 	int (*task_movememory)(struct task_struct *p);
 	int (*task_kill)(struct task_struct *p, struct siginfo *info,
 				int sig, u32 secid);
diff --git a/include/linux/security.h b/include/linux/security.h
index 8b6ce7c8984d..1e54ef927537 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -93,7 +93,8 @@ extern int cap_mmap_file(struct file *file, unsigned long reqprot,
 extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
 extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 			  unsigned long arg4, unsigned long arg5);
-extern int cap_task_setscheduler(struct task_struct *p);
+extern int cap_task_setscheduler(struct task_struct *p,
+				 const struct cred *cred);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setnice(struct task_struct *p, int nice);
 extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
@@ -329,8 +330,8 @@ int security_task_setioprio(struct task_struct *p, int ioprio);
 int security_task_getioprio(struct task_struct *p);
 int security_task_setrlimit(struct task_struct *p, unsigned int resource,
 		struct rlimit *new_rlim);
-int security_task_setscheduler(struct task_struct *p);
-int security_task_getscheduler(struct task_struct *p);
+int security_task_setscheduler(struct task_struct *p, const struct cred *cred);
+int security_task_getscheduler(struct task_struct *p, const struct cred *cred);
 int security_task_movememory(struct task_struct *p);
 int security_task_kill(struct task_struct *p, struct siginfo *info,
 			int sig, u32 secid);
@@ -960,12 +961,14 @@ static inline int security_task_setrlimit(struct task_struct *p,
 	return 0;
 }
 
-static inline int security_task_setscheduler(struct task_struct *p)
+static inline int security_task_setscheduler(struct task_struct *p,
+					     const struct cred *cred)
 {
 	return cap_task_setscheduler(p);
 }
 
-static inline int security_task_getscheduler(struct task_struct *p)
+static inline int security_task_getscheduler(struct task_struct *p,
+					     const struct cred *cred)
 {
 	return 0;
 }
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 29f815d2ef7e..e3a797b4dde3 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1480,7 +1480,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
 		ret = task_can_attach(task, cs->cpus_allowed);
 		if (ret)
 			goto out_unlock;
-		ret = security_task_setscheduler(task);
+		ret = security_task_setscheduler(task, current_cred());
 		if (ret)
 			goto out_unlock;
 	}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 42d4027f9e26..37f1dc2ea7d6 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4165,7 +4165,7 @@ static int __sched_setscheduler(struct task_struct *p,
 	}
 
 	if (user) {
-		retval = security_task_setscheduler(p);
+		retval = security_task_setscheduler(p, current_cred());
 		if (retval)
 			return retval;
 	}
@@ -4544,7 +4544,7 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
 	rcu_read_lock();
 	p = find_process_by_pid(pid);
 	if (p) {
-		retval = security_task_getscheduler(p);
+		retval = security_task_getscheduler(p, current_cred());
 		if (!retval)
 			retval = p->policy
 				| (p->sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0);
@@ -4576,7 +4576,7 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
 	if (!p)
 		goto out_unlock;
 
-	retval = security_task_getscheduler(p);
+	retval = security_task_getscheduler(p, current_cred());
 	if (retval)
 		goto out_unlock;
 
@@ -4658,7 +4658,7 @@ SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
 	if (!p)
 		goto out_unlock;
 
-	retval = security_task_getscheduler(p);
+	retval = security_task_getscheduler(p, current_cred());
 	if (retval)
 		goto out_unlock;
 
@@ -4722,7 +4722,7 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 		rcu_read_unlock();
 	}
 
-	retval = security_task_setscheduler(p);
+	retval = security_task_setscheduler(p, current_cred());
 	if (retval)
 		goto out_free_new_mask;
 
@@ -4819,7 +4819,7 @@ long sched_getaffinity(pid_t pid, struct cpumask *mask)
 	if (!p)
 		goto out_unlock;
 
-	retval = security_task_getscheduler(p);
+	retval = security_task_getscheduler(p, current_cred());
 	if (retval)
 		goto out_unlock;
 
@@ -5164,7 +5164,7 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
 	if (!p)
 		goto out_unlock;
 
-	retval = security_task_getscheduler(p);
+	retval = security_task_getscheduler(p, current_cred());
 	if (retval)
 		goto out_unlock;
 
diff --git a/security/commoncap.c b/security/commoncap.c
index ffbb3ea18720..a2508cd3aab9 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -813,14 +813,15 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
  * yet with increased caps.
  * So we check for increased caps on the target process.
  */
-static int cap_safe_nice(struct task_struct *p)
+static int cap_safe_nice(struct task_struct *p, const struct cred *cred)
 {
 	int is_subset, ret = 0;
 
 	rcu_read_lock();
 	is_subset = cap_issubset(__task_cred(p)->cap_permitted,
-				 current_cred()->cap_permitted);
-	if (!is_subset && !ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
+				 cred->cap_permitted);
+	if (!is_subset &&
+	    security_capable(cred, __task_cred(p)->user_ns, CAP_SYS_NICE) != 0)
 		ret = -EPERM;
 	rcu_read_unlock();
 
@@ -830,13 +831,14 @@ static int cap_safe_nice(struct task_struct *p)
 /**
  * cap_task_setscheduler - Detemine if scheduler policy change is permitted
  * @p: The task to affect
+ * @cred: The caller's credentials
  *
  * Detemine if the requested scheduler policy change is permitted for the
  * specified task, returning 0 if permission is granted, -ve if denied.
  */
-int cap_task_setscheduler(struct task_struct *p)
+int cap_task_setscheduler(struct task_struct *p, const struct cred *cred)
 {
-	return cap_safe_nice(p);
+	return cap_safe_nice(p, cred);
 }
 
 /**
@@ -849,7 +851,7 @@ int cap_task_setscheduler(struct task_struct *p)
  */
 int cap_task_setioprio(struct task_struct *p, int ioprio)
 {
-	return cap_safe_nice(p);
+	return cap_safe_nice(p, current_cred());
 }
 
 /**
@@ -862,7 +864,7 @@ int cap_task_setioprio(struct task_struct *p, int ioprio)
  */
 int cap_task_setnice(struct task_struct *p, int nice)
 {
-	return cap_safe_nice(p);
+	return cap_safe_nice(p, current_cred());
 }
 
 /*
diff --git a/security/security.c b/security/security.c
index cb375573f021..846012b5502b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1005,14 +1005,14 @@ int security_task_setrlimit(struct task_struct *p, unsigned int resource,
 	return call_int_hook(task_setrlimit, 0, p, resource, new_rlim);
 }
 
-int security_task_setscheduler(struct task_struct *p)
+int security_task_setscheduler(struct task_struct *p, const struct cred *cred)
 {
-	return call_int_hook(task_setscheduler, 0, p);
+	return call_int_hook(task_setscheduler, 0, p, cred);
 }
 
-int security_task_getscheduler(struct task_struct *p)
+int security_task_getscheduler(struct task_struct *p, const struct cred *cred)
 {
-	return call_int_hook(task_getscheduler, 0, p);
+	return call_int_hook(task_getscheduler, 0, p, cred);
 }
 
 int security_task_movememory(struct task_struct *p)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8c383176a846..9a19da9f1ea2 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3910,14 +3910,26 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
 	return 0;
 }
 
-static int selinux_task_setscheduler(struct task_struct *p)
+static int selinux_task_setscheduler(struct task_struct *p,
+				     const struct cred *cred)
 {
-	return current_has_perm(p, PROCESS__SETSCHED);
+	u32 sid, tsid;
+
+	sid = cred_sid(cred);
+	tsid = task_sid(p);
+	return avc_has_perm(sid, tsid, SECCLASS_PROCESS, PROCESS__SETSCHED,
+			    NULL);
 }
 
-static int selinux_task_getscheduler(struct task_struct *p)
+static int selinux_task_getscheduler(struct task_struct *p,
+				     const struct cred *cred)
 {
-	return current_has_perm(p, PROCESS__GETSCHED);
+	u32 sid, tsid;
+
+	sid = cred_sid(cred);
+	tsid = task_sid(p);
+	return avc_has_perm(sid, tsid, SECCLASS_PROCESS, PROCESS__GETSCHED,
+			    NULL);
 }
 
 static int selinux_task_movememory(struct task_struct *p)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 6aef4b558e73..0737325baa14 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2209,13 +2209,16 @@ static int smack_task_getioprio(struct task_struct *p)
 /**
  * smack_task_setscheduler - Smack check on setting scheduler
  * @p: the task object
+ * @cred: the caller's credentials
  * @policy: unused
  * @lp: unused
  *
  * Return 0 if read access is permitted
  */
-static int smack_task_setscheduler(struct task_struct *p)
+static int smack_task_setscheduler(struct task_struct *p,
+				   const struct cred *cred)
 {
+	// TODO: handle non-current accesses (via timerslack)
 	return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
@@ -2225,8 +2228,10 @@ static int smack_task_setscheduler(struct task_struct *p)
  *
  * Return 0 if read access is permitted
  */
-static int smack_task_getscheduler(struct task_struct *p)
+static int smack_task_getscheduler(struct task_struct *p,
+				   const struct cred *cred)
 {
+	// TODO: handle non-current accesses (via timerslack)
 	return smk_curacc_on_task(p, MAY_READ, __func__);
 }
 
