diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:26 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:26 -0500 |
commit | 3b11a1decef07c19443d24ae926982bc8ec9f4c0 (patch) | |
tree | b6555f0e5b07f4b2badd332a0a900b974920c49d /security | |
parent | 98870ab0a5a3f1822aee681d2997017e1c87d026 (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 'security')
-rw-r--r-- | security/selinux/hooks.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 21a592184633..91b06f2aa963 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -161,7 +161,7 @@ static int selinux_secmark_enabled(void) | |||
161 | */ | 161 | */ |
162 | static void cred_init_security(void) | 162 | static void cred_init_security(void) |
163 | { | 163 | { |
164 | struct cred *cred = (struct cred *) current->cred; | 164 | struct cred *cred = (struct cred *) current->real_cred; |
165 | struct task_security_struct *tsec; | 165 | struct task_security_struct *tsec; |
166 | 166 | ||
167 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); | 167 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); |
@@ -184,7 +184,7 @@ static inline u32 cred_sid(const struct cred *cred) | |||
184 | } | 184 | } |
185 | 185 | ||
186 | /* | 186 | /* |
187 | * get the security ID of a task | 187 | * get the objective security ID of a task |
188 | */ | 188 | */ |
189 | static inline u32 task_sid(const struct task_struct *task) | 189 | static inline u32 task_sid(const struct task_struct *task) |
190 | { | 190 | { |
@@ -197,7 +197,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * get the security ID of the current task | 200 | * get the subjective security ID of the current task |
201 | */ | 201 | */ |
202 | static inline u32 current_sid(void) | 202 | static inline u32 current_sid(void) |
203 | { | 203 | { |
@@ -1395,6 +1395,7 @@ static int cred_has_perm(const struct cred *actor, | |||
1395 | * Check permission between a pair of tasks, e.g. signal checks, | 1395 | * Check permission between a pair of tasks, e.g. signal checks, |
1396 | * fork check, ptrace check, etc. | 1396 | * fork check, ptrace check, etc. |
1397 | * tsk1 is the actor and tsk2 is the target | 1397 | * tsk1 is the actor and tsk2 is the target |
1398 | * - this uses the default subjective creds of tsk1 | ||
1398 | */ | 1399 | */ |
1399 | static int task_has_perm(const struct task_struct *tsk1, | 1400 | static int task_has_perm(const struct task_struct *tsk1, |
1400 | const struct task_struct *tsk2, | 1401 | const struct task_struct *tsk2, |
@@ -1410,6 +1411,22 @@ static int task_has_perm(const struct task_struct *tsk1, | |||
1410 | return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL); | 1411 | return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL); |
1411 | } | 1412 | } |
1412 | 1413 | ||
1414 | /* | ||
1415 | * Check permission between current and another task, e.g. signal checks, | ||
1416 | * fork check, ptrace check, etc. | ||
1417 | * current is the actor and tsk2 is the target | ||
1418 | * - this uses current's subjective creds | ||
1419 | */ | ||
1420 | static int current_has_perm(const struct task_struct *tsk, | ||
1421 | u32 perms) | ||
1422 | { | ||
1423 | u32 sid, tsid; | ||
1424 | |||
1425 | sid = current_sid(); | ||
1426 | tsid = task_sid(tsk); | ||
1427 | return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL); | ||
1428 | } | ||
1429 | |||
1413 | #if CAP_LAST_CAP > 63 | 1430 | #if CAP_LAST_CAP > 63 |
1414 | #error Fix SELinux to handle capabilities > 63. | 1431 | #error Fix SELinux to handle capabilities > 63. |
1415 | #endif | 1432 | #endif |
@@ -1807,7 +1824,7 @@ static int selinux_ptrace_may_access(struct task_struct *child, | |||
1807 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); | 1824 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); |
1808 | } | 1825 | } |
1809 | 1826 | ||
1810 | return task_has_perm(current, child, PROCESS__PTRACE); | 1827 | return current_has_perm(child, PROCESS__PTRACE); |
1811 | } | 1828 | } |
1812 | 1829 | ||
1813 | static int selinux_ptrace_traceme(struct task_struct *parent) | 1830 | 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, | |||
1826 | { | 1843 | { |
1827 | int error; | 1844 | int error; |
1828 | 1845 | ||
1829 | error = task_has_perm(current, target, PROCESS__GETCAP); | 1846 | error = current_has_perm(target, PROCESS__GETCAP); |
1830 | if (error) | 1847 | if (error) |
1831 | return error; | 1848 | return error; |
1832 | 1849 | ||
@@ -3071,7 +3088,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3071 | } else if (!vma->vm_file && | 3088 | } else if (!vma->vm_file && |
3072 | vma->vm_start <= vma->vm_mm->start_stack && | 3089 | vma->vm_start <= vma->vm_mm->start_stack && |
3073 | vma->vm_end >= vma->vm_mm->start_stack) { | 3090 | vma->vm_end >= vma->vm_mm->start_stack) { |
3074 | rc = task_has_perm(current, current, PROCESS__EXECSTACK); | 3091 | rc = current_has_perm(current, PROCESS__EXECSTACK); |
3075 | } else if (vma->vm_file && vma->anon_vma) { | 3092 | } else if (vma->vm_file && vma->anon_vma) { |
3076 | /* | 3093 | /* |
3077 | * We are making executable a file mapping that has | 3094 | * We are making executable a file mapping that has |
@@ -3220,7 +3237,7 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3220 | if (rc) | 3237 | if (rc) |
3221 | return rc; | 3238 | return rc; |
3222 | 3239 | ||
3223 | return task_has_perm(current, current, PROCESS__FORK); | 3240 | return current_has_perm(current, PROCESS__FORK); |
3224 | } | 3241 | } |
3225 | 3242 | ||
3226 | /* | 3243 | /* |
@@ -3285,17 +3302,17 @@ static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) | |||
3285 | 3302 | ||
3286 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3303 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3287 | { | 3304 | { |
3288 | return task_has_perm(current, p, PROCESS__SETPGID); | 3305 | return current_has_perm(p, PROCESS__SETPGID); |
3289 | } | 3306 | } |
3290 | 3307 | ||
3291 | static int selinux_task_getpgid(struct task_struct *p) | 3308 | static int selinux_task_getpgid(struct task_struct *p) |
3292 | { | 3309 | { |
3293 | return task_has_perm(current, p, PROCESS__GETPGID); | 3310 | return current_has_perm(p, PROCESS__GETPGID); |
3294 | } | 3311 | } |
3295 | 3312 | ||
3296 | static int selinux_task_getsid(struct task_struct *p) | 3313 | static int selinux_task_getsid(struct task_struct *p) |
3297 | { | 3314 | { |
3298 | return task_has_perm(current, p, PROCESS__GETSESSION); | 3315 | return current_has_perm(p, PROCESS__GETSESSION); |
3299 | } | 3316 | } |
3300 | 3317 | ||
3301 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | 3318 | 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) | |||
3317 | if (rc) | 3334 | if (rc) |
3318 | return rc; | 3335 | return rc; |
3319 | 3336 | ||
3320 | return task_has_perm(current, p, PROCESS__SETSCHED); | 3337 | return current_has_perm(p, PROCESS__SETSCHED); |
3321 | } | 3338 | } |
3322 | 3339 | ||
3323 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) | 3340 | 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) | |||
3328 | if (rc) | 3345 | if (rc) |
3329 | return rc; | 3346 | return rc; |
3330 | 3347 | ||
3331 | return task_has_perm(current, p, PROCESS__SETSCHED); | 3348 | return current_has_perm(p, PROCESS__SETSCHED); |
3332 | } | 3349 | } |
3333 | 3350 | ||
3334 | static int selinux_task_getioprio(struct task_struct *p) | 3351 | static int selinux_task_getioprio(struct task_struct *p) |
3335 | { | 3352 | { |
3336 | return task_has_perm(current, p, PROCESS__GETSCHED); | 3353 | return current_has_perm(p, PROCESS__GETSCHED); |
3337 | } | 3354 | } |
3338 | 3355 | ||
3339 | static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 3356 | 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 | |||
3350 | later be used as a safe reset point for the soft limit | 3367 | later be used as a safe reset point for the soft limit |
3351 | upon context transitions. See selinux_bprm_committing_creds. */ | 3368 | upon context transitions. See selinux_bprm_committing_creds. */ |
3352 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3369 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3353 | return task_has_perm(current, current, PROCESS__SETRLIMIT); | 3370 | return current_has_perm(current, PROCESS__SETRLIMIT); |
3354 | 3371 | ||
3355 | return 0; | 3372 | return 0; |
3356 | } | 3373 | } |
@@ -3363,17 +3380,17 @@ static int selinux_task_setscheduler(struct task_struct *p, int policy, struct s | |||
3363 | if (rc) | 3380 | if (rc) |
3364 | return rc; | 3381 | return rc; |
3365 | 3382 | ||
3366 | return task_has_perm(current, p, PROCESS__SETSCHED); | 3383 | return current_has_perm(p, PROCESS__SETSCHED); |
3367 | } | 3384 | } |
3368 | 3385 | ||
3369 | static int selinux_task_getscheduler(struct task_struct *p) | 3386 | static int selinux_task_getscheduler(struct task_struct *p) |
3370 | { | 3387 | { |
3371 | return task_has_perm(current, p, PROCESS__GETSCHED); | 3388 | return current_has_perm(p, PROCESS__GETSCHED); |
3372 | } | 3389 | } |
3373 | 3390 | ||
3374 | static int selinux_task_movememory(struct task_struct *p) | 3391 | static int selinux_task_movememory(struct task_struct *p) |
3375 | { | 3392 | { |
3376 | return task_has_perm(current, p, PROCESS__SETSCHED); | 3393 | return current_has_perm(p, PROCESS__SETSCHED); |
3377 | } | 3394 | } |
3378 | 3395 | ||
3379 | static int selinux_task_kill(struct task_struct *p, struct siginfo *info, | 3396 | 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, | |||
3394 | rc = avc_has_perm(secid, task_sid(p), | 3411 | rc = avc_has_perm(secid, task_sid(p), |
3395 | SECCLASS_PROCESS, perm, NULL); | 3412 | SECCLASS_PROCESS, perm, NULL); |
3396 | else | 3413 | else |
3397 | rc = task_has_perm(current, p, perm); | 3414 | rc = current_has_perm(p, perm); |
3398 | return rc; | 3415 | return rc; |
3399 | } | 3416 | } |
3400 | 3417 | ||
@@ -5250,7 +5267,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
5250 | unsigned len; | 5267 | unsigned len; |
5251 | 5268 | ||
5252 | if (current != p) { | 5269 | if (current != p) { |
5253 | error = task_has_perm(current, p, PROCESS__GETATTR); | 5270 | error = current_has_perm(p, PROCESS__GETATTR); |
5254 | if (error) | 5271 | if (error) |
5255 | return error; | 5272 | return error; |
5256 | } | 5273 | } |
@@ -5309,15 +5326,15 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5309 | * above restriction is ever removed. | 5326 | * above restriction is ever removed. |
5310 | */ | 5327 | */ |
5311 | if (!strcmp(name, "exec")) | 5328 | if (!strcmp(name, "exec")) |
5312 | error = task_has_perm(current, p, PROCESS__SETEXEC); | 5329 | error = current_has_perm(p, PROCESS__SETEXEC); |
5313 | else if (!strcmp(name, "fscreate")) | 5330 | else if (!strcmp(name, "fscreate")) |
5314 | error = task_has_perm(current, p, PROCESS__SETFSCREATE); | 5331 | error = current_has_perm(p, PROCESS__SETFSCREATE); |
5315 | else if (!strcmp(name, "keycreate")) | 5332 | else if (!strcmp(name, "keycreate")) |
5316 | error = task_has_perm(current, p, PROCESS__SETKEYCREATE); | 5333 | error = current_has_perm(p, PROCESS__SETKEYCREATE); |
5317 | else if (!strcmp(name, "sockcreate")) | 5334 | else if (!strcmp(name, "sockcreate")) |
5318 | error = task_has_perm(current, p, PROCESS__SETSOCKCREATE); | 5335 | error = current_has_perm(p, PROCESS__SETSOCKCREATE); |
5319 | else if (!strcmp(name, "current")) | 5336 | else if (!strcmp(name, "current")) |
5320 | error = task_has_perm(current, p, PROCESS__SETCURRENT); | 5337 | error = current_has_perm(p, PROCESS__SETCURRENT); |
5321 | else | 5338 | else |
5322 | error = -EINVAL; | 5339 | error = -EINVAL; |
5323 | if (error) | 5340 | if (error) |