aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:26 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:26 -0500
commit3b11a1decef07c19443d24ae926982bc8ec9f4c0 (patch)
treeb6555f0e5b07f4b2badd332a0a900b974920c49d /kernel/fork.c
parent98870ab0a5a3f1822aee681d2997017e1c87d026 (diff)
CRED: Differentiate objective and effective subjective credentials on a task
Differentiate the objective and real subjective credentials from the effective subjective credentials on a task by introducing a second credentials pointer into the task_struct. task_struct::real_cred then refers to the objective and apparent real subjective credentials of a task, as perceived by the other tasks in the system. task_struct::cred then refers to the effective subjective credentials of a task, as used by that task when it's actually running. These are not visible to the other tasks in the system. __task_cred(task) then refers to the objective/real credentials of the task in question. current_cred() refers to the effective subjective credentials of the current task. prepare_creds() uses the objective creds as a base and commit_creds() changes both pointers in the task_struct (indeed commit_creds() requires them to be the same). override_creds() and revert_creds() change the subjective creds pointer only, and the former returns the old subjective creds. These are used by NFSD, faccessat() and do_coredump(), and will by used by CacheFiles. In SELinux, current_has_perm() is provided as an alternative to task_has_perm(). This uses the effective subjective context of current, whereas task_has_perm() uses the objective/real context of the subject. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 82a7948a664e..af0d0f04585c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -146,6 +146,7 @@ void __put_task_struct(struct task_struct *tsk)
146 WARN_ON(atomic_read(&tsk->usage)); 146 WARN_ON(atomic_read(&tsk->usage));
147 WARN_ON(tsk == current); 147 WARN_ON(tsk == current);
148 148
149 put_cred(tsk->real_cred);
149 put_cred(tsk->cred); 150 put_cred(tsk->cred);
150 delayacct_tsk_free(tsk); 151 delayacct_tsk_free(tsk);
151 152
@@ -961,10 +962,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
961 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); 962 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
962#endif 963#endif
963 retval = -EAGAIN; 964 retval = -EAGAIN;
964 if (atomic_read(&p->cred->user->processes) >= 965 if (atomic_read(&p->real_cred->user->processes) >=
965 p->signal->rlim[RLIMIT_NPROC].rlim_cur) { 966 p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
966 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && 967 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
967 p->cred->user != current->nsproxy->user_ns->root_user) 968 p->real_cred->user != current->nsproxy->user_ns->root_user)
968 goto bad_fork_free; 969 goto bad_fork_free;
969 } 970 }
970 971
@@ -1278,6 +1279,7 @@ bad_fork_cleanup_put_domain:
1278 module_put(task_thread_info(p)->exec_domain->module); 1279 module_put(task_thread_info(p)->exec_domain->module);
1279bad_fork_cleanup_count: 1280bad_fork_cleanup_count:
1280 atomic_dec(&p->cred->user->processes); 1281 atomic_dec(&p->cred->user->processes);
1282 put_cred(p->real_cred);
1281 put_cred(p->cred); 1283 put_cred(p->cred);
1282bad_fork_free: 1284bad_fork_free:
1283 free_task(p); 1285 free_task(p);