mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-22 23:04:43 +00:00
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:
parent
98870ab0a5
commit
3b11a1dece
7 changed files with 95 additions and 54 deletions
|
@ -161,7 +161,7 @@ static int selinux_secmark_enabled(void)
|
|||
*/
|
||||
static void cred_init_security(void)
|
||||
{
|
||||
struct cred *cred = (struct cred *) current->cred;
|
||||
struct cred *cred = (struct cred *) current->real_cred;
|
||||
struct task_security_struct *tsec;
|
||||
|
||||
tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
|
||||
|
@ -184,7 +184,7 @@ static inline u32 cred_sid(const struct cred *cred)
|
|||
}
|
||||
|
||||
/*
|
||||
* get the security ID of a task
|
||||
* get the objective security ID of a task
|
||||
*/
|
||||
static inline u32 task_sid(const struct task_struct *task)
|
||||
{
|
||||
|
@ -197,7 +197,7 @@ static inline u32 task_sid(const struct task_struct *task)
|
|||
}
|
||||
|
||||
/*
|
||||
* get the security ID of the current task
|
||||
* get the subjective security ID of the current task
|
||||
*/
|
||||
static inline u32 current_sid(void)
|
||||
{
|
||||
|
@ -1395,6 +1395,7 @@ static int cred_has_perm(const struct cred *actor,
|
|||
* Check permission between a pair of tasks, e.g. signal checks,
|
||||
* fork check, ptrace check, etc.
|
||||
* tsk1 is the actor and tsk2 is the target
|
||||
* - this uses the default subjective creds of tsk1
|
||||
*/
|
||||
static int task_has_perm(const struct task_struct *tsk1,
|
||||
const struct task_struct *tsk2,
|
||||
|
@ -1410,6 +1411,22 @@ static int task_has_perm(const struct task_struct *tsk1,
|
|||
return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check permission between current and another task, e.g. signal checks,
|
||||
* fork check, ptrace check, etc.
|
||||
* current is the actor and tsk2 is the target
|
||||
* - this uses current's subjective creds
|
||||
*/
|
||||
static int current_has_perm(const struct task_struct *tsk,
|
||||
u32 perms)
|
||||
{
|
||||
u32 sid, tsid;
|
||||
|
||||
sid = current_sid();
|
||||
tsid = task_sid(tsk);
|
||||
return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
|
||||
}
|
||||
|
||||
#if CAP_LAST_CAP > 63
|
||||
#error Fix SELinux to handle capabilities > 63.
|
||||
#endif
|
||||
|
@ -1807,7 +1824,7 @@ static int selinux_ptrace_may_access(struct task_struct *child,
|
|||
return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
|
||||
}
|
||||
|
||||
return task_has_perm(current, child, PROCESS__PTRACE);
|
||||
return current_has_perm(child, PROCESS__PTRACE);
|
||||
}
|
||||
|
||||
static int selinux_ptrace_traceme(struct task_struct *parent)
|
||||
|
@ -1826,7 +1843,7 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
|
|||
{
|
||||
int error;
|
||||
|
||||
error = task_has_perm(current, target, PROCESS__GETCAP);
|
||||
error = current_has_perm(target, PROCESS__GETCAP);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -3071,7 +3088,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
|
|||
} else if (!vma->vm_file &&
|
||||
vma->vm_start <= vma->vm_mm->start_stack &&
|
||||
vma->vm_end >= vma->vm_mm->start_stack) {
|
||||
rc = task_has_perm(current, current, PROCESS__EXECSTACK);
|
||||
rc = current_has_perm(current, PROCESS__EXECSTACK);
|
||||
} else if (vma->vm_file && vma->anon_vma) {
|
||||
/*
|
||||
* We are making executable a file mapping that has
|
||||
|
@ -3220,7 +3237,7 @@ static int selinux_task_create(unsigned long clone_flags)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
return task_has_perm(current, current, PROCESS__FORK);
|
||||
return current_has_perm(current, PROCESS__FORK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3285,17 +3302,17 @@ static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
|
|||
|
||||
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
|
||||
{
|
||||
return task_has_perm(current, p, PROCESS__SETPGID);
|
||||
return current_has_perm(p, PROCESS__SETPGID);
|
||||
}
|
||||
|
||||
static int selinux_task_getpgid(struct task_struct *p)
|
||||
{
|
||||
return task_has_perm(current, p, PROCESS__GETPGID);
|
||||
return current_has_perm(p, PROCESS__GETPGID);
|
||||
}
|
||||
|
||||
static int selinux_task_getsid(struct task_struct *p)
|
||||
{
|
||||
return task_has_perm(current, p, PROCESS__GETSESSION);
|
||||
return current_has_perm(p, PROCESS__GETSESSION);
|
||||
}
|
||||
|
||||
static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
|
||||
|
@ -3317,7 +3334,7 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
return task_has_perm(current, p, PROCESS__SETSCHED);
|
||||
return current_has_perm(p, PROCESS__SETSCHED);
|
||||
}
|
||||
|
||||
static int selinux_task_setioprio(struct task_struct *p, int ioprio)
|
||||
|
@ -3328,12 +3345,12 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
return task_has_perm(current, p, PROCESS__SETSCHED);
|
||||
return current_has_perm(p, PROCESS__SETSCHED);
|
||||
}
|
||||
|
||||
static int selinux_task_getioprio(struct task_struct *p)
|
||||
{
|
||||
return task_has_perm(current, p, PROCESS__GETSCHED);
|
||||
return current_has_perm(p, PROCESS__GETSCHED);
|
||||
}
|
||||
|
||||
static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
|
||||
|
@ -3350,7 +3367,7 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim
|
|||
later be used as a safe reset point for the soft limit
|
||||
upon context transitions. See selinux_bprm_committing_creds. */
|
||||
if (old_rlim->rlim_max != new_rlim->rlim_max)
|
||||
return task_has_perm(current, current, PROCESS__SETRLIMIT);
|
||||
return current_has_perm(current, PROCESS__SETRLIMIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3363,17 +3380,17 @@ static int selinux_task_setscheduler(struct task_struct *p, int policy, struct s
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
return task_has_perm(current, p, PROCESS__SETSCHED);
|
||||
return current_has_perm(p, PROCESS__SETSCHED);
|
||||
}
|
||||
|
||||
static int selinux_task_getscheduler(struct task_struct *p)
|
||||
{
|
||||
return task_has_perm(current, p, PROCESS__GETSCHED);
|
||||
return current_has_perm(p, PROCESS__GETSCHED);
|
||||
}
|
||||
|
||||
static int selinux_task_movememory(struct task_struct *p)
|
||||
{
|
||||
return task_has_perm(current, p, PROCESS__SETSCHED);
|
||||
return current_has_perm(p, PROCESS__SETSCHED);
|
||||
}
|
||||
|
||||
static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
|
||||
|
@ -3394,7 +3411,7 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
|
|||
rc = avc_has_perm(secid, task_sid(p),
|
||||
SECCLASS_PROCESS, perm, NULL);
|
||||
else
|
||||
rc = task_has_perm(current, p, perm);
|
||||
rc = current_has_perm(p, perm);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -5250,7 +5267,7 @@ static int selinux_getprocattr(struct task_struct *p,
|
|||
unsigned len;
|
||||
|
||||
if (current != p) {
|
||||
error = task_has_perm(current, p, PROCESS__GETATTR);
|
||||
error = current_has_perm(p, PROCESS__GETATTR);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
@ -5309,15 +5326,15 @@ static int selinux_setprocattr(struct task_struct *p,
|
|||
* above restriction is ever removed.
|
||||
*/
|
||||
if (!strcmp(name, "exec"))
|
||||
error = task_has_perm(current, p, PROCESS__SETEXEC);
|
||||
error = current_has_perm(p, PROCESS__SETEXEC);
|
||||
else if (!strcmp(name, "fscreate"))
|
||||
error = task_has_perm(current, p, PROCESS__SETFSCREATE);
|
||||
error = current_has_perm(p, PROCESS__SETFSCREATE);
|
||||
else if (!strcmp(name, "keycreate"))
|
||||
error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
|
||||
error = current_has_perm(p, PROCESS__SETKEYCREATE);
|
||||
else if (!strcmp(name, "sockcreate"))
|
||||
error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
|
||||
error = current_has_perm(p, PROCESS__SETSOCKCREATE);
|
||||
else if (!strcmp(name, "current"))
|
||||
error = task_has_perm(current, p, PROCESS__SETCURRENT);
|
||||
error = current_has_perm(p, PROCESS__SETCURRENT);
|
||||
else
|
||||
error = -EINVAL;
|
||||
if (error)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue