aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:19 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:19 -0500
commitc69e8d9c01db2adc503464993c358901c9af9de4 (patch)
treebed94aaa9aeb7a7834d1c880f72b62a11a752c78 /kernel
parent86a264abe542cfececb4df129bc45a0338d8cdb9 (diff)
CRED: Use RCU to access another task's creds and to release a task's own creds
Use RCU to access another task's creds and to release a task's own creds. This means that it will be possible for the credentials of a task to be replaced without another task (a) requiring a full lock to read them, and (b) seeing deallocated memory. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: James Morris <jmorris@namei.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c33
-rw-r--r--kernel/cgroup.c16
-rw-r--r--kernel/exit.c14
-rw-r--r--kernel/futex.c22
-rw-r--r--kernel/futex_compat.c7
-rw-r--r--kernel/ptrace.c22
-rw-r--r--kernel/sched.c31
-rw-r--r--kernel/signal.c49
-rw-r--r--kernel/sys.c11
-rw-r--r--kernel/tsacct.c6
10 files changed, 130 insertions, 81 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2febf5165fad..ae8ef88ade3f 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -447,7 +447,7 @@ static int audit_filter_rules(struct task_struct *tsk,
447 struct audit_names *name, 447 struct audit_names *name,
448 enum audit_state *state) 448 enum audit_state *state)
449{ 449{
450 struct cred *cred = tsk->cred; 450 const struct cred *cred = get_task_cred(tsk);
451 int i, j, need_sid = 1; 451 int i, j, need_sid = 1;
452 u32 sid; 452 u32 sid;
453 453
@@ -642,8 +642,10 @@ static int audit_filter_rules(struct task_struct *tsk,
642 break; 642 break;
643 } 643 }
644 644
645 if (!result) 645 if (!result) {
646 put_cred(cred);
646 return 0; 647 return 0;
648 }
647 } 649 }
648 if (rule->filterkey && ctx) 650 if (rule->filterkey && ctx)
649 ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); 651 ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
@@ -651,6 +653,7 @@ static int audit_filter_rules(struct task_struct *tsk,
651 case AUDIT_NEVER: *state = AUDIT_DISABLED; break; 653 case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
652 case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; 654 case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
653 } 655 }
656 put_cred(cred);
654 return 1; 657 return 1;
655} 658}
656 659
@@ -1229,7 +1232,7 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
1229 1232
1230static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) 1233static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
1231{ 1234{
1232 struct cred *cred = tsk->cred; 1235 const struct cred *cred;
1233 int i, call_panic = 0; 1236 int i, call_panic = 0;
1234 struct audit_buffer *ab; 1237 struct audit_buffer *ab;
1235 struct audit_aux_data *aux; 1238 struct audit_aux_data *aux;
@@ -1239,13 +1242,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
1239 context->pid = tsk->pid; 1242 context->pid = tsk->pid;
1240 if (!context->ppid) 1243 if (!context->ppid)
1241 context->ppid = sys_getppid(); 1244 context->ppid = sys_getppid();
1242 context->uid = cred->uid; 1245 cred = current_cred();
1243 context->gid = cred->gid; 1246 context->uid = cred->uid;
1244 context->euid = cred->euid; 1247 context->gid = cred->gid;
1245 context->suid = cred->suid; 1248 context->euid = cred->euid;
1249 context->suid = cred->suid;
1246 context->fsuid = cred->fsuid; 1250 context->fsuid = cred->fsuid;
1247 context->egid = cred->egid; 1251 context->egid = cred->egid;
1248 context->sgid = cred->sgid; 1252 context->sgid = cred->sgid;
1249 context->fsgid = cred->fsgid; 1253 context->fsgid = cred->fsgid;
1250 context->personality = tsk->personality; 1254 context->personality = tsk->personality;
1251 1255
@@ -2088,7 +2092,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
2088 audit_log_format(ab, "login pid=%d uid=%u " 2092 audit_log_format(ab, "login pid=%d uid=%u "
2089 "old auid=%u new auid=%u" 2093 "old auid=%u new auid=%u"
2090 " old ses=%u new ses=%u", 2094 " old ses=%u new ses=%u",
2091 task->pid, task->cred->uid, 2095 task->pid, task_uid(task),
2092 task->loginuid, loginuid, 2096 task->loginuid, loginuid,
2093 task->sessionid, sessionid); 2097 task->sessionid, sessionid);
2094 audit_log_end(ab); 2098 audit_log_end(ab);
@@ -2471,7 +2475,7 @@ void __audit_ptrace(struct task_struct *t)
2471 2475
2472 context->target_pid = t->pid; 2476 context->target_pid = t->pid;
2473 context->target_auid = audit_get_loginuid(t); 2477 context->target_auid = audit_get_loginuid(t);
2474 context->target_uid = t->cred->uid; 2478 context->target_uid = task_uid(t);
2475 context->target_sessionid = audit_get_sessionid(t); 2479 context->target_sessionid = audit_get_sessionid(t);
2476 security_task_getsecid(t, &context->target_sid); 2480 security_task_getsecid(t, &context->target_sid);
2477 memcpy(context->target_comm, t->comm, TASK_COMM_LEN); 2481 memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
@@ -2490,6 +2494,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
2490 struct audit_aux_data_pids *axp; 2494 struct audit_aux_data_pids *axp;
2491 struct task_struct *tsk = current; 2495 struct task_struct *tsk = current;
2492 struct audit_context *ctx = tsk->audit_context; 2496 struct audit_context *ctx = tsk->audit_context;
2497 uid_t uid = current_uid(), t_uid = task_uid(t);
2493 2498
2494 if (audit_pid && t->tgid == audit_pid) { 2499 if (audit_pid && t->tgid == audit_pid) {
2495 if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { 2500 if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
@@ -2497,7 +2502,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
2497 if (tsk->loginuid != -1) 2502 if (tsk->loginuid != -1)
2498 audit_sig_uid = tsk->loginuid; 2503 audit_sig_uid = tsk->loginuid;
2499 else 2504 else
2500 audit_sig_uid = tsk->cred->uid; 2505 audit_sig_uid = uid;
2501 security_task_getsecid(tsk, &audit_sig_sid); 2506 security_task_getsecid(tsk, &audit_sig_sid);
2502 } 2507 }
2503 if (!audit_signals || audit_dummy_context()) 2508 if (!audit_signals || audit_dummy_context())
@@ -2509,7 +2514,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
2509 if (!ctx->target_pid) { 2514 if (!ctx->target_pid) {
2510 ctx->target_pid = t->tgid; 2515 ctx->target_pid = t->tgid;
2511 ctx->target_auid = audit_get_loginuid(t); 2516 ctx->target_auid = audit_get_loginuid(t);
2512 ctx->target_uid = t->cred->uid; 2517 ctx->target_uid = t_uid;
2513 ctx->target_sessionid = audit_get_sessionid(t); 2518 ctx->target_sessionid = audit_get_sessionid(t);
2514 security_task_getsecid(t, &ctx->target_sid); 2519 security_task_getsecid(t, &ctx->target_sid);
2515 memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN); 2520 memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
@@ -2530,7 +2535,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
2530 2535
2531 axp->target_pid[axp->pid_count] = t->tgid; 2536 axp->target_pid[axp->pid_count] = t->tgid;
2532 axp->target_auid[axp->pid_count] = audit_get_loginuid(t); 2537 axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
2533 axp->target_uid[axp->pid_count] = t->cred->uid; 2538 axp->target_uid[axp->pid_count] = t_uid;
2534 axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); 2539 axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
2535 security_task_getsecid(t, &axp->target_sid[axp->pid_count]); 2540 security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
2536 memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN); 2541 memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e210526e6401..a512a75a5560 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1279,7 +1279,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1279static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) 1279static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
1280{ 1280{
1281 struct task_struct *tsk; 1281 struct task_struct *tsk;
1282 uid_t euid; 1282 const struct cred *cred = current_cred(), *tcred;
1283 int ret; 1283 int ret;
1284 1284
1285 if (pid) { 1285 if (pid) {
@@ -1289,16 +1289,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
1289 rcu_read_unlock(); 1289 rcu_read_unlock();
1290 return -ESRCH; 1290 return -ESRCH;
1291 } 1291 }
1292 get_task_struct(tsk);
1293 rcu_read_unlock();
1294 1292
1295 euid = current_euid(); 1293 tcred = __task_cred(tsk);
1296 if (euid && 1294 if (cred->euid &&
1297 euid != tsk->cred->uid && 1295 cred->euid != tcred->uid &&
1298 euid != tsk->cred->suid) { 1296 cred->euid != tcred->suid) {
1299 put_task_struct(tsk); 1297 rcu_read_unlock();
1300 return -EACCES; 1298 return -EACCES;
1301 } 1299 }
1300 get_task_struct(tsk);
1301 rcu_read_unlock();
1302 } else { 1302 } else {
1303 tsk = current; 1303 tsk = current;
1304 get_task_struct(tsk); 1304 get_task_struct(tsk);
diff --git a/kernel/exit.c b/kernel/exit.c
index e0f6e1892fb9..bbc22530f2c1 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -160,7 +160,10 @@ void release_task(struct task_struct * p)
160 int zap_leader; 160 int zap_leader;
161repeat: 161repeat:
162 tracehook_prepare_release_task(p); 162 tracehook_prepare_release_task(p);
163 atomic_dec(&p->cred->user->processes); 163 /* don't need to get the RCU readlock here - the process is dead and
164 * can't be modifying its own credentials */
165 atomic_dec(&__task_cred(p)->user->processes);
166
164 proc_flush_task(p); 167 proc_flush_task(p);
165 write_lock_irq(&tasklist_lock); 168 write_lock_irq(&tasklist_lock);
166 tracehook_finish_release_task(p); 169 tracehook_finish_release_task(p);
@@ -1267,12 +1270,12 @@ static int wait_task_zombie(struct task_struct *p, int options,
1267 unsigned long state; 1270 unsigned long state;
1268 int retval, status, traced; 1271 int retval, status, traced;
1269 pid_t pid = task_pid_vnr(p); 1272 pid_t pid = task_pid_vnr(p);
1273 uid_t uid = __task_cred(p)->uid;
1270 1274
1271 if (!likely(options & WEXITED)) 1275 if (!likely(options & WEXITED))
1272 return 0; 1276 return 0;
1273 1277
1274 if (unlikely(options & WNOWAIT)) { 1278 if (unlikely(options & WNOWAIT)) {
1275 uid_t uid = p->cred->uid;
1276 int exit_code = p->exit_code; 1279 int exit_code = p->exit_code;
1277 int why, status; 1280 int why, status;
1278 1281
@@ -1393,7 +1396,7 @@ static int wait_task_zombie(struct task_struct *p, int options,
1393 if (!retval && infop) 1396 if (!retval && infop)
1394 retval = put_user(pid, &infop->si_pid); 1397 retval = put_user(pid, &infop->si_pid);
1395 if (!retval && infop) 1398 if (!retval && infop)
1396 retval = put_user(p->cred->uid, &infop->si_uid); 1399 retval = put_user(uid, &infop->si_uid);
1397 if (!retval) 1400 if (!retval)
1398 retval = pid; 1401 retval = pid;
1399 1402
@@ -1458,7 +1461,8 @@ static int wait_task_stopped(int ptrace, struct task_struct *p,
1458 if (!unlikely(options & WNOWAIT)) 1461 if (!unlikely(options & WNOWAIT))
1459 p->exit_code = 0; 1462 p->exit_code = 0;
1460 1463
1461 uid = p->cred->uid; 1464 /* don't need the RCU readlock here as we're holding a spinlock */
1465 uid = __task_cred(p)->uid;
1462unlock_sig: 1466unlock_sig:
1463 spin_unlock_irq(&p->sighand->siglock); 1467 spin_unlock_irq(&p->sighand->siglock);
1464 if (!exit_code) 1468 if (!exit_code)
@@ -1532,10 +1536,10 @@ static int wait_task_continued(struct task_struct *p, int options,
1532 } 1536 }
1533 if (!unlikely(options & WNOWAIT)) 1537 if (!unlikely(options & WNOWAIT))
1534 p->signal->flags &= ~SIGNAL_STOP_CONTINUED; 1538 p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
1539 uid = __task_cred(p)->uid;
1535 spin_unlock_irq(&p->sighand->siglock); 1540 spin_unlock_irq(&p->sighand->siglock);
1536 1541
1537 pid = task_pid_vnr(p); 1542 pid = task_pid_vnr(p);
1538 uid = p->cred->uid;
1539 get_task_struct(p); 1543 get_task_struct(p);
1540 read_unlock(&tasklist_lock); 1544 read_unlock(&tasklist_lock);
1541 1545
diff --git a/kernel/futex.c b/kernel/futex.c
index 28421d8210b8..4fe790e89d0f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -439,15 +439,20 @@ static void free_pi_state(struct futex_pi_state *pi_state)
439static struct task_struct * futex_find_get_task(pid_t pid) 439static struct task_struct * futex_find_get_task(pid_t pid)
440{ 440{
441 struct task_struct *p; 441 struct task_struct *p;
442 uid_t euid = current_euid(); 442 const struct cred *cred = current_cred(), *pcred;
443 443
444 rcu_read_lock(); 444 rcu_read_lock();
445 p = find_task_by_vpid(pid); 445 p = find_task_by_vpid(pid);
446 if (!p || (euid != p->cred->euid && 446 if (!p) {
447 euid != p->cred->uid))
448 p = ERR_PTR(-ESRCH); 447 p = ERR_PTR(-ESRCH);
449 else 448 } else {
450 get_task_struct(p); 449 pcred = __task_cred(p);
450 if (cred->euid != pcred->euid &&
451 cred->euid != pcred->uid)
452 p = ERR_PTR(-ESRCH);
453 else
454 get_task_struct(p);
455 }
451 456
452 rcu_read_unlock(); 457 rcu_read_unlock();
453 458
@@ -1831,7 +1836,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
1831{ 1836{
1832 struct robust_list_head __user *head; 1837 struct robust_list_head __user *head;
1833 unsigned long ret; 1838 unsigned long ret;
1834 uid_t euid = current_euid(); 1839 const struct cred *cred = current_cred(), *pcred;
1835 1840
1836 if (!futex_cmpxchg_enabled) 1841 if (!futex_cmpxchg_enabled)
1837 return -ENOSYS; 1842 return -ENOSYS;
@@ -1847,8 +1852,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
1847 if (!p) 1852 if (!p)
1848 goto err_unlock; 1853 goto err_unlock;
1849 ret = -EPERM; 1854 ret = -EPERM;
1850 if (euid != p->cred->euid && 1855 pcred = __task_cred(p);
1851 euid != p->cred->uid && 1856 if (cred->euid != pcred->euid &&
1857 cred->euid != pcred->uid &&
1852 !capable(CAP_SYS_PTRACE)) 1858 !capable(CAP_SYS_PTRACE))
1853 goto err_unlock; 1859 goto err_unlock;
1854 head = p->robust_list; 1860 head = p->robust_list;
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 2c3fd5ed34f5..d607a5b9ee29 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -135,7 +135,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
135{ 135{
136 struct compat_robust_list_head __user *head; 136 struct compat_robust_list_head __user *head;
137 unsigned long ret; 137 unsigned long ret;
138 uid_t euid = current_euid(); 138 const struct cred *cred = current_cred(), *pcred;
139 139
140 if (!futex_cmpxchg_enabled) 140 if (!futex_cmpxchg_enabled)
141 return -ENOSYS; 141 return -ENOSYS;
@@ -151,8 +151,9 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
151 if (!p) 151 if (!p)
152 goto err_unlock; 152 goto err_unlock;
153 ret = -EPERM; 153 ret = -EPERM;
154 if (euid != p->cred->euid && 154 pcred = __task_cred(p);
155 euid != p->cred->uid && 155 if (cred->euid != pcred->euid &&
156 cred->euid != pcred->uid &&
156 !capable(CAP_SYS_PTRACE)) 157 !capable(CAP_SYS_PTRACE))
157 goto err_unlock; 158 goto err_unlock;
158 head = p->compat_robust_list; 159 head = p->compat_robust_list;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 49849d12dd12..b9d5f4e4f6a4 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -115,7 +115,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
115 115
116int __ptrace_may_access(struct task_struct *task, unsigned int mode) 116int __ptrace_may_access(struct task_struct *task, unsigned int mode)
117{ 117{
118 struct cred *cred = current->cred, *tcred = task->cred; 118 const struct cred *cred = current_cred(), *tcred;
119 119
120 /* May we inspect the given task? 120 /* May we inspect the given task?
121 * This check is used both for attaching with ptrace 121 * This check is used both for attaching with ptrace
@@ -125,19 +125,23 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
125 * because setting up the necessary parent/child relationship 125 * because setting up the necessary parent/child relationship
126 * or halting the specified task is impossible. 126 * or halting the specified task is impossible.
127 */ 127 */
128 uid_t uid = cred->uid;
129 gid_t gid = cred->gid;
130 int dumpable = 0; 128 int dumpable = 0;
131 /* Don't let security modules deny introspection */ 129 /* Don't let security modules deny introspection */
132 if (task == current) 130 if (task == current)
133 return 0; 131 return 0;
134 if ((uid != tcred->euid || 132 rcu_read_lock();
135 uid != tcred->suid || 133 tcred = __task_cred(task);
136 uid != tcred->uid || 134 if ((cred->uid != tcred->euid ||
137 gid != tcred->egid || 135 cred->uid != tcred->suid ||
138 gid != tcred->sgid || 136 cred->uid != tcred->uid ||
139 gid != tcred->gid) && !capable(CAP_SYS_PTRACE)) 137 cred->gid != tcred->egid ||
138 cred->gid != tcred->sgid ||
139 cred->gid != tcred->gid) &&
140 !capable(CAP_SYS_PTRACE)) {
141 rcu_read_unlock();
140 return -EPERM; 142 return -EPERM;
143 }
144 rcu_read_unlock();
141 smp_rmb(); 145 smp_rmb();
142 if (task->mm) 146 if (task->mm)
143 dumpable = get_dumpable(task->mm); 147 dumpable = get_dumpable(task->mm);
diff --git a/kernel/sched.c b/kernel/sched.c
index 733c59e645aa..92992e287b10 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -345,7 +345,9 @@ static inline struct task_group *task_group(struct task_struct *p)
345 struct task_group *tg; 345 struct task_group *tg;
346 346
347#ifdef CONFIG_USER_SCHED 347#ifdef CONFIG_USER_SCHED
348 tg = p->cred->user->tg; 348 rcu_read_lock();
349 tg = __task_cred(p)->user->tg;
350 rcu_read_unlock();
349#elif defined(CONFIG_CGROUP_SCHED) 351#elif defined(CONFIG_CGROUP_SCHED)
350 tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id), 352 tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
351 struct task_group, css); 353 struct task_group, css);
@@ -5121,6 +5123,22 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
5121 set_load_weight(p); 5123 set_load_weight(p);
5122} 5124}
5123 5125
5126/*
5127 * check the target process has a UID that matches the current process's
5128 */
5129static bool check_same_owner(struct task_struct *p)
5130{
5131 const struct cred *cred = current_cred(), *pcred;
5132 bool match;
5133
5134 rcu_read_lock();
5135 pcred = __task_cred(p);
5136 match = (cred->euid == pcred->euid ||
5137 cred->euid == pcred->uid);
5138 rcu_read_unlock();
5139 return match;
5140}
5141
5124static int __sched_setscheduler(struct task_struct *p, int policy, 5142static int __sched_setscheduler(struct task_struct *p, int policy,
5125 struct sched_param *param, bool user) 5143 struct sched_param *param, bool user)
5126{ 5144{
@@ -5128,7 +5146,6 @@ static int __sched_setscheduler(struct task_struct *p, int policy,
5128 unsigned long flags; 5146 unsigned long flags;
5129 const struct sched_class *prev_class = p->sched_class; 5147 const struct sched_class *prev_class = p->sched_class;
5130 struct rq *rq; 5148 struct rq *rq;
5131 uid_t euid;
5132 5149
5133 /* may grab non-irq protected spin_locks */ 5150 /* may grab non-irq protected spin_locks */
5134 BUG_ON(in_interrupt()); 5151 BUG_ON(in_interrupt());
@@ -5181,9 +5198,7 @@ recheck:
5181 return -EPERM; 5198 return -EPERM;
5182 5199
5183 /* can't change other user's priorities */ 5200 /* can't change other user's priorities */
5184 euid = current_euid(); 5201 if (!check_same_owner(p))
5185 if (euid != p->cred->euid &&
5186 euid != p->cred->uid)
5187 return -EPERM; 5202 return -EPERM;
5188 } 5203 }
5189 5204
@@ -5394,7 +5409,6 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
5394 cpumask_t cpus_allowed; 5409 cpumask_t cpus_allowed;
5395 cpumask_t new_mask = *in_mask; 5410 cpumask_t new_mask = *in_mask;
5396 struct task_struct *p; 5411 struct task_struct *p;
5397 uid_t euid;
5398 int retval; 5412 int retval;
5399 5413
5400 get_online_cpus(); 5414 get_online_cpus();
@@ -5415,11 +5429,8 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
5415 get_task_struct(p); 5429 get_task_struct(p);
5416 read_unlock(&tasklist_lock); 5430 read_unlock(&tasklist_lock);
5417 5431
5418 euid = current_euid();
5419 retval = -EPERM; 5432 retval = -EPERM;
5420 if (euid != p->cred->euid && 5433 if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
5421 euid != p->cred->uid &&
5422 !capable(CAP_SYS_NICE))
5423 goto out_unlock; 5434 goto out_unlock;
5424 5435
5425 retval = security_task_setscheduler(p, 0, NULL); 5436 retval = security_task_setscheduler(p, 0, NULL);
diff --git a/kernel/signal.c b/kernel/signal.c
index 80e8a6489f97..84989124bafb 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -177,6 +177,11 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
177 return sig; 177 return sig;
178} 178}
179 179
180/*
181 * allocate a new signal queue record
182 * - this may be called without locks if and only if t == current, otherwise an
183 * appopriate lock must be held to protect t's user_struct
184 */
180static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, 185static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
181 int override_rlimit) 186 int override_rlimit)
182{ 187{
@@ -184,11 +189,12 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
184 struct user_struct *user; 189 struct user_struct *user;
185 190
186 /* 191 /*
187 * In order to avoid problems with "switch_user()", we want to make 192 * We won't get problems with the target's UID changing under us
188 * sure that the compiler doesn't re-load "t->user" 193 * because changing it requires RCU be used, and if t != current, the
194 * caller must be holding the RCU readlock (by way of a spinlock) and
195 * we use RCU protection here
189 */ 196 */
190 user = t->cred->user; 197 user = __task_cred(t)->user;
191 barrier();
192 atomic_inc(&user->sigpending); 198 atomic_inc(&user->sigpending);
193 if (override_rlimit || 199 if (override_rlimit ||
194 atomic_read(&user->sigpending) <= 200 atomic_read(&user->sigpending) <=
@@ -562,12 +568,13 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
562 568
563/* 569/*
564 * Bad permissions for sending the signal 570 * Bad permissions for sending the signal
571 * - the caller must hold at least the RCU read lock
565 */ 572 */
566static int check_kill_permission(int sig, struct siginfo *info, 573static int check_kill_permission(int sig, struct siginfo *info,
567 struct task_struct *t) 574 struct task_struct *t)
568{ 575{
576 const struct cred *cred = current_cred(), *tcred;
569 struct pid *sid; 577 struct pid *sid;
570 uid_t uid, euid;
571 int error; 578 int error;
572 579
573 if (!valid_signal(sig)) 580 if (!valid_signal(sig))
@@ -580,10 +587,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
580 if (error) 587 if (error)
581 return error; 588 return error;
582 589
583 uid = current_uid(); 590 tcred = __task_cred(t);
584 euid = current_euid(); 591 if ((cred->euid ^ tcred->suid) &&
585 if ((euid ^ t->cred->suid) && (euid ^ t->cred->uid) && 592 (cred->euid ^ tcred->uid) &&
586 (uid ^ t->cred->suid) && (uid ^ t->cred->uid) && 593 (cred->uid ^ tcred->suid) &&
594 (cred->uid ^ tcred->uid) &&
587 !capable(CAP_KILL)) { 595 !capable(CAP_KILL)) {
588 switch (sig) { 596 switch (sig) {
589 case SIGCONT: 597 case SIGCONT:
@@ -1011,6 +1019,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
1011 return sighand; 1019 return sighand;
1012} 1020}
1013 1021
1022/*
1023 * send signal info to all the members of a group
1024 * - the caller must hold the RCU read lock at least
1025 */
1014int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) 1026int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
1015{ 1027{
1016 unsigned long flags; 1028 unsigned long flags;
@@ -1032,8 +1044,8 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
1032/* 1044/*
1033 * __kill_pgrp_info() sends a signal to a process group: this is what the tty 1045 * __kill_pgrp_info() sends a signal to a process group: this is what the tty
1034 * control characters do (^C, ^Z etc) 1046 * control characters do (^C, ^Z etc)
1047 * - the caller must hold at least a readlock on tasklist_lock
1035 */ 1048 */
1036
1037int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp) 1049int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
1038{ 1050{
1039 struct task_struct *p = NULL; 1051 struct task_struct *p = NULL;
@@ -1089,6 +1101,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1089{ 1101{
1090 int ret = -EINVAL; 1102 int ret = -EINVAL;
1091 struct task_struct *p; 1103 struct task_struct *p;
1104 const struct cred *pcred;
1092 1105
1093 if (!valid_signal(sig)) 1106 if (!valid_signal(sig))
1094 return ret; 1107 return ret;
@@ -1099,9 +1112,11 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1099 ret = -ESRCH; 1112 ret = -ESRCH;
1100 goto out_unlock; 1113 goto out_unlock;
1101 } 1114 }
1102 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) 1115 pcred = __task_cred(p);
1103 && (euid != p->cred->suid) && (euid != p->cred->uid) 1116 if ((info == SEND_SIG_NOINFO ||
1104 && (uid != p->cred->suid) && (uid != p->cred->uid)) { 1117 (!is_si_special(info) && SI_FROMUSER(info))) &&
1118 euid != pcred->suid && euid != pcred->uid &&
1119 uid != pcred->suid && uid != pcred->uid) {
1105 ret = -EPERM; 1120 ret = -EPERM;
1106 goto out_unlock; 1121 goto out_unlock;
1107 } 1122 }
@@ -1372,10 +1387,9 @@ int do_notify_parent(struct task_struct *tsk, int sig)
1372 */ 1387 */
1373 rcu_read_lock(); 1388 rcu_read_lock();
1374 info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); 1389 info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
1390 info.si_uid = __task_cred(tsk)->uid;
1375 rcu_read_unlock(); 1391 rcu_read_unlock();
1376 1392
1377 info.si_uid = tsk->cred->uid;
1378
1379 thread_group_cputime(tsk, &cputime); 1393 thread_group_cputime(tsk, &cputime);
1380 info.si_utime = cputime_to_jiffies(cputime.utime); 1394 info.si_utime = cputime_to_jiffies(cputime.utime);
1381 info.si_stime = cputime_to_jiffies(cputime.stime); 1395 info.si_stime = cputime_to_jiffies(cputime.stime);
@@ -1443,10 +1457,9 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
1443 */ 1457 */
1444 rcu_read_lock(); 1458 rcu_read_lock();
1445 info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); 1459 info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
1460 info.si_uid = __task_cred(tsk)->uid;
1446 rcu_read_unlock(); 1461 rcu_read_unlock();
1447 1462
1448 info.si_uid = tsk->cred->uid;
1449
1450 info.si_utime = cputime_to_clock_t(tsk->utime); 1463 info.si_utime = cputime_to_clock_t(tsk->utime);
1451 info.si_stime = cputime_to_clock_t(tsk->stime); 1464 info.si_stime = cputime_to_clock_t(tsk->stime);
1452 1465
@@ -1713,7 +1726,7 @@ static int ptrace_signal(int signr, siginfo_t *info,
1713 info->si_errno = 0; 1726 info->si_errno = 0;
1714 info->si_code = SI_USER; 1727 info->si_code = SI_USER;
1715 info->si_pid = task_pid_vnr(current->parent); 1728 info->si_pid = task_pid_vnr(current->parent);
1716 info->si_uid = current->parent->cred->uid; 1729 info->si_uid = task_uid(current->parent);
1717 } 1730 }
1718 1731
1719 /* If the (new) signal is now blocked, requeue it. */ 1732 /* If the (new) signal is now blocked, requeue it. */
diff --git a/kernel/sys.c b/kernel/sys.c
index c4d6b59553e9..ccc9eb736d35 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -112,14 +112,17 @@ EXPORT_SYMBOL(cad_pid);
112 112
113void (*pm_power_off_prepare)(void); 113void (*pm_power_off_prepare)(void);
114 114
115/*
116 * set the priority of a task
117 * - the caller must hold the RCU read lock
118 */
115static int set_one_prio(struct task_struct *p, int niceval, int error) 119static int set_one_prio(struct task_struct *p, int niceval, int error)
116{ 120{
117 uid_t euid = current_euid(); 121 const struct cred *cred = current_cred(), *pcred = __task_cred(p);
118 int no_nice; 122 int no_nice;
119 123
120 if (p->cred->uid != euid && 124 if (pcred->uid != cred->euid &&
121 p->cred->euid != euid && 125 pcred->euid != cred->euid && !capable(CAP_SYS_NICE)) {
122 !capable(CAP_SYS_NICE)) {
123 error = -EPERM; 126 error = -EPERM;
124 goto out; 127 goto out;
125 } 128 }
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 6d1ed07bf312..2dc06ab35716 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -27,6 +27,7 @@
27 */ 27 */
28void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) 28void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
29{ 29{
30 const struct cred *tcred;
30 struct timespec uptime, ts; 31 struct timespec uptime, ts;
31 u64 ac_etime; 32 u64 ac_etime;
32 33
@@ -53,10 +54,11 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
53 stats->ac_flag |= AXSIG; 54 stats->ac_flag |= AXSIG;
54 stats->ac_nice = task_nice(tsk); 55 stats->ac_nice = task_nice(tsk);
55 stats->ac_sched = tsk->policy; 56 stats->ac_sched = tsk->policy;
56 stats->ac_uid = tsk->cred->uid;
57 stats->ac_gid = tsk->cred->gid;
58 stats->ac_pid = tsk->pid; 57 stats->ac_pid = tsk->pid;
59 rcu_read_lock(); 58 rcu_read_lock();
59 tcred = __task_cred(tsk);
60 stats->ac_uid = tcred->uid;
61 stats->ac_gid = tcred->gid;
60 stats->ac_ppid = pid_alive(tsk) ? 62 stats->ac_ppid = pid_alive(tsk) ?
61 rcu_dereference(tsk->real_parent)->tgid : 0; 63 rcu_dereference(tsk->real_parent)->tgid : 0;
62 rcu_read_unlock(); 64 rcu_read_unlock();