aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c42
-rw-r--r--kernel/capability.c78
-rw-r--r--kernel/cred-internals.h21
-rw-r--r--kernel/cred.c321
-rw-r--r--kernel/exit.c9
-rw-r--r--kernel/fork.c7
-rw-r--r--kernel/kmod.c30
-rw-r--r--kernel/ptrace.c9
-rw-r--r--kernel/signal.c10
-rw-r--r--kernel/sys.c450
-rw-r--r--kernel/user.c37
-rw-r--r--kernel/user_namespace.c12
12 files changed, 652 insertions, 374 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index ae8ef88ade3f..bc1e2d854bf6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2546,18 +2546,17 @@ int __audit_signal_info(int sig, struct task_struct *t)
2546 2546
2547/** 2547/**
2548 * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps 2548 * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
2549 * @bprm pointer to the bprm being processed 2549 * @bprm: pointer to the bprm being processed
2550 * @caps the caps read from the disk 2550 * @new: the proposed new credentials
2551 * @old: the old credentials
2551 * 2552 *
2552 * Simply check if the proc already has the caps given by the file and if not 2553 * Simply check if the proc already has the caps given by the file and if not
2553 * store the priv escalation info for later auditing at the end of the syscall 2554 * store the priv escalation info for later auditing at the end of the syscall
2554 * 2555 *
2555 * this can fail and we don't care. See the note in audit.h for
2556 * audit_log_bprm_fcaps() for my explaination....
2557 *
2558 * -Eric 2556 * -Eric
2559 */ 2557 */
2560void __audit_log_bprm_fcaps(struct linux_binprm *bprm, kernel_cap_t *pP, kernel_cap_t *pE) 2558int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
2559 const struct cred *new, const struct cred *old)
2561{ 2560{
2562 struct audit_aux_data_bprm_fcaps *ax; 2561 struct audit_aux_data_bprm_fcaps *ax;
2563 struct audit_context *context = current->audit_context; 2562 struct audit_context *context = current->audit_context;
@@ -2566,7 +2565,7 @@ void __audit_log_bprm_fcaps(struct linux_binprm *bprm, kernel_cap_t *pP, kernel_
2566 2565
2567 ax = kmalloc(sizeof(*ax), GFP_KERNEL); 2566 ax = kmalloc(sizeof(*ax), GFP_KERNEL);
2568 if (!ax) 2567 if (!ax)
2569 return; 2568 return -ENOMEM;
2570 2569
2571 ax->d.type = AUDIT_BPRM_FCAPS; 2570 ax->d.type = AUDIT_BPRM_FCAPS;
2572 ax->d.next = context->aux; 2571 ax->d.next = context->aux;
@@ -2581,26 +2580,27 @@ void __audit_log_bprm_fcaps(struct linux_binprm *bprm, kernel_cap_t *pP, kernel_
2581 ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); 2580 ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
2582 ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; 2581 ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
2583 2582
2584 ax->old_pcap.permitted = *pP; 2583 ax->old_pcap.permitted = old->cap_permitted;
2585 ax->old_pcap.inheritable = current->cred->cap_inheritable; 2584 ax->old_pcap.inheritable = old->cap_inheritable;
2586 ax->old_pcap.effective = *pE; 2585 ax->old_pcap.effective = old->cap_effective;
2587 2586
2588 ax->new_pcap.permitted = current->cred->cap_permitted; 2587 ax->new_pcap.permitted = new->cap_permitted;
2589 ax->new_pcap.inheritable = current->cred->cap_inheritable; 2588 ax->new_pcap.inheritable = new->cap_inheritable;
2590 ax->new_pcap.effective = current->cred->cap_effective; 2589 ax->new_pcap.effective = new->cap_effective;
2590 return 0;
2591} 2591}
2592 2592
2593/** 2593/**
2594 * __audit_log_capset - store information about the arguments to the capset syscall 2594 * __audit_log_capset - store information about the arguments to the capset syscall
2595 * @pid target pid of the capset call 2595 * @pid: target pid of the capset call
2596 * @eff effective cap set 2596 * @new: the new credentials
2597 * @inh inheritible cap set 2597 * @old: the old (current) credentials
2598 * @perm permited cap set
2599 * 2598 *
2600 * Record the aguments userspace sent to sys_capset for later printing by the 2599 * Record the aguments userspace sent to sys_capset for later printing by the
2601 * audit system if applicable 2600 * audit system if applicable
2602 */ 2601 */
2603int __audit_log_capset(pid_t pid, kernel_cap_t *eff, kernel_cap_t *inh, kernel_cap_t *perm) 2602int __audit_log_capset(pid_t pid,
2603 const struct cred *new, const struct cred *old)
2604{ 2604{
2605 struct audit_aux_data_capset *ax; 2605 struct audit_aux_data_capset *ax;
2606 struct audit_context *context = current->audit_context; 2606 struct audit_context *context = current->audit_context;
@@ -2617,9 +2617,9 @@ int __audit_log_capset(pid_t pid, kernel_cap_t *eff, kernel_cap_t *inh, kernel_c
2617 context->aux = (void *)ax; 2617 context->aux = (void *)ax;
2618 2618
2619 ax->pid = pid; 2619 ax->pid = pid;
2620 ax->cap.effective = *eff; 2620 ax->cap.effective = new->cap_effective;
2621 ax->cap.inheritable = *eff; 2621 ax->cap.inheritable = new->cap_effective;
2622 ax->cap.permitted = *perm; 2622 ax->cap.permitted = new->cap_permitted;
2623 2623
2624 return 0; 2624 return 0;
2625} 2625}
diff --git a/kernel/capability.c b/kernel/capability.c
index a404b980b1bd..36b4b4daebec 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -15,12 +15,7 @@
15#include <linux/syscalls.h> 15#include <linux/syscalls.h>
16#include <linux/pid_namespace.h> 16#include <linux/pid_namespace.h>
17#include <asm/uaccess.h> 17#include <asm/uaccess.h>
18 18#include "cred-internals.h"
19/*
20 * This lock protects task->cap_* for all tasks including current.
21 * Locking rule: acquire this prior to tasklist_lock.
22 */
23static DEFINE_SPINLOCK(task_capability_lock);
24 19
25/* 20/*
26 * Leveraged for setting/resetting capabilities 21 * Leveraged for setting/resetting capabilities
@@ -128,12 +123,11 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
128} 123}
129 124
130/* 125/*
131 * If we have configured with filesystem capability support, then the 126 * The only thing that can change the capabilities of the current
132 * only thing that can change the capabilities of the current process 127 * process is the current process. As such, we can't be in this code
133 * is the current process. As such, we can't be in this code at the 128 * at the same time as we are in the process of setting capabilities
134 * same time as we are in the process of setting capabilities in this 129 * in this process. The net result is that we can limit our use of
135 * process. The net result is that we can limit our use of locks to 130 * locks to when we are reading the caps of another process.
136 * when we are reading the caps of another process.
137 */ 131 */
138static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, 132static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
139 kernel_cap_t *pIp, kernel_cap_t *pPp) 133 kernel_cap_t *pIp, kernel_cap_t *pPp)
@@ -143,7 +137,6 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
143 if (pid && (pid != task_pid_vnr(current))) { 137 if (pid && (pid != task_pid_vnr(current))) {
144 struct task_struct *target; 138 struct task_struct *target;
145 139
146 spin_lock(&task_capability_lock);
147 read_lock(&tasklist_lock); 140 read_lock(&tasklist_lock);
148 141
149 target = find_task_by_vpid(pid); 142 target = find_task_by_vpid(pid);
@@ -153,34 +146,12 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
153 ret = security_capget(target, pEp, pIp, pPp); 146 ret = security_capget(target, pEp, pIp, pPp);
154 147
155 read_unlock(&tasklist_lock); 148 read_unlock(&tasklist_lock);
156 spin_unlock(&task_capability_lock);
157 } else 149 } else
158 ret = security_capget(current, pEp, pIp, pPp); 150 ret = security_capget(current, pEp, pIp, pPp);
159 151
160 return ret; 152 return ret;
161} 153}
162 154
163/*
164 * Atomically modify the effective capabilities returning the original
165 * value. No permission check is performed here - it is assumed that the
166 * caller is permitted to set the desired effective capabilities.
167 */
168kernel_cap_t cap_set_effective(const kernel_cap_t pE_new)
169{
170 kernel_cap_t pE_old;
171
172 spin_lock(&task_capability_lock);
173
174 pE_old = current->cred->cap_effective;
175 current->cred->cap_effective = pE_new;
176
177 spin_unlock(&task_capability_lock);
178
179 return pE_old;
180}
181
182EXPORT_SYMBOL(cap_set_effective);
183
184/** 155/**
185 * sys_capget - get the capabilities of a given process. 156 * sys_capget - get the capabilities of a given process.
186 * @header: pointer to struct that contains capability version and 157 * @header: pointer to struct that contains capability version and
@@ -208,7 +179,6 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
208 return -EINVAL; 179 return -EINVAL;
209 180
210 ret = cap_get_target_pid(pid, &pE, &pI, &pP); 181 ret = cap_get_target_pid(pid, &pE, &pI, &pP);
211
212 if (!ret) { 182 if (!ret) {
213 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 183 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
214 unsigned i; 184 unsigned i;
@@ -270,6 +240,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
270 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 240 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
271 unsigned i, tocopy; 241 unsigned i, tocopy;
272 kernel_cap_t inheritable, permitted, effective; 242 kernel_cap_t inheritable, permitted, effective;
243 struct cred *new;
273 int ret; 244 int ret;
274 pid_t pid; 245 pid_t pid;
275 246
@@ -284,8 +255,8 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
284 if (pid != 0 && pid != task_pid_vnr(current)) 255 if (pid != 0 && pid != task_pid_vnr(current))
285 return -EPERM; 256 return -EPERM;
286 257
287 if (copy_from_user(&kdata, data, tocopy 258 if (copy_from_user(&kdata, data,
288 * sizeof(struct __user_cap_data_struct))) 259 tocopy * sizeof(struct __user_cap_data_struct)))
289 return -EFAULT; 260 return -EFAULT;
290 261
291 for (i = 0; i < tocopy; i++) { 262 for (i = 0; i < tocopy; i++) {
@@ -300,24 +271,23 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
300 i++; 271 i++;
301 } 272 }
302 273
303 ret = audit_log_capset(pid, &effective, &inheritable, &permitted); 274 new = prepare_creds();
304 if (ret) 275 if (!new)
276 return -ENOMEM;
277
278 ret = security_capset(new, current_cred(),
279 &effective, &inheritable, &permitted);
280 if (ret < 0)
281 goto error;
282
283 ret = audit_log_capset(pid, new, current_cred());
284 if (ret < 0)
305 return ret; 285 return ret;
306 286
307 /* This lock is required even when filesystem capability support is 287 return commit_creds(new);
308 * configured - it protects the sys_capget() call from returning 288
309 * incorrect data in the case that the targeted process is not the 289error:
310 * current one. 290 abort_creds(new);
311 */
312 spin_lock(&task_capability_lock);
313
314 ret = security_capset_check(&effective, &inheritable, &permitted);
315 /* Having verified that the proposed changes are legal, we now put them
316 * into effect.
317 */
318 if (!ret)
319 security_capset_set(&effective, &inheritable, &permitted);
320 spin_unlock(&task_capability_lock);
321 return ret; 291 return ret;
322} 292}
323 293
diff --git a/kernel/cred-internals.h b/kernel/cred-internals.h
new file mode 100644
index 000000000000..2dc4fc2d0bf1
--- /dev/null
+++ b/kernel/cred-internals.h
@@ -0,0 +1,21 @@
1/* Internal credentials stuff
2 *
3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12/*
13 * user.c
14 */
15static inline void sched_switch_user(struct task_struct *p)
16{
17#ifdef CONFIG_USER_SCHED
18 sched_move_task(p);
19#endif /* CONFIG_USER_SCHED */
20}
21
diff --git a/kernel/cred.c b/kernel/cred.c
index ac73e3617684..cb6b5eda978d 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -15,6 +15,10 @@
15#include <linux/keyctl.h> 15#include <linux/keyctl.h>
16#include <linux/init_task.h> 16#include <linux/init_task.h>
17#include <linux/security.h> 17#include <linux/security.h>
18#include <linux/cn_proc.h>
19#include "cred-internals.h"
20
21static struct kmem_cache *cred_jar;
18 22
19/* 23/*
20 * The common credentials for the initial task's thread group 24 * The common credentials for the initial task's thread group
@@ -64,7 +68,7 @@ static void release_tgcred_rcu(struct rcu_head *rcu)
64/* 68/*
65 * Release a set of thread group credentials. 69 * Release a set of thread group credentials.
66 */ 70 */
67static void release_tgcred(struct cred *cred) 71void release_tgcred(struct cred *cred)
68{ 72{
69#ifdef CONFIG_KEYS 73#ifdef CONFIG_KEYS
70 struct thread_group_cred *tgcred = cred->tgcred; 74 struct thread_group_cred *tgcred = cred->tgcred;
@@ -81,79 +85,322 @@ static void put_cred_rcu(struct rcu_head *rcu)
81{ 85{
82 struct cred *cred = container_of(rcu, struct cred, rcu); 86 struct cred *cred = container_of(rcu, struct cred, rcu);
83 87
84 BUG_ON(atomic_read(&cred->usage) != 0); 88 if (atomic_read(&cred->usage) != 0)
89 panic("CRED: put_cred_rcu() sees %p with usage %d\n",
90 cred, atomic_read(&cred->usage));
85 91
92 security_cred_free(cred);
86 key_put(cred->thread_keyring); 93 key_put(cred->thread_keyring);
87 key_put(cred->request_key_auth); 94 key_put(cred->request_key_auth);
88 release_tgcred(cred); 95 release_tgcred(cred);
89 put_group_info(cred->group_info); 96 put_group_info(cred->group_info);
90 free_uid(cred->user); 97 free_uid(cred->user);
91 security_cred_free(cred); 98 kmem_cache_free(cred_jar, cred);
92 kfree(cred);
93} 99}
94 100
95/** 101/**
96 * __put_cred - Destroy a set of credentials 102 * __put_cred - Destroy a set of credentials
97 * @sec: The record to release 103 * @cred: The record to release
98 * 104 *
99 * Destroy a set of credentials on which no references remain. 105 * Destroy a set of credentials on which no references remain.
100 */ 106 */
101void __put_cred(struct cred *cred) 107void __put_cred(struct cred *cred)
102{ 108{
109 BUG_ON(atomic_read(&cred->usage) != 0);
110
103 call_rcu(&cred->rcu, put_cred_rcu); 111 call_rcu(&cred->rcu, put_cred_rcu);
104} 112}
105EXPORT_SYMBOL(__put_cred); 113EXPORT_SYMBOL(__put_cred);
106 114
115/**
116 * prepare_creds - Prepare a new set of credentials for modification
117 *
118 * Prepare a new set of task credentials for modification. A task's creds
119 * shouldn't generally be modified directly, therefore this function is used to
120 * prepare a new copy, which the caller then modifies and then commits by
121 * calling commit_creds().
122 *
123 * Returns a pointer to the new creds-to-be if successful, NULL otherwise.
124 *
125 * Call commit_creds() or abort_creds() to clean up.
126 */
127struct cred *prepare_creds(void)
128{
129 struct task_struct *task = current;
130 const struct cred *old;
131 struct cred *new;
132
133 BUG_ON(atomic_read(&task->cred->usage) < 1);
134
135 new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
136 if (!new)
137 return NULL;
138
139 old = task->cred;
140 memcpy(new, old, sizeof(struct cred));
141
142 atomic_set(&new->usage, 1);
143 get_group_info(new->group_info);
144 get_uid(new->user);
145
146#ifdef CONFIG_KEYS
147 key_get(new->thread_keyring);
148 key_get(new->request_key_auth);
149 atomic_inc(&new->tgcred->usage);
150#endif
151
152#ifdef CONFIG_SECURITY
153 new->security = NULL;
154#endif
155
156 if (security_prepare_creds(new, old, GFP_KERNEL) < 0)
157 goto error;
158 return new;
159
160error:
161 abort_creds(new);
162 return NULL;
163}
164EXPORT_SYMBOL(prepare_creds);
165
166/*
167 * prepare new credentials for the usermode helper dispatcher
168 */
169struct cred *prepare_usermodehelper_creds(void)
170{
171#ifdef CONFIG_KEYS
172 struct thread_group_cred *tgcred = NULL;
173#endif
174 struct cred *new;
175
176#ifdef CONFIG_KEYS
177 tgcred = kzalloc(sizeof(*new->tgcred), GFP_ATOMIC);
178 if (!tgcred)
179 return NULL;
180#endif
181
182 new = kmem_cache_alloc(cred_jar, GFP_ATOMIC);
183 if (!new)
184 return NULL;
185
186 memcpy(new, &init_cred, sizeof(struct cred));
187
188 atomic_set(&new->usage, 1);
189 get_group_info(new->group_info);
190 get_uid(new->user);
191
192#ifdef CONFIG_KEYS
193 new->thread_keyring = NULL;
194 new->request_key_auth = NULL;
195 new->jit_keyring = KEY_REQKEY_DEFL_DEFAULT;
196
197 atomic_set(&tgcred->usage, 1);
198 spin_lock_init(&tgcred->lock);
199 new->tgcred = tgcred;
200#endif
201
202#ifdef CONFIG_SECURITY
203 new->security = NULL;
204#endif
205 if (security_prepare_creds(new, &init_cred, GFP_ATOMIC) < 0)
206 goto error;
207
208 BUG_ON(atomic_read(&new->usage) != 1);
209 return new;
210
211error:
212 put_cred(new);
213 return NULL;
214}
215
107/* 216/*
108 * Copy credentials for the new process created by fork() 217 * Copy credentials for the new process created by fork()
218 *
219 * We share if we can, but under some circumstances we have to generate a new
220 * set.
109 */ 221 */
110int copy_creds(struct task_struct *p, unsigned long clone_flags) 222int copy_creds(struct task_struct *p, unsigned long clone_flags)
111{ 223{
112 struct cred *pcred; 224#ifdef CONFIG_KEYS
113 int ret; 225 struct thread_group_cred *tgcred;
226#endif
227 struct cred *new;
228
229 mutex_init(&p->cred_exec_mutex);
114 230
115 pcred = kmemdup(p->cred, sizeof(*p->cred), GFP_KERNEL); 231 if (
116 if (!pcred) 232#ifdef CONFIG_KEYS
233 !p->cred->thread_keyring &&
234#endif
235 clone_flags & CLONE_THREAD
236 ) {
237 get_cred(p->cred);
238 atomic_inc(&p->cred->user->processes);
239 return 0;
240 }
241
242 new = prepare_creds();
243 if (!new)
117 return -ENOMEM; 244 return -ENOMEM;
118 245
119#ifdef CONFIG_KEYS 246#ifdef CONFIG_KEYS
120 if (clone_flags & CLONE_THREAD) { 247 /* new threads get their own thread keyrings if their parent already
121 atomic_inc(&pcred->tgcred->usage); 248 * had one */
122 } else { 249 if (new->thread_keyring) {
123 pcred->tgcred = kmalloc(sizeof(struct cred), GFP_KERNEL); 250 key_put(new->thread_keyring);
124 if (!pcred->tgcred) { 251 new->thread_keyring = NULL;
125 kfree(pcred); 252 if (clone_flags & CLONE_THREAD)
253 install_thread_keyring_to_cred(new);
254 }
255
256 /* we share the process and session keyrings between all the threads in
257 * a process - this is slightly icky as we violate COW credentials a
258 * bit */
259 if (!(clone_flags & CLONE_THREAD)) {
260 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
261 if (!tgcred) {
262 put_cred(new);
126 return -ENOMEM; 263 return -ENOMEM;
127 } 264 }
128 atomic_set(&pcred->tgcred->usage, 1); 265 atomic_set(&tgcred->usage, 1);
129 spin_lock_init(&pcred->tgcred->lock); 266 spin_lock_init(&tgcred->lock);
130 pcred->tgcred->process_keyring = NULL; 267 tgcred->process_keyring = NULL;
131 pcred->tgcred->session_keyring = 268 tgcred->session_keyring = key_get(new->tgcred->session_keyring);
132 key_get(p->cred->tgcred->session_keyring); 269
270 release_tgcred(new);
271 new->tgcred = tgcred;
133 } 272 }
134#endif 273#endif
135 274
136#ifdef CONFIG_SECURITY 275 atomic_inc(&new->user->processes);
137 pcred->security = NULL; 276 p->cred = new;
138#endif 277 return 0;
278}
139 279
140 ret = security_cred_alloc(pcred); 280/**
141 if (ret < 0) { 281 * commit_creds - Install new credentials upon the current task
142 release_tgcred(pcred); 282 * @new: The credentials to be assigned
143 kfree(pcred); 283 *
144 return ret; 284 * Install a new set of credentials to the current task, using RCU to replace
285 * the old set.
286 *
287 * This function eats the caller's reference to the new credentials.
288 *
289 * Always returns 0 thus allowing this function to be tail-called at the end
290 * of, say, sys_setgid().
291 */
292int commit_creds(struct cred *new)
293{
294 struct task_struct *task = current;
295 const struct cred *old;
296
297 BUG_ON(atomic_read(&new->usage) < 1);
298 BUG_ON(atomic_read(&task->cred->usage) < 1);
299
300 old = task->cred;
301 security_commit_creds(new, old);
302
303 /* dumpability changes */
304 if (old->euid != new->euid ||
305 old->egid != new->egid ||
306 old->fsuid != new->fsuid ||
307 old->fsgid != new->fsgid ||
308 !cap_issubset(new->cap_permitted, old->cap_permitted)) {
309 set_dumpable(task->mm, suid_dumpable);
310 task->pdeath_signal = 0;
311 smp_wmb();
145 } 312 }
146 313
147 atomic_set(&pcred->usage, 1); 314 /* alter the thread keyring */
148 get_group_info(pcred->group_info); 315 if (new->fsuid != old->fsuid)
149 get_uid(pcred->user); 316 key_fsuid_changed(task);
150 key_get(pcred->thread_keyring); 317 if (new->fsgid != old->fsgid)
151 key_get(pcred->request_key_auth); 318 key_fsgid_changed(task);
319
320 /* do it
321 * - What if a process setreuid()'s and this brings the
322 * new uid over his NPROC rlimit? We can check this now
323 * cheaply with the new uid cache, so if it matters
324 * we should be checking for it. -DaveM
325 */
326 if (new->user != old->user)
327 atomic_inc(&new->user->processes);
328 rcu_assign_pointer(task->cred, new);
329 if (new->user != old->user)
330 atomic_dec(&old->user->processes);
331
332 sched_switch_user(task);
333
334 /* send notifications */
335 if (new->uid != old->uid ||
336 new->euid != old->euid ||
337 new->suid != old->suid ||
338 new->fsuid != old->fsuid)
339 proc_id_connector(task, PROC_EVENT_UID);
152 340
153 atomic_inc(&pcred->user->processes); 341 if (new->gid != old->gid ||
342 new->egid != old->egid ||
343 new->sgid != old->sgid ||
344 new->fsgid != old->fsgid)
345 proc_id_connector(task, PROC_EVENT_GID);
154 346
155 /* RCU assignment is unneeded here as no-one can have accessed this 347 put_cred(old);
156 * pointer yet, barring us */
157 p->cred = pcred;
158 return 0; 348 return 0;
159} 349}
350EXPORT_SYMBOL(commit_creds);
351
352/**
353 * abort_creds - Discard a set of credentials and unlock the current task
354 * @new: The credentials that were going to be applied
355 *
356 * Discard a set of credentials that were under construction and unlock the
357 * current task.
358 */
359void abort_creds(struct cred *new)
360{
361 BUG_ON(atomic_read(&new->usage) < 1);
362 put_cred(new);
363}
364EXPORT_SYMBOL(abort_creds);
365
366/**
367 * override_creds - Temporarily override the current process's credentials
368 * @new: The credentials to be assigned
369 *
370 * Install a set of temporary override credentials on the current process,
371 * returning the old set for later reversion.
372 */
373const struct cred *override_creds(const struct cred *new)
374{
375 const struct cred *old = current->cred;
376
377 rcu_assign_pointer(current->cred, get_cred(new));
378 return old;
379}
380EXPORT_SYMBOL(override_creds);
381
382/**
383 * revert_creds - Revert a temporary credentials override
384 * @old: The credentials to be restored
385 *
386 * Revert a temporary set of override credentials to an old set, discarding the
387 * override set.
388 */
389void revert_creds(const struct cred *old)
390{
391 const struct cred *override = current->cred;
392
393 rcu_assign_pointer(current->cred, old);
394 put_cred(override);
395}
396EXPORT_SYMBOL(revert_creds);
397
398/*
399 * initialise the credentials stuff
400 */
401void __init cred_init(void)
402{
403 /* allocate a slab in which we can store credentials */
404 cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred),
405 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
406}
diff --git a/kernel/exit.c b/kernel/exit.c
index bbc22530f2c1..c0711da15486 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -47,12 +47,14 @@
47#include <linux/blkdev.h> 47#include <linux/blkdev.h>
48#include <linux/task_io_accounting_ops.h> 48#include <linux/task_io_accounting_ops.h>
49#include <linux/tracehook.h> 49#include <linux/tracehook.h>
50#include <linux/init_task.h>
50#include <trace/sched.h> 51#include <trace/sched.h>
51 52
52#include <asm/uaccess.h> 53#include <asm/uaccess.h>
53#include <asm/unistd.h> 54#include <asm/unistd.h>
54#include <asm/pgtable.h> 55#include <asm/pgtable.h>
55#include <asm/mmu_context.h> 56#include <asm/mmu_context.h>
57#include "cred-internals.h"
56 58
57static void exit_mm(struct task_struct * tsk); 59static void exit_mm(struct task_struct * tsk);
58 60
@@ -338,12 +340,12 @@ static void reparent_to_kthreadd(void)
338 /* cpus_allowed? */ 340 /* cpus_allowed? */
339 /* rt_priority? */ 341 /* rt_priority? */
340 /* signals? */ 342 /* signals? */
341 security_task_reparent_to_init(current);
342 memcpy(current->signal->rlim, init_task.signal->rlim, 343 memcpy(current->signal->rlim, init_task.signal->rlim,
343 sizeof(current->signal->rlim)); 344 sizeof(current->signal->rlim));
344 atomic_inc(&(INIT_USER->__count)); 345
346 atomic_inc(&init_cred.usage);
347 commit_creds(&init_cred);
345 write_unlock_irq(&tasklist_lock); 348 write_unlock_irq(&tasklist_lock);
346 switch_uid(INIT_USER);
347} 349}
348 350
349void __set_special_pids(struct pid *pid) 351void __set_special_pids(struct pid *pid)
@@ -1085,7 +1087,6 @@ NORET_TYPE void do_exit(long code)
1085 check_stack_usage(); 1087 check_stack_usage();
1086 exit_thread(); 1088 exit_thread();
1087 cgroup_exit(tsk, 1); 1089 cgroup_exit(tsk, 1);
1088 exit_keys(tsk);
1089 1090
1090 if (group_dead && tsk->signal->leader) 1091 if (group_dead && tsk->signal->leader)
1091 disassociate_ctty(1); 1092 disassociate_ctty(1);
diff --git a/kernel/fork.c b/kernel/fork.c
index ded1972672a3..82a7948a664e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1084,10 +1084,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1084 goto bad_fork_cleanup_sighand; 1084 goto bad_fork_cleanup_sighand;
1085 if ((retval = copy_mm(clone_flags, p))) 1085 if ((retval = copy_mm(clone_flags, p)))
1086 goto bad_fork_cleanup_signal; 1086 goto bad_fork_cleanup_signal;
1087 if ((retval = copy_keys(clone_flags, p)))
1088 goto bad_fork_cleanup_mm;
1089 if ((retval = copy_namespaces(clone_flags, p))) 1087 if ((retval = copy_namespaces(clone_flags, p)))
1090 goto bad_fork_cleanup_keys; 1088 goto bad_fork_cleanup_mm;
1091 if ((retval = copy_io(clone_flags, p))) 1089 if ((retval = copy_io(clone_flags, p)))
1092 goto bad_fork_cleanup_namespaces; 1090 goto bad_fork_cleanup_namespaces;
1093 retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); 1091 retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
@@ -1252,8 +1250,6 @@ bad_fork_cleanup_io:
1252 put_io_context(p->io_context); 1250 put_io_context(p->io_context);
1253bad_fork_cleanup_namespaces: 1251bad_fork_cleanup_namespaces:
1254 exit_task_namespaces(p); 1252 exit_task_namespaces(p);
1255bad_fork_cleanup_keys:
1256 exit_keys(p);
1257bad_fork_cleanup_mm: 1253bad_fork_cleanup_mm:
1258 if (p->mm) 1254 if (p->mm)
1259 mmput(p->mm); 1255 mmput(p->mm);
@@ -1281,6 +1277,7 @@ bad_fork_cleanup_cgroup:
1281bad_fork_cleanup_put_domain: 1277bad_fork_cleanup_put_domain:
1282 module_put(task_thread_info(p)->exec_domain->module); 1278 module_put(task_thread_info(p)->exec_domain->module);
1283bad_fork_cleanup_count: 1279bad_fork_cleanup_count:
1280 atomic_dec(&p->cred->user->processes);
1284 put_cred(p->cred); 1281 put_cred(p->cred);
1285bad_fork_free: 1282bad_fork_free:
1286 free_task(p); 1283 free_task(p);
diff --git a/kernel/kmod.c b/kernel/kmod.c
index f044f8f57703..b46dbb908669 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -118,10 +118,10 @@ EXPORT_SYMBOL(request_module);
118struct subprocess_info { 118struct subprocess_info {
119 struct work_struct work; 119 struct work_struct work;
120 struct completion *complete; 120 struct completion *complete;
121 struct cred *cred;
121 char *path; 122 char *path;
122 char **argv; 123 char **argv;
123 char **envp; 124 char **envp;
124 struct key *ring;
125 enum umh_wait wait; 125 enum umh_wait wait;
126 int retval; 126 int retval;
127 struct file *stdin; 127 struct file *stdin;
@@ -134,19 +134,20 @@ struct subprocess_info {
134static int ____call_usermodehelper(void *data) 134static int ____call_usermodehelper(void *data)
135{ 135{
136 struct subprocess_info *sub_info = data; 136 struct subprocess_info *sub_info = data;
137 struct key *new_session, *old_session;
138 int retval; 137 int retval;
139 138
140 /* Unblock all signals and set the session keyring. */ 139 BUG_ON(atomic_read(&sub_info->cred->usage) != 1);
141 new_session = key_get(sub_info->ring); 140
141 /* Unblock all signals */
142 spin_lock_irq(&current->sighand->siglock); 142 spin_lock_irq(&current->sighand->siglock);
143 old_session = __install_session_keyring(new_session);
144 flush_signal_handlers(current, 1); 143 flush_signal_handlers(current, 1);
145 sigemptyset(&current->blocked); 144 sigemptyset(&current->blocked);
146 recalc_sigpending(); 145 recalc_sigpending();
147 spin_unlock_irq(&current->sighand->siglock); 146 spin_unlock_irq(&current->sighand->siglock);
148 147
149 key_put(old_session); 148 /* Install the credentials */
149 commit_creds(sub_info->cred);
150 sub_info->cred = NULL;
150 151
151 /* Install input pipe when needed */ 152 /* Install input pipe when needed */
152 if (sub_info->stdin) { 153 if (sub_info->stdin) {
@@ -185,6 +186,8 @@ void call_usermodehelper_freeinfo(struct subprocess_info *info)
185{ 186{
186 if (info->cleanup) 187 if (info->cleanup)
187 (*info->cleanup)(info->argv, info->envp); 188 (*info->cleanup)(info->argv, info->envp);
189 if (info->cred)
190 put_cred(info->cred);
188 kfree(info); 191 kfree(info);
189} 192}
190EXPORT_SYMBOL(call_usermodehelper_freeinfo); 193EXPORT_SYMBOL(call_usermodehelper_freeinfo);
@@ -240,6 +243,8 @@ static void __call_usermodehelper(struct work_struct *work)
240 pid_t pid; 243 pid_t pid;
241 enum umh_wait wait = sub_info->wait; 244 enum umh_wait wait = sub_info->wait;
242 245
246 BUG_ON(atomic_read(&sub_info->cred->usage) != 1);
247
243 /* CLONE_VFORK: wait until the usermode helper has execve'd 248 /* CLONE_VFORK: wait until the usermode helper has execve'd
244 * successfully We need the data structures to stay around 249 * successfully We need the data structures to stay around
245 * until that is done. */ 250 * until that is done. */
@@ -362,6 +367,9 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
362 sub_info->path = path; 367 sub_info->path = path;
363 sub_info->argv = argv; 368 sub_info->argv = argv;
364 sub_info->envp = envp; 369 sub_info->envp = envp;
370 sub_info->cred = prepare_usermodehelper_creds();
371 if (!sub_info->cred)
372 return NULL;
365 373
366 out: 374 out:
367 return sub_info; 375 return sub_info;
@@ -376,7 +384,13 @@ EXPORT_SYMBOL(call_usermodehelper_setup);
376void call_usermodehelper_setkeys(struct subprocess_info *info, 384void call_usermodehelper_setkeys(struct subprocess_info *info,
377 struct key *session_keyring) 385 struct key *session_keyring)
378{ 386{
379 info->ring = session_keyring; 387#ifdef CONFIG_KEYS
388 struct thread_group_cred *tgcred = info->cred->tgcred;
389 key_put(tgcred->session_keyring);
390 tgcred->session_keyring = key_get(session_keyring);
391#else
392 BUG();
393#endif
380} 394}
381EXPORT_SYMBOL(call_usermodehelper_setkeys); 395EXPORT_SYMBOL(call_usermodehelper_setkeys);
382 396
@@ -444,6 +458,8 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info,
444 DECLARE_COMPLETION_ONSTACK(done); 458 DECLARE_COMPLETION_ONSTACK(done);
445 int retval = 0; 459 int retval = 0;
446 460
461 BUG_ON(atomic_read(&sub_info->cred->usage) != 1);
462
447 helper_lock(); 463 helper_lock();
448 if (sub_info->path[0] == '\0') 464 if (sub_info->path[0] == '\0')
449 goto out; 465 goto out;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index b9d5f4e4f6a4..f764b8806955 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -171,6 +171,14 @@ int ptrace_attach(struct task_struct *task)
171 if (same_thread_group(task, current)) 171 if (same_thread_group(task, current))
172 goto out; 172 goto out;
173 173
174 /* Protect exec's credential calculations against our interference;
175 * SUID, SGID and LSM creds get determined differently under ptrace.
176 */
177 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
178 if (retval < 0)
179 goto out;
180
181 retval = -EPERM;
174repeat: 182repeat:
175 /* 183 /*
176 * Nasty, nasty. 184 * Nasty, nasty.
@@ -210,6 +218,7 @@ repeat:
210bad: 218bad:
211 write_unlock_irqrestore(&tasklist_lock, flags); 219 write_unlock_irqrestore(&tasklist_lock, flags);
212 task_unlock(task); 220 task_unlock(task);
221 mutex_unlock(&current->cred_exec_mutex);
213out: 222out:
214 return retval; 223 return retval;
215} 224}
diff --git a/kernel/signal.c b/kernel/signal.c
index 84989124bafb..2a64304ed54b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -180,7 +180,7 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
180/* 180/*
181 * allocate a new signal queue record 181 * allocate a new signal queue record
182 * - this may be called without locks if and only if t == current, otherwise an 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 183 * appopriate lock must be held to stop the target task from exiting
184 */ 184 */
185static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, 185static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
186 int override_rlimit) 186 int override_rlimit)
@@ -194,7 +194,7 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
194 * caller must be holding the RCU readlock (by way of a spinlock) and 194 * caller must be holding the RCU readlock (by way of a spinlock) and
195 * we use RCU protection here 195 * we use RCU protection here
196 */ 196 */
197 user = __task_cred(t)->user; 197 user = get_uid(__task_cred(t)->user);
198 atomic_inc(&user->sigpending); 198 atomic_inc(&user->sigpending);
199 if (override_rlimit || 199 if (override_rlimit ||
200 atomic_read(&user->sigpending) <= 200 atomic_read(&user->sigpending) <=
@@ -202,12 +202,14 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
202 q = kmem_cache_alloc(sigqueue_cachep, flags); 202 q = kmem_cache_alloc(sigqueue_cachep, flags);
203 if (unlikely(q == NULL)) { 203 if (unlikely(q == NULL)) {
204 atomic_dec(&user->sigpending); 204 atomic_dec(&user->sigpending);
205 free_uid(user);
205 } else { 206 } else {
206 INIT_LIST_HEAD(&q->list); 207 INIT_LIST_HEAD(&q->list);
207 q->flags = 0; 208 q->flags = 0;
208 q->user = get_uid(user); 209 q->user = user;
209 } 210 }
210 return(q); 211
212 return q;
211} 213}
212 214
213static void __sigqueue_free(struct sigqueue *q) 215static void __sigqueue_free(struct sigqueue *q)
diff --git a/kernel/sys.c b/kernel/sys.c
index ccc9eb736d35..ab735040468a 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -180,7 +180,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
180 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 180 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
181 break; 181 break;
182 case PRIO_USER: 182 case PRIO_USER:
183 user = cred->user; 183 user = (struct user_struct *) cred->user;
184 if (!who) 184 if (!who)
185 who = cred->uid; 185 who = cred->uid;
186 else if ((who != cred->uid) && 186 else if ((who != cred->uid) &&
@@ -479,47 +479,48 @@ void ctrl_alt_del(void)
479 */ 479 */
480asmlinkage long sys_setregid(gid_t rgid, gid_t egid) 480asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
481{ 481{
482 struct cred *cred = current->cred; 482 const struct cred *old;
483 int old_rgid = cred->gid; 483 struct cred *new;
484 int old_egid = cred->egid;
485 int new_rgid = old_rgid;
486 int new_egid = old_egid;
487 int retval; 484 int retval;
488 485
486 new = prepare_creds();
487 if (!new)
488 return -ENOMEM;
489 old = current_cred();
490
489 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE); 491 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
490 if (retval) 492 if (retval)
491 return retval; 493 goto error;
492 494
495 retval = -EPERM;
493 if (rgid != (gid_t) -1) { 496 if (rgid != (gid_t) -1) {
494 if ((old_rgid == rgid) || 497 if (old->gid == rgid ||
495 (cred->egid == rgid) || 498 old->egid == rgid ||
496 capable(CAP_SETGID)) 499 capable(CAP_SETGID))
497 new_rgid = rgid; 500 new->gid = rgid;
498 else 501 else
499 return -EPERM; 502 goto error;
500 } 503 }
501 if (egid != (gid_t) -1) { 504 if (egid != (gid_t) -1) {
502 if ((old_rgid == egid) || 505 if (old->gid == egid ||
503 (cred->egid == egid) || 506 old->egid == egid ||
504 (cred->sgid == egid) || 507 old->sgid == egid ||
505 capable(CAP_SETGID)) 508 capable(CAP_SETGID))
506 new_egid = egid; 509 new->egid = egid;
507 else 510 else
508 return -EPERM; 511 goto error;
509 }
510 if (new_egid != old_egid) {
511 set_dumpable(current->mm, suid_dumpable);
512 smp_wmb();
513 } 512 }
513
514 if (rgid != (gid_t) -1 || 514 if (rgid != (gid_t) -1 ||
515 (egid != (gid_t) -1 && egid != old_rgid)) 515 (egid != (gid_t) -1 && egid != old->gid))
516 cred->sgid = new_egid; 516 new->sgid = new->egid;
517 cred->fsgid = new_egid; 517 new->fsgid = new->egid;
518 cred->egid = new_egid; 518
519 cred->gid = new_rgid; 519 return commit_creds(new);
520 key_fsgid_changed(current); 520
521 proc_id_connector(current, PROC_EVENT_GID); 521error:
522 return 0; 522 abort_creds(new);
523 return retval;
523} 524}
524 525
525/* 526/*
@@ -529,40 +530,42 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
529 */ 530 */
530asmlinkage long sys_setgid(gid_t gid) 531asmlinkage long sys_setgid(gid_t gid)
531{ 532{
532 struct cred *cred = current->cred; 533 const struct cred *old;
533 int old_egid = cred->egid; 534 struct cred *new;
534 int retval; 535 int retval;
535 536
537 new = prepare_creds();
538 if (!new)
539 return -ENOMEM;
540 old = current_cred();
541
536 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID); 542 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
537 if (retval) 543 if (retval)
538 return retval; 544 goto error;
539 545
540 if (capable(CAP_SETGID)) { 546 retval = -EPERM;
541 if (old_egid != gid) { 547 if (capable(CAP_SETGID))
542 set_dumpable(current->mm, suid_dumpable); 548 new->gid = new->egid = new->sgid = new->fsgid = gid;
543 smp_wmb(); 549 else if (gid == old->gid || gid == old->sgid)
544 } 550 new->egid = new->fsgid = gid;
545 cred->gid = cred->egid = cred->sgid = cred->fsgid = gid;
546 } else if ((gid == cred->gid) || (gid == cred->sgid)) {
547 if (old_egid != gid) {
548 set_dumpable(current->mm, suid_dumpable);
549 smp_wmb();
550 }
551 cred->egid = cred->fsgid = gid;
552 }
553 else 551 else
554 return -EPERM; 552 goto error;
555 553
556 key_fsgid_changed(current); 554 return commit_creds(new);
557 proc_id_connector(current, PROC_EVENT_GID); 555
558 return 0; 556error:
557 abort_creds(new);
558 return retval;
559} 559}
560 560
561static int set_user(uid_t new_ruid, int dumpclear) 561/*
562 * change the user struct in a credentials set to match the new UID
563 */
564static int set_user(struct cred *new)
562{ 565{
563 struct user_struct *new_user; 566 struct user_struct *new_user;
564 567
565 new_user = alloc_uid(current->nsproxy->user_ns, new_ruid); 568 new_user = alloc_uid(current->nsproxy->user_ns, new->uid);
566 if (!new_user) 569 if (!new_user)
567 return -EAGAIN; 570 return -EAGAIN;
568 571
@@ -573,13 +576,8 @@ static int set_user(uid_t new_ruid, int dumpclear)
573 return -EAGAIN; 576 return -EAGAIN;
574 } 577 }
575 578
576 switch_uid(new_user); 579 free_uid(new->user);
577 580 new->user = new_user;
578 if (dumpclear) {
579 set_dumpable(current->mm, suid_dumpable);
580 smp_wmb();
581 }
582 current->cred->uid = new_ruid;
583 return 0; 581 return 0;
584} 582}
585 583
@@ -600,55 +598,56 @@ static int set_user(uid_t new_ruid, int dumpclear)
600 */ 598 */
601asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) 599asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
602{ 600{
603 struct cred *cred = current->cred; 601 const struct cred *old;
604 int old_ruid, old_euid, old_suid, new_ruid, new_euid; 602 struct cred *new;
605 int retval; 603 int retval;
606 604
605 new = prepare_creds();
606 if (!new)
607 return -ENOMEM;
608 old = current_cred();
609
607 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE); 610 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
608 if (retval) 611 if (retval)
609 return retval; 612 goto error;
610
611 new_ruid = old_ruid = cred->uid;
612 new_euid = old_euid = cred->euid;
613 old_suid = cred->suid;
614 613
614 retval = -EPERM;
615 if (ruid != (uid_t) -1) { 615 if (ruid != (uid_t) -1) {
616 new_ruid = ruid; 616 new->uid = ruid;
617 if ((old_ruid != ruid) && 617 if (old->uid != ruid &&
618 (cred->euid != ruid) && 618 old->euid != ruid &&
619 !capable(CAP_SETUID)) 619 !capable(CAP_SETUID))
620 return -EPERM; 620 goto error;
621 } 621 }
622 622
623 if (euid != (uid_t) -1) { 623 if (euid != (uid_t) -1) {
624 new_euid = euid; 624 new->euid = euid;
625 if ((old_ruid != euid) && 625 if (old->uid != euid &&
626 (cred->euid != euid) && 626 old->euid != euid &&
627 (cred->suid != euid) && 627 old->suid != euid &&
628 !capable(CAP_SETUID)) 628 !capable(CAP_SETUID))
629 return -EPERM; 629 goto error;
630 } 630 }
631 631
632 if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) 632 retval = -EAGAIN;
633 return -EAGAIN; 633 if (new->uid != old->uid && set_user(new) < 0)
634 goto error;
634 635
635 if (new_euid != old_euid) {
636 set_dumpable(current->mm, suid_dumpable);
637 smp_wmb();
638 }
639 cred->fsuid = cred->euid = new_euid;
640 if (ruid != (uid_t) -1 || 636 if (ruid != (uid_t) -1 ||
641 (euid != (uid_t) -1 && euid != old_ruid)) 637 (euid != (uid_t) -1 && euid != old->uid))
642 cred->suid = cred->euid; 638 new->suid = new->euid;
643 cred->fsuid = cred->euid; 639 new->fsuid = new->euid;
644
645 key_fsuid_changed(current);
646 proc_id_connector(current, PROC_EVENT_UID);
647 640
648 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); 641 retval = security_task_fix_setuid(new, old, LSM_SETID_RE);
649} 642 if (retval < 0)
643 goto error;
650 644
645 return commit_creds(new);
651 646
647error:
648 abort_creds(new);
649 return retval;
650}
652 651
653/* 652/*
654 * setuid() is implemented like SysV with SAVED_IDS 653 * setuid() is implemented like SysV with SAVED_IDS
@@ -663,37 +662,41 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
663 */ 662 */
664asmlinkage long sys_setuid(uid_t uid) 663asmlinkage long sys_setuid(uid_t uid)
665{ 664{
666 struct cred *cred = current->cred; 665 const struct cred *old;
667 int old_euid = cred->euid; 666 struct cred *new;
668 int old_ruid, old_suid, new_suid;
669 int retval; 667 int retval;
670 668
669 new = prepare_creds();
670 if (!new)
671 return -ENOMEM;
672 old = current_cred();
673
671 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID); 674 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
672 if (retval) 675 if (retval)
673 return retval; 676 goto error;
674 677
675 old_ruid = cred->uid; 678 retval = -EPERM;
676 old_suid = cred->suid;
677 new_suid = old_suid;
678
679 if (capable(CAP_SETUID)) { 679 if (capable(CAP_SETUID)) {
680 if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) 680 new->suid = new->uid = uid;
681 return -EAGAIN; 681 if (uid != old->uid && set_user(new) < 0) {
682 new_suid = uid; 682 retval = -EAGAIN;
683 } else if ((uid != cred->uid) && (uid != new_suid)) 683 goto error;
684 return -EPERM; 684 }
685 685 } else if (uid != old->uid && uid != new->suid) {
686 if (old_euid != uid) { 686 goto error;
687 set_dumpable(current->mm, suid_dumpable);
688 smp_wmb();
689 } 687 }
690 cred->fsuid = cred->euid = uid;
691 cred->suid = new_suid;
692 688
693 key_fsuid_changed(current); 689 new->fsuid = new->euid = uid;
694 proc_id_connector(current, PROC_EVENT_UID); 690
691 retval = security_task_fix_setuid(new, old, LSM_SETID_ID);
692 if (retval < 0)
693 goto error;
694
695 return commit_creds(new);
695 696
696 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); 697error:
698 abort_creds(new);
699 return retval;
697} 700}
698 701
699 702
@@ -703,47 +706,53 @@ asmlinkage long sys_setuid(uid_t uid)
703 */ 706 */
704asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) 707asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
705{ 708{
706 struct cred *cred = current->cred; 709 const struct cred *old;
707 int old_ruid = cred->uid; 710 struct cred *new;
708 int old_euid = cred->euid;
709 int old_suid = cred->suid;
710 int retval; 711 int retval;
711 712
713 new = prepare_creds();
714 if (!new)
715 return -ENOMEM;
716
712 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES); 717 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
713 if (retval) 718 if (retval)
714 return retval; 719 goto error;
720 old = current_cred();
715 721
722 retval = -EPERM;
716 if (!capable(CAP_SETUID)) { 723 if (!capable(CAP_SETUID)) {
717 if ((ruid != (uid_t) -1) && (ruid != cred->uid) && 724 if (ruid != (uid_t) -1 && ruid != old->uid &&
718 (ruid != cred->euid) && (ruid != cred->suid)) 725 ruid != old->euid && ruid != old->suid)
719 return -EPERM; 726 goto error;
720 if ((euid != (uid_t) -1) && (euid != cred->uid) && 727 if (euid != (uid_t) -1 && euid != old->uid &&
721 (euid != cred->euid) && (euid != cred->suid)) 728 euid != old->euid && euid != old->suid)
722 return -EPERM; 729 goto error;
723 if ((suid != (uid_t) -1) && (suid != cred->uid) && 730 if (suid != (uid_t) -1 && suid != old->uid &&
724 (suid != cred->euid) && (suid != cred->suid)) 731 suid != old->euid && suid != old->suid)
725 return -EPERM; 732 goto error;
726 } 733 }
734
735 retval = -EAGAIN;
727 if (ruid != (uid_t) -1) { 736 if (ruid != (uid_t) -1) {
728 if (ruid != cred->uid && 737 new->uid = ruid;
729 set_user(ruid, euid != cred->euid) < 0) 738 if (ruid != old->uid && set_user(new) < 0)
730 return -EAGAIN; 739 goto error;
731 } 740 }
732 if (euid != (uid_t) -1) { 741 if (euid != (uid_t) -1)
733 if (euid != cred->euid) { 742 new->euid = euid;
734 set_dumpable(current->mm, suid_dumpable);
735 smp_wmb();
736 }
737 cred->euid = euid;
738 }
739 cred->fsuid = cred->euid;
740 if (suid != (uid_t) -1) 743 if (suid != (uid_t) -1)
741 cred->suid = suid; 744 new->suid = suid;
745 new->fsuid = new->euid;
742 746
743 key_fsuid_changed(current); 747 retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
744 proc_id_connector(current, PROC_EVENT_UID); 748 if (retval < 0)
749 goto error;
745 750
746 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); 751 return commit_creds(new);
752
753error:
754 abort_creds(new);
755 return retval;
747} 756}
748 757
749asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid) 758asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)
@@ -763,40 +772,45 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us
763 */ 772 */
764asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) 773asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
765{ 774{
766 struct cred *cred = current->cred; 775 const struct cred *old;
776 struct cred *new;
767 int retval; 777 int retval;
768 778
779 new = prepare_creds();
780 if (!new)
781 return -ENOMEM;
782 old = current_cred();
783
769 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES); 784 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
770 if (retval) 785 if (retval)
771 return retval; 786 goto error;
772 787
788 retval = -EPERM;
773 if (!capable(CAP_SETGID)) { 789 if (!capable(CAP_SETGID)) {
774 if ((rgid != (gid_t) -1) && (rgid != cred->gid) && 790 if (rgid != (gid_t) -1 && rgid != old->gid &&
775 (rgid != cred->egid) && (rgid != cred->sgid)) 791 rgid != old->egid && rgid != old->sgid)
776 return -EPERM; 792 goto error;
777 if ((egid != (gid_t) -1) && (egid != cred->gid) && 793 if (egid != (gid_t) -1 && egid != old->gid &&
778 (egid != cred->egid) && (egid != cred->sgid)) 794 egid != old->egid && egid != old->sgid)
779 return -EPERM; 795 goto error;
780 if ((sgid != (gid_t) -1) && (sgid != cred->gid) && 796 if (sgid != (gid_t) -1 && sgid != old->gid &&
781 (sgid != cred->egid) && (sgid != cred->sgid)) 797 sgid != old->egid && sgid != old->sgid)
782 return -EPERM; 798 goto error;
783 } 799 }
784 if (egid != (gid_t) -1) { 800
785 if (egid != cred->egid) {
786 set_dumpable(current->mm, suid_dumpable);
787 smp_wmb();
788 }
789 cred->egid = egid;
790 }
791 cred->fsgid = cred->egid;
792 if (rgid != (gid_t) -1) 801 if (rgid != (gid_t) -1)
793 cred->gid = rgid; 802 new->gid = rgid;
803 if (egid != (gid_t) -1)
804 new->egid = egid;
794 if (sgid != (gid_t) -1) 805 if (sgid != (gid_t) -1)
795 cred->sgid = sgid; 806 new->sgid = sgid;
807 new->fsgid = new->egid;
796 808
797 key_fsgid_changed(current); 809 return commit_creds(new);
798 proc_id_connector(current, PROC_EVENT_GID); 810
799 return 0; 811error:
812 abort_creds(new);
813 return retval;
800} 814}
801 815
802asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid) 816asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
@@ -820,28 +834,35 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us
820 */ 834 */
821asmlinkage long sys_setfsuid(uid_t uid) 835asmlinkage long sys_setfsuid(uid_t uid)
822{ 836{
823 struct cred *cred = current->cred; 837 const struct cred *old;
824 int old_fsuid; 838 struct cred *new;
839 uid_t old_fsuid;
840
841 new = prepare_creds();
842 if (!new)
843 return current_fsuid();
844 old = current_cred();
845 old_fsuid = old->fsuid;
825 846
826 old_fsuid = cred->fsuid; 847 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
827 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) 848 goto error;
828 return old_fsuid;
829 849
830 if (uid == cred->uid || uid == cred->euid || 850 if (uid == old->uid || uid == old->euid ||
831 uid == cred->suid || uid == cred->fsuid || 851 uid == old->suid || uid == old->fsuid ||
832 capable(CAP_SETUID)) { 852 capable(CAP_SETUID)) {
833 if (uid != old_fsuid) { 853 if (uid != old_fsuid) {
834 set_dumpable(current->mm, suid_dumpable); 854 new->fsuid = uid;
835 smp_wmb(); 855 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
856 goto change_okay;
836 } 857 }
837 cred->fsuid = uid;
838 } 858 }
839 859
840 key_fsuid_changed(current); 860error:
841 proc_id_connector(current, PROC_EVENT_UID); 861 abort_creds(new);
842 862 return old_fsuid;
843 security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
844 863
864change_okay:
865 commit_creds(new);
845 return old_fsuid; 866 return old_fsuid;
846} 867}
847 868
@@ -850,24 +871,34 @@ asmlinkage long sys_setfsuid(uid_t uid)
850 */ 871 */
851asmlinkage long sys_setfsgid(gid_t gid) 872asmlinkage long sys_setfsgid(gid_t gid)
852{ 873{
853 struct cred *cred = current->cred; 874 const struct cred *old;
854 int old_fsgid; 875 struct cred *new;
876 gid_t old_fsgid;
877
878 new = prepare_creds();
879 if (!new)
880 return current_fsgid();
881 old = current_cred();
882 old_fsgid = old->fsgid;
855 883
856 old_fsgid = cred->fsgid;
857 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) 884 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
858 return old_fsgid; 885 goto error;
859 886
860 if (gid == cred->gid || gid == cred->egid || 887 if (gid == old->gid || gid == old->egid ||
861 gid == cred->sgid || gid == cred->fsgid || 888 gid == old->sgid || gid == old->fsgid ||
862 capable(CAP_SETGID)) { 889 capable(CAP_SETGID)) {
863 if (gid != old_fsgid) { 890 if (gid != old_fsgid) {
864 set_dumpable(current->mm, suid_dumpable); 891 new->fsgid = gid;
865 smp_wmb(); 892 goto change_okay;
866 } 893 }
867 cred->fsgid = gid;
868 key_fsgid_changed(current);
869 proc_id_connector(current, PROC_EVENT_GID);
870 } 894 }
895
896error:
897 abort_creds(new);
898 return old_fsgid;
899
900change_okay:
901 commit_creds(new);
871 return old_fsgid; 902 return old_fsgid;
872} 903}
873 904
@@ -1136,7 +1167,7 @@ EXPORT_SYMBOL(groups_free);
1136 1167
1137/* export the group_info to a user-space array */ 1168/* export the group_info to a user-space array */
1138static int groups_to_user(gid_t __user *grouplist, 1169static int groups_to_user(gid_t __user *grouplist,
1139 struct group_info *group_info) 1170 const struct group_info *group_info)
1140{ 1171{
1141 int i; 1172 int i;
1142 unsigned int count = group_info->ngroups; 1173 unsigned int count = group_info->ngroups;
@@ -1227,31 +1258,25 @@ int groups_search(const struct group_info *group_info, gid_t grp)
1227} 1258}
1228 1259
1229/** 1260/**
1230 * set_groups - Change a group subscription in a security record 1261 * set_groups - Change a group subscription in a set of credentials
1231 * @sec: The security record to alter 1262 * @new: The newly prepared set of credentials to alter
1232 * @group_info: The group list to impose 1263 * @group_info: The group list to install
1233 * 1264 *
1234 * Validate a group subscription and, if valid, impose it upon a task security 1265 * Validate a group subscription and, if valid, insert it into a set
1235 * record. 1266 * of credentials.
1236 */ 1267 */
1237int set_groups(struct cred *cred, struct group_info *group_info) 1268int set_groups(struct cred *new, struct group_info *group_info)
1238{ 1269{
1239 int retval; 1270 int retval;
1240 struct group_info *old_info;
1241 1271
1242 retval = security_task_setgroups(group_info); 1272 retval = security_task_setgroups(group_info);
1243 if (retval) 1273 if (retval)
1244 return retval; 1274 return retval;
1245 1275
1276 put_group_info(new->group_info);
1246 groups_sort(group_info); 1277 groups_sort(group_info);
1247 get_group_info(group_info); 1278 get_group_info(group_info);
1248 1279 new->group_info = group_info;
1249 spin_lock(&cred->lock);
1250 old_info = cred->group_info;
1251 cred->group_info = group_info;
1252 spin_unlock(&cred->lock);
1253
1254 put_group_info(old_info);
1255 return 0; 1280 return 0;
1256} 1281}
1257 1282
@@ -1266,7 +1291,20 @@ EXPORT_SYMBOL(set_groups);
1266 */ 1291 */
1267int set_current_groups(struct group_info *group_info) 1292int set_current_groups(struct group_info *group_info)
1268{ 1293{
1269 return set_groups(current->cred, group_info); 1294 struct cred *new;
1295 int ret;
1296
1297 new = prepare_creds();
1298 if (!new)
1299 return -ENOMEM;
1300
1301 ret = set_groups(new, group_info);
1302 if (ret < 0) {
1303 abort_creds(new);
1304 return ret;
1305 }
1306
1307 return commit_creds(new);
1270} 1308}
1271 1309
1272EXPORT_SYMBOL(set_current_groups); 1310EXPORT_SYMBOL(set_current_groups);
@@ -1666,9 +1704,11 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1666 unsigned char comm[sizeof(me->comm)]; 1704 unsigned char comm[sizeof(me->comm)];
1667 long error; 1705 long error;
1668 1706
1669 if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) 1707 error = security_task_prctl(option, arg2, arg3, arg4, arg5);
1708 if (error != -ENOSYS)
1670 return error; 1709 return error;
1671 1710
1711 error = 0;
1672 switch (option) { 1712 switch (option) {
1673 case PR_SET_PDEATHSIG: 1713 case PR_SET_PDEATHSIG:
1674 if (!valid_signal(arg2)) { 1714 if (!valid_signal(arg2)) {
diff --git a/kernel/user.c b/kernel/user.c
index 104d22ac84d5..d476307dd4b0 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -16,6 +16,7 @@
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/user_namespace.h> 18#include <linux/user_namespace.h>
19#include "cred-internals.h"
19 20
20struct user_namespace init_user_ns = { 21struct user_namespace init_user_ns = {
21 .kref = { 22 .kref = {
@@ -104,16 +105,10 @@ static int sched_create_user(struct user_struct *up)
104 return rc; 105 return rc;
105} 106}
106 107
107static void sched_switch_user(struct task_struct *p)
108{
109 sched_move_task(p);
110}
111
112#else /* CONFIG_USER_SCHED */ 108#else /* CONFIG_USER_SCHED */
113 109
114static void sched_destroy_user(struct user_struct *up) { } 110static void sched_destroy_user(struct user_struct *up) { }
115static int sched_create_user(struct user_struct *up) { return 0; } 111static int sched_create_user(struct user_struct *up) { return 0; }
116static void sched_switch_user(struct task_struct *p) { }
117 112
118#endif /* CONFIG_USER_SCHED */ 113#endif /* CONFIG_USER_SCHED */
119 114
@@ -448,36 +443,6 @@ out_unlock:
448 return NULL; 443 return NULL;
449} 444}
450 445
451void switch_uid(struct user_struct *new_user)
452{
453 struct user_struct *old_user;
454
455 /* What if a process setreuid()'s and this brings the
456 * new uid over his NPROC rlimit? We can check this now
457 * cheaply with the new uid cache, so if it matters
458 * we should be checking for it. -DaveM
459 */
460 old_user = current->cred->user;
461 atomic_inc(&new_user->processes);
462 atomic_dec(&old_user->processes);
463 switch_uid_keyring(new_user);
464 current->cred->user = new_user;
465 sched_switch_user(current);
466
467 /*
468 * We need to synchronize with __sigqueue_alloc()
469 * doing a get_uid(p->user).. If that saw the old
470 * user value, we need to wait until it has exited
471 * its critical region before we can free the old
472 * structure.
473 */
474 smp_mb();
475 spin_unlock_wait(&current->sighand->siglock);
476
477 free_uid(old_user);
478 suid_keys(current);
479}
480
481#ifdef CONFIG_USER_NS 446#ifdef CONFIG_USER_NS
482void release_uids(struct user_namespace *ns) 447void release_uids(struct user_namespace *ns)
483{ 448{
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index f82730adea00..0d9c51d67333 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -19,6 +19,7 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
19{ 19{
20 struct user_namespace *ns; 20 struct user_namespace *ns;
21 struct user_struct *new_user; 21 struct user_struct *new_user;
22 struct cred *new;
22 int n; 23 int n;
23 24
24 ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL); 25 ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL);
@@ -45,7 +46,16 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
45 return ERR_PTR(-ENOMEM); 46 return ERR_PTR(-ENOMEM);
46 } 47 }
47 48
48 switch_uid(new_user); 49 /* Install the new user */
50 new = prepare_creds();
51 if (!new) {
52 free_uid(new_user);
53 free_uid(ns->root_user);
54 kfree(ns);
55 }
56 free_uid(new->user);
57 new->user = new_user;
58 commit_creds(new);
49 return ns; 59 return ns;
50} 60}
51 61