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>
This commit is contained in:
committed by
James Morris
parent
98870ab0a5
commit
3b11a1dece
@@ -35,7 +35,7 @@ static struct thread_group_cred init_tgcred = {
|
||||
* The initial credentials for the initial task
|
||||
*/
|
||||
struct cred init_cred = {
|
||||
.usage = ATOMIC_INIT(3),
|
||||
.usage = ATOMIC_INIT(4),
|
||||
.securebits = SECUREBITS_DEFAULT,
|
||||
.cap_inheritable = CAP_INIT_INH_SET,
|
||||
.cap_permitted = CAP_FULL_SET,
|
||||
@@ -120,6 +120,8 @@ EXPORT_SYMBOL(__put_cred);
|
||||
* prepare a new copy, which the caller then modifies and then commits by
|
||||
* calling commit_creds().
|
||||
*
|
||||
* Preparation involves making a copy of the objective creds for modification.
|
||||
*
|
||||
* Returns a pointer to the new creds-to-be if successful, NULL otherwise.
|
||||
*
|
||||
* Call commit_creds() or abort_creds() to clean up.
|
||||
@@ -130,7 +132,7 @@ struct cred *prepare_creds(void)
|
||||
const struct cred *old;
|
||||
struct cred *new;
|
||||
|
||||
BUG_ON(atomic_read(&task->cred->usage) < 1);
|
||||
BUG_ON(atomic_read(&task->real_cred->usage) < 1);
|
||||
|
||||
new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
|
||||
if (!new)
|
||||
@@ -262,6 +264,9 @@ error:
|
||||
*
|
||||
* We share if we can, but under some circumstances we have to generate a new
|
||||
* set.
|
||||
*
|
||||
* The new process gets the current process's subjective credentials as its
|
||||
* objective and subjective credentials
|
||||
*/
|
||||
int copy_creds(struct task_struct *p, unsigned long clone_flags)
|
||||
{
|
||||
@@ -278,6 +283,7 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
|
||||
#endif
|
||||
clone_flags & CLONE_THREAD
|
||||
) {
|
||||
p->real_cred = get_cred(p->cred);
|
||||
get_cred(p->cred);
|
||||
atomic_inc(&p->cred->user->processes);
|
||||
return 0;
|
||||
@@ -317,7 +323,7 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
|
||||
#endif
|
||||
|
||||
atomic_inc(&new->user->processes);
|
||||
p->cred = new;
|
||||
p->cred = p->real_cred = get_cred(new);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -326,7 +332,9 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
|
||||
* @new: The credentials to be assigned
|
||||
*
|
||||
* Install a new set of credentials to the current task, using RCU to replace
|
||||
* the old set.
|
||||
* the old set. Both the objective and the subjective credentials pointers are
|
||||
* updated. This function may not be called if the subjective credentials are
|
||||
* in an overridden state.
|
||||
*
|
||||
* This function eats the caller's reference to the new credentials.
|
||||
*
|
||||
@@ -338,12 +346,15 @@ int commit_creds(struct cred *new)
|
||||
struct task_struct *task = current;
|
||||
const struct cred *old;
|
||||
|
||||
BUG_ON(task->cred != task->real_cred);
|
||||
BUG_ON(atomic_read(&task->real_cred->usage) < 2);
|
||||
BUG_ON(atomic_read(&new->usage) < 1);
|
||||
BUG_ON(atomic_read(&task->cred->usage) < 1);
|
||||
|
||||
old = task->cred;
|
||||
old = task->real_cred;
|
||||
security_commit_creds(new, old);
|
||||
|
||||
get_cred(new); /* we will require a ref for the subj creds too */
|
||||
|
||||
/* dumpability changes */
|
||||
if (old->euid != new->euid ||
|
||||
old->egid != new->egid ||
|
||||
@@ -369,6 +380,7 @@ int commit_creds(struct cred *new)
|
||||
*/
|
||||
if (new->user != old->user)
|
||||
atomic_inc(&new->user->processes);
|
||||
rcu_assign_pointer(task->real_cred, new);
|
||||
rcu_assign_pointer(task->cred, new);
|
||||
if (new->user != old->user)
|
||||
atomic_dec(&old->user->processes);
|
||||
@@ -388,6 +400,8 @@ int commit_creds(struct cred *new)
|
||||
new->fsgid != old->fsgid)
|
||||
proc_id_connector(task, PROC_EVENT_GID);
|
||||
|
||||
/* release the old obj and subj refs both */
|
||||
put_cred(old);
|
||||
put_cred(old);
|
||||
return 0;
|
||||
}
|
||||
@@ -408,11 +422,11 @@ void abort_creds(struct cred *new)
|
||||
EXPORT_SYMBOL(abort_creds);
|
||||
|
||||
/**
|
||||
* override_creds - Temporarily override the current process's credentials
|
||||
* override_creds - Override the current process's subjective credentials
|
||||
* @new: The credentials to be assigned
|
||||
*
|
||||
* Install a set of temporary override credentials on the current process,
|
||||
* returning the old set for later reversion.
|
||||
* Install a set of temporary override subjective credentials on the current
|
||||
* process, returning the old set for later reversion.
|
||||
*/
|
||||
const struct cred *override_creds(const struct cred *new)
|
||||
{
|
||||
@@ -424,11 +438,11 @@ const struct cred *override_creds(const struct cred *new)
|
||||
EXPORT_SYMBOL(override_creds);
|
||||
|
||||
/**
|
||||
* revert_creds - Revert a temporary credentials override
|
||||
* revert_creds - Revert a temporary subjective credentials override
|
||||
* @old: The credentials to be restored
|
||||
*
|
||||
* Revert a temporary set of override credentials to an old set, discarding the
|
||||
* override set.
|
||||
* Revert a temporary set of override subjective credentials to an old set,
|
||||
* discarding the override set.
|
||||
*/
|
||||
void revert_creds(const struct cred *old)
|
||||
{
|
||||
|
Reference in New Issue
Block a user