diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/hooks.c | 286 |
1 files changed, 140 insertions, 146 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f20cbd681ba6..c71bba78872f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -156,20 +156,20 @@ static int selinux_secmark_enabled(void) | |||
156 | return (atomic_read(&selinux_secmark_refcount) > 0); | 156 | return (atomic_read(&selinux_secmark_refcount) > 0); |
157 | } | 157 | } |
158 | 158 | ||
159 | /* Allocate and free functions for each kind of security blob. */ | 159 | /* |
160 | 160 | * initialise the security for the init task | |
161 | static int cred_alloc_security(struct cred *cred) | 161 | */ |
162 | static void cred_init_security(void) | ||
162 | { | 163 | { |
164 | struct cred *cred = (struct cred *) current->cred; | ||
163 | struct task_security_struct *tsec; | 165 | struct task_security_struct *tsec; |
164 | 166 | ||
165 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); | 167 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); |
166 | if (!tsec) | 168 | if (!tsec) |
167 | return -ENOMEM; | 169 | panic("SELinux: Failed to initialize initial task.\n"); |
168 | 170 | ||
169 | tsec->osid = tsec->sid = SECINITSID_UNLABELED; | 171 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
170 | cred->security = tsec; | 172 | cred->security = tsec; |
171 | |||
172 | return 0; | ||
173 | } | 173 | } |
174 | 174 | ||
175 | /* | 175 | /* |
@@ -1379,6 +1379,19 @@ static inline u32 signal_to_av(int sig) | |||
1379 | } | 1379 | } |
1380 | 1380 | ||
1381 | /* | 1381 | /* |
1382 | * Check permission between a pair of credentials | ||
1383 | * fork check, ptrace check, etc. | ||
1384 | */ | ||
1385 | static int cred_has_perm(const struct cred *actor, | ||
1386 | const struct cred *target, | ||
1387 | u32 perms) | ||
1388 | { | ||
1389 | u32 asid = cred_sid(actor), tsid = cred_sid(target); | ||
1390 | |||
1391 | return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL); | ||
1392 | } | ||
1393 | |||
1394 | /* | ||
1382 | * Check permission between a pair of tasks, e.g. signal checks, | 1395 | * Check permission between a pair of tasks, e.g. signal checks, |
1383 | * fork check, ptrace check, etc. | 1396 | * fork check, ptrace check, etc. |
1384 | * tsk1 is the actor and tsk2 is the target | 1397 | * tsk1 is the actor and tsk2 is the target |
@@ -1820,24 +1833,19 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | |||
1820 | return secondary_ops->capget(target, effective, inheritable, permitted); | 1833 | return secondary_ops->capget(target, effective, inheritable, permitted); |
1821 | } | 1834 | } |
1822 | 1835 | ||
1823 | static int selinux_capset_check(const kernel_cap_t *effective, | 1836 | static int selinux_capset(struct cred *new, const struct cred *old, |
1824 | const kernel_cap_t *inheritable, | 1837 | const kernel_cap_t *effective, |
1825 | const kernel_cap_t *permitted) | 1838 | const kernel_cap_t *inheritable, |
1839 | const kernel_cap_t *permitted) | ||
1826 | { | 1840 | { |
1827 | int error; | 1841 | int error; |
1828 | 1842 | ||
1829 | error = secondary_ops->capset_check(effective, inheritable, permitted); | 1843 | error = secondary_ops->capset(new, old, |
1844 | effective, inheritable, permitted); | ||
1830 | if (error) | 1845 | if (error) |
1831 | return error; | 1846 | return error; |
1832 | 1847 | ||
1833 | return task_has_perm(current, current, PROCESS__SETCAP); | 1848 | return cred_has_perm(old, new, PROCESS__SETCAP); |
1834 | } | ||
1835 | |||
1836 | static void selinux_capset_set(const kernel_cap_t *effective, | ||
1837 | const kernel_cap_t *inheritable, | ||
1838 | const kernel_cap_t *permitted) | ||
1839 | { | ||
1840 | secondary_ops->capset_set(effective, inheritable, permitted); | ||
1841 | } | 1849 | } |
1842 | 1850 | ||
1843 | static int selinux_capable(struct task_struct *tsk, int cap, int audit) | 1851 | static int selinux_capable(struct task_struct *tsk, int cap, int audit) |
@@ -2244,16 +2252,23 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2244 | spin_unlock(&files->file_lock); | 2252 | spin_unlock(&files->file_lock); |
2245 | } | 2253 | } |
2246 | 2254 | ||
2247 | static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | 2255 | static int selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) |
2248 | { | 2256 | { |
2249 | struct task_security_struct *tsec; | 2257 | struct task_security_struct *tsec; |
2250 | struct bprm_security_struct *bsec; | 2258 | struct bprm_security_struct *bsec; |
2259 | struct cred *new; | ||
2251 | u32 sid; | 2260 | u32 sid; |
2252 | int rc; | 2261 | int rc; |
2253 | 2262 | ||
2254 | secondary_ops->bprm_apply_creds(bprm, unsafe); | 2263 | rc = secondary_ops->bprm_apply_creds(bprm, unsafe); |
2264 | if (rc < 0) | ||
2265 | return rc; | ||
2255 | 2266 | ||
2256 | tsec = current_security(); | 2267 | new = prepare_creds(); |
2268 | if (!new) | ||
2269 | return -ENOMEM; | ||
2270 | |||
2271 | tsec = new->security; | ||
2257 | 2272 | ||
2258 | bsec = bprm->security; | 2273 | bsec = bprm->security; |
2259 | sid = bsec->sid; | 2274 | sid = bsec->sid; |
@@ -2268,7 +2283,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | |||
2268 | PROCESS__SHARE, NULL); | 2283 | PROCESS__SHARE, NULL); |
2269 | if (rc) { | 2284 | if (rc) { |
2270 | bsec->unsafe = 1; | 2285 | bsec->unsafe = 1; |
2271 | return; | 2286 | goto out; |
2272 | } | 2287 | } |
2273 | } | 2288 | } |
2274 | 2289 | ||
@@ -2292,12 +2307,16 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | |||
2292 | PROCESS__PTRACE, NULL); | 2307 | PROCESS__PTRACE, NULL); |
2293 | if (rc) { | 2308 | if (rc) { |
2294 | bsec->unsafe = 1; | 2309 | bsec->unsafe = 1; |
2295 | return; | 2310 | goto out; |
2296 | } | 2311 | } |
2297 | } | 2312 | } |
2298 | } | 2313 | } |
2299 | tsec->sid = sid; | 2314 | tsec->sid = sid; |
2300 | } | 2315 | } |
2316 | |||
2317 | out: | ||
2318 | commit_creds(new); | ||
2319 | return 0; | ||
2301 | } | 2320 | } |
2302 | 2321 | ||
2303 | /* | 2322 | /* |
@@ -3021,6 +3040,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
3021 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 3040 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
3022 | { | 3041 | { |
3023 | const struct cred *cred = current_cred(); | 3042 | const struct cred *cred = current_cred(); |
3043 | int rc = 0; | ||
3024 | 3044 | ||
3025 | #ifndef CONFIG_PPC32 | 3045 | #ifndef CONFIG_PPC32 |
3026 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 3046 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
@@ -3029,9 +3049,9 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3029 | * private file mapping that will also be writable. | 3049 | * private file mapping that will also be writable. |
3030 | * This has an additional check. | 3050 | * This has an additional check. |
3031 | */ | 3051 | */ |
3032 | int rc = task_has_perm(current, current, PROCESS__EXECMEM); | 3052 | rc = cred_has_perm(cred, cred, PROCESS__EXECMEM); |
3033 | if (rc) | 3053 | if (rc) |
3034 | return rc; | 3054 | goto error; |
3035 | } | 3055 | } |
3036 | #endif | 3056 | #endif |
3037 | 3057 | ||
@@ -3048,7 +3068,9 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3048 | 3068 | ||
3049 | return file_has_perm(cred, file, av); | 3069 | return file_has_perm(cred, file, av); |
3050 | } | 3070 | } |
3051 | return 0; | 3071 | |
3072 | error: | ||
3073 | return rc; | ||
3052 | } | 3074 | } |
3053 | 3075 | ||
3054 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, | 3076 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, |
@@ -3090,8 +3112,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3090 | rc = 0; | 3112 | rc = 0; |
3091 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3113 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3092 | vma->vm_end <= vma->vm_mm->brk) { | 3114 | vma->vm_end <= vma->vm_mm->brk) { |
3093 | rc = task_has_perm(current, current, | 3115 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); |
3094 | PROCESS__EXECHEAP); | ||
3095 | } else if (!vma->vm_file && | 3116 | } else if (!vma->vm_file && |
3096 | vma->vm_start <= vma->vm_mm->start_stack && | 3117 | vma->vm_start <= vma->vm_mm->start_stack && |
3097 | vma->vm_end >= vma->vm_mm->start_stack) { | 3118 | vma->vm_end >= vma->vm_mm->start_stack) { |
@@ -3104,8 +3125,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3104 | * modified content. This typically should only | 3125 | * modified content. This typically should only |
3105 | * occur for text relocations. | 3126 | * occur for text relocations. |
3106 | */ | 3127 | */ |
3107 | rc = file_has_perm(cred, vma->vm_file, | 3128 | rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD); |
3108 | FILE__EXECMOD); | ||
3109 | } | 3129 | } |
3110 | if (rc) | 3130 | if (rc) |
3111 | return rc; | 3131 | return rc; |
@@ -3211,6 +3231,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) | |||
3211 | struct file_security_struct *fsec; | 3231 | struct file_security_struct *fsec; |
3212 | struct inode *inode; | 3232 | struct inode *inode; |
3213 | struct inode_security_struct *isec; | 3233 | struct inode_security_struct *isec; |
3234 | |||
3214 | inode = file->f_path.dentry->d_inode; | 3235 | inode = file->f_path.dentry->d_inode; |
3215 | fsec = file->f_security; | 3236 | fsec = file->f_security; |
3216 | isec = inode->i_security; | 3237 | isec = inode->i_security; |
@@ -3247,38 +3268,41 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3247 | return task_has_perm(current, current, PROCESS__FORK); | 3268 | return task_has_perm(current, current, PROCESS__FORK); |
3248 | } | 3269 | } |
3249 | 3270 | ||
3250 | static int selinux_cred_alloc_security(struct cred *cred) | 3271 | /* |
3272 | * detach and free the LSM part of a set of credentials | ||
3273 | */ | ||
3274 | static void selinux_cred_free(struct cred *cred) | ||
3251 | { | 3275 | { |
3252 | struct task_security_struct *tsec1, *tsec2; | 3276 | struct task_security_struct *tsec = cred->security; |
3253 | int rc; | 3277 | cred->security = NULL; |
3254 | 3278 | kfree(tsec); | |
3255 | tsec1 = current_security(); | 3279 | } |
3256 | 3280 | ||
3257 | rc = cred_alloc_security(cred); | 3281 | /* |
3258 | if (rc) | 3282 | * prepare a new set of credentials for modification |
3259 | return rc; | 3283 | */ |
3260 | tsec2 = cred->security; | 3284 | static int selinux_cred_prepare(struct cred *new, const struct cred *old, |
3285 | gfp_t gfp) | ||
3286 | { | ||
3287 | const struct task_security_struct *old_tsec; | ||
3288 | struct task_security_struct *tsec; | ||
3261 | 3289 | ||
3262 | tsec2->osid = tsec1->osid; | 3290 | old_tsec = old->security; |
3263 | tsec2->sid = tsec1->sid; | ||
3264 | 3291 | ||
3265 | /* Retain the exec, fs, key, and sock SIDs across fork */ | 3292 | tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp); |
3266 | tsec2->exec_sid = tsec1->exec_sid; | 3293 | if (!tsec) |
3267 | tsec2->create_sid = tsec1->create_sid; | 3294 | return -ENOMEM; |
3268 | tsec2->keycreate_sid = tsec1->keycreate_sid; | ||
3269 | tsec2->sockcreate_sid = tsec1->sockcreate_sid; | ||
3270 | 3295 | ||
3296 | new->security = tsec; | ||
3271 | return 0; | 3297 | return 0; |
3272 | } | 3298 | } |
3273 | 3299 | ||
3274 | /* | 3300 | /* |
3275 | * detach and free the LSM part of a set of credentials | 3301 | * commit new credentials |
3276 | */ | 3302 | */ |
3277 | static void selinux_cred_free(struct cred *cred) | 3303 | static void selinux_cred_commit(struct cred *new, const struct cred *old) |
3278 | { | 3304 | { |
3279 | struct task_security_struct *tsec = cred->security; | 3305 | secondary_ops->cred_commit(new, old); |
3280 | cred->security = NULL; | ||
3281 | kfree(tsec); | ||
3282 | } | 3306 | } |
3283 | 3307 | ||
3284 | static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 3308 | static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
@@ -3292,9 +3316,10 @@ static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | |||
3292 | return 0; | 3316 | return 0; |
3293 | } | 3317 | } |
3294 | 3318 | ||
3295 | static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 3319 | static int selinux_task_fix_setuid(struct cred *new, const struct cred *old, |
3320 | int flags) | ||
3296 | { | 3321 | { |
3297 | return secondary_ops->task_post_setuid(id0, id1, id2, flags); | 3322 | return secondary_ops->task_fix_setuid(new, old, flags); |
3298 | } | 3323 | } |
3299 | 3324 | ||
3300 | static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) | 3325 | static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) |
@@ -3368,7 +3393,7 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim | |||
3368 | /* Control the ability to change the hard limit (whether | 3393 | /* Control the ability to change the hard limit (whether |
3369 | lowering or raising it), so that the hard limit can | 3394 | lowering or raising it), so that the hard limit can |
3370 | later be used as a safe reset point for the soft limit | 3395 | later be used as a safe reset point for the soft limit |
3371 | upon context transitions. See selinux_bprm_apply_creds. */ | 3396 | upon context transitions. See selinux_bprm_committing_creds. */ |
3372 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3397 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3373 | return task_has_perm(current, current, PROCESS__SETRLIMIT); | 3398 | return task_has_perm(current, current, PROCESS__SETRLIMIT); |
3374 | 3399 | ||
@@ -3422,13 +3447,12 @@ static int selinux_task_prctl(int option, | |||
3422 | unsigned long arg2, | 3447 | unsigned long arg2, |
3423 | unsigned long arg3, | 3448 | unsigned long arg3, |
3424 | unsigned long arg4, | 3449 | unsigned long arg4, |
3425 | unsigned long arg5, | 3450 | unsigned long arg5) |
3426 | long *rc_p) | ||
3427 | { | 3451 | { |
3428 | /* The current prctl operations do not appear to require | 3452 | /* The current prctl operations do not appear to require |
3429 | any SELinux controls since they merely observe or modify | 3453 | any SELinux controls since they merely observe or modify |
3430 | the state of the current process. */ | 3454 | the state of the current process. */ |
3431 | return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p); | 3455 | return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5); |
3432 | } | 3456 | } |
3433 | 3457 | ||
3434 | static int selinux_task_wait(struct task_struct *p) | 3458 | static int selinux_task_wait(struct task_struct *p) |
@@ -3436,18 +3460,6 @@ static int selinux_task_wait(struct task_struct *p) | |||
3436 | return task_has_perm(p, current, PROCESS__SIGCHLD); | 3460 | return task_has_perm(p, current, PROCESS__SIGCHLD); |
3437 | } | 3461 | } |
3438 | 3462 | ||
3439 | static void selinux_task_reparent_to_init(struct task_struct *p) | ||
3440 | { | ||
3441 | struct task_security_struct *tsec; | ||
3442 | |||
3443 | secondary_ops->task_reparent_to_init(p); | ||
3444 | |||
3445 | tsec = p->cred->security; | ||
3446 | tsec->osid = tsec->sid; | ||
3447 | tsec->sid = SECINITSID_KERNEL; | ||
3448 | return; | ||
3449 | } | ||
3450 | |||
3451 | static void selinux_task_to_inode(struct task_struct *p, | 3463 | static void selinux_task_to_inode(struct task_struct *p, |
3452 | struct inode *inode) | 3464 | struct inode *inode) |
3453 | { | 3465 | { |
@@ -5325,7 +5337,8 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5325 | { | 5337 | { |
5326 | struct task_security_struct *tsec; | 5338 | struct task_security_struct *tsec; |
5327 | struct task_struct *tracer; | 5339 | struct task_struct *tracer; |
5328 | u32 sid = 0; | 5340 | struct cred *new; |
5341 | u32 sid = 0, ptsid; | ||
5329 | int error; | 5342 | int error; |
5330 | char *str = value; | 5343 | char *str = value; |
5331 | 5344 | ||
@@ -5372,86 +5385,75 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5372 | return error; | 5385 | return error; |
5373 | } | 5386 | } |
5374 | 5387 | ||
5388 | new = prepare_creds(); | ||
5389 | if (!new) | ||
5390 | return -ENOMEM; | ||
5391 | |||
5375 | /* Permission checking based on the specified context is | 5392 | /* Permission checking based on the specified context is |
5376 | performed during the actual operation (execve, | 5393 | performed during the actual operation (execve, |
5377 | open/mkdir/...), when we know the full context of the | 5394 | open/mkdir/...), when we know the full context of the |
5378 | operation. See selinux_bprm_set_security for the execve | 5395 | operation. See selinux_bprm_set_creds for the execve |
5379 | checks and may_create for the file creation checks. The | 5396 | checks and may_create for the file creation checks. The |
5380 | operation will then fail if the context is not permitted. */ | 5397 | operation will then fail if the context is not permitted. */ |
5381 | tsec = p->cred->security; | 5398 | tsec = new->security; |
5382 | if (!strcmp(name, "exec")) | 5399 | if (!strcmp(name, "exec")) { |
5383 | tsec->exec_sid = sid; | 5400 | tsec->exec_sid = sid; |
5384 | else if (!strcmp(name, "fscreate")) | 5401 | } else if (!strcmp(name, "fscreate")) { |
5385 | tsec->create_sid = sid; | 5402 | tsec->create_sid = sid; |
5386 | else if (!strcmp(name, "keycreate")) { | 5403 | } else if (!strcmp(name, "keycreate")) { |
5387 | error = may_create_key(sid, p); | 5404 | error = may_create_key(sid, p); |
5388 | if (error) | 5405 | if (error) |
5389 | return error; | 5406 | goto abort_change; |
5390 | tsec->keycreate_sid = sid; | 5407 | tsec->keycreate_sid = sid; |
5391 | } else if (!strcmp(name, "sockcreate")) | 5408 | } else if (!strcmp(name, "sockcreate")) { |
5392 | tsec->sockcreate_sid = sid; | 5409 | tsec->sockcreate_sid = sid; |
5393 | else if (!strcmp(name, "current")) { | 5410 | } else if (!strcmp(name, "current")) { |
5394 | struct av_decision avd; | 5411 | error = -EINVAL; |
5395 | |||
5396 | if (sid == 0) | 5412 | if (sid == 0) |
5397 | return -EINVAL; | 5413 | goto abort_change; |
5398 | /* | 5414 | |
5399 | * SELinux allows to change context in the following case only. | 5415 | /* Only allow single threaded processes to change context */ |
5400 | * - Single threaded processes. | 5416 | error = -EPERM; |
5401 | * - Multi threaded processes intend to change its context into | 5417 | if (!is_single_threaded(p)) { |
5402 | * more restricted domain (defined by TYPEBOUNDS statement). | 5418 | error = security_bounded_transition(tsec->sid, sid); |
5403 | */ | 5419 | if (error) |
5404 | if (atomic_read(&p->mm->mm_users) != 1) { | 5420 | goto abort_change; |
5405 | struct task_struct *g, *t; | ||
5406 | struct mm_struct *mm = p->mm; | ||
5407 | read_lock(&tasklist_lock); | ||
5408 | do_each_thread(g, t) { | ||
5409 | if (t->mm == mm && t != p) { | ||
5410 | read_unlock(&tasklist_lock); | ||
5411 | error = security_bounded_transition(tsec->sid, sid); | ||
5412 | if (!error) | ||
5413 | goto boundary_ok; | ||
5414 | |||
5415 | return error; | ||
5416 | } | ||
5417 | } while_each_thread(g, t); | ||
5418 | read_unlock(&tasklist_lock); | ||
5419 | } | 5421 | } |
5420 | boundary_ok: | ||
5421 | 5422 | ||
5422 | /* Check permissions for the transition. */ | 5423 | /* Check permissions for the transition. */ |
5423 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 5424 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, |
5424 | PROCESS__DYNTRANSITION, NULL); | 5425 | PROCESS__DYNTRANSITION, NULL); |
5425 | if (error) | 5426 | if (error) |
5426 | return error; | 5427 | goto abort_change; |
5427 | 5428 | ||
5428 | /* Check for ptracing, and update the task SID if ok. | 5429 | /* Check for ptracing, and update the task SID if ok. |
5429 | Otherwise, leave SID unchanged and fail. */ | 5430 | Otherwise, leave SID unchanged and fail. */ |
5431 | ptsid = 0; | ||
5430 | task_lock(p); | 5432 | task_lock(p); |
5431 | rcu_read_lock(); | ||
5432 | tracer = tracehook_tracer_task(p); | 5433 | tracer = tracehook_tracer_task(p); |
5433 | if (tracer != NULL) { | 5434 | if (tracer) |
5434 | u32 ptsid = task_sid(tracer); | 5435 | ptsid = task_sid(tracer); |
5435 | rcu_read_unlock(); | 5436 | task_unlock(p); |
5436 | error = avc_has_perm_noaudit(ptsid, sid, | 5437 | |
5437 | SECCLASS_PROCESS, | 5438 | if (tracer) { |
5438 | PROCESS__PTRACE, 0, &avd); | 5439 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
5439 | if (!error) | 5440 | PROCESS__PTRACE, NULL); |
5440 | tsec->sid = sid; | ||
5441 | task_unlock(p); | ||
5442 | avc_audit(ptsid, sid, SECCLASS_PROCESS, | ||
5443 | PROCESS__PTRACE, &avd, error, NULL); | ||
5444 | if (error) | 5441 | if (error) |
5445 | return error; | 5442 | goto abort_change; |
5446 | } else { | ||
5447 | rcu_read_unlock(); | ||
5448 | tsec->sid = sid; | ||
5449 | task_unlock(p); | ||
5450 | } | 5443 | } |
5451 | } else | ||
5452 | return -EINVAL; | ||
5453 | 5444 | ||
5445 | tsec->sid = sid; | ||
5446 | } else { | ||
5447 | error = -EINVAL; | ||
5448 | goto abort_change; | ||
5449 | } | ||
5450 | |||
5451 | commit_creds(new); | ||
5454 | return size; | 5452 | return size; |
5453 | |||
5454 | abort_change: | ||
5455 | abort_creds(new); | ||
5456 | return error; | ||
5455 | } | 5457 | } |
5456 | 5458 | ||
5457 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5459 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
@@ -5471,23 +5473,21 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5471 | 5473 | ||
5472 | #ifdef CONFIG_KEYS | 5474 | #ifdef CONFIG_KEYS |
5473 | 5475 | ||
5474 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk, | 5476 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
5475 | unsigned long flags) | 5477 | unsigned long flags) |
5476 | { | 5478 | { |
5477 | const struct task_security_struct *__tsec; | 5479 | const struct task_security_struct *tsec; |
5478 | struct key_security_struct *ksec; | 5480 | struct key_security_struct *ksec; |
5479 | 5481 | ||
5480 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); | 5482 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); |
5481 | if (!ksec) | 5483 | if (!ksec) |
5482 | return -ENOMEM; | 5484 | return -ENOMEM; |
5483 | 5485 | ||
5484 | rcu_read_lock(); | 5486 | tsec = cred->security; |
5485 | __tsec = __task_cred(tsk)->security; | 5487 | if (tsec->keycreate_sid) |
5486 | if (__tsec->keycreate_sid) | 5488 | ksec->sid = tsec->keycreate_sid; |
5487 | ksec->sid = __tsec->keycreate_sid; | ||
5488 | else | 5489 | else |
5489 | ksec->sid = __tsec->sid; | 5490 | ksec->sid = tsec->sid; |
5490 | rcu_read_unlock(); | ||
5491 | 5491 | ||
5492 | k->security = ksec; | 5492 | k->security = ksec; |
5493 | return 0; | 5493 | return 0; |
@@ -5502,8 +5502,8 @@ static void selinux_key_free(struct key *k) | |||
5502 | } | 5502 | } |
5503 | 5503 | ||
5504 | static int selinux_key_permission(key_ref_t key_ref, | 5504 | static int selinux_key_permission(key_ref_t key_ref, |
5505 | struct task_struct *ctx, | 5505 | const struct cred *cred, |
5506 | key_perm_t perm) | 5506 | key_perm_t perm) |
5507 | { | 5507 | { |
5508 | struct key *key; | 5508 | struct key *key; |
5509 | struct key_security_struct *ksec; | 5509 | struct key_security_struct *ksec; |
@@ -5515,7 +5515,7 @@ static int selinux_key_permission(key_ref_t key_ref, | |||
5515 | if (perm == 0) | 5515 | if (perm == 0) |
5516 | return 0; | 5516 | return 0; |
5517 | 5517 | ||
5518 | sid = task_sid(ctx); | 5518 | sid = cred_sid(cred); |
5519 | 5519 | ||
5520 | key = key_ref_to_ptr(key_ref); | 5520 | key = key_ref_to_ptr(key_ref); |
5521 | ksec = key->security; | 5521 | ksec = key->security; |
@@ -5545,8 +5545,7 @@ static struct security_operations selinux_ops = { | |||
5545 | .ptrace_may_access = selinux_ptrace_may_access, | 5545 | .ptrace_may_access = selinux_ptrace_may_access, |
5546 | .ptrace_traceme = selinux_ptrace_traceme, | 5546 | .ptrace_traceme = selinux_ptrace_traceme, |
5547 | .capget = selinux_capget, | 5547 | .capget = selinux_capget, |
5548 | .capset_check = selinux_capset_check, | 5548 | .capset = selinux_capset, |
5549 | .capset_set = selinux_capset_set, | ||
5550 | .sysctl = selinux_sysctl, | 5549 | .sysctl = selinux_sysctl, |
5551 | .capable = selinux_capable, | 5550 | .capable = selinux_capable, |
5552 | .quotactl = selinux_quotactl, | 5551 | .quotactl = selinux_quotactl, |
@@ -5621,10 +5620,11 @@ static struct security_operations selinux_ops = { | |||
5621 | .dentry_open = selinux_dentry_open, | 5620 | .dentry_open = selinux_dentry_open, |
5622 | 5621 | ||
5623 | .task_create = selinux_task_create, | 5622 | .task_create = selinux_task_create, |
5624 | .cred_alloc_security = selinux_cred_alloc_security, | ||
5625 | .cred_free = selinux_cred_free, | 5623 | .cred_free = selinux_cred_free, |
5624 | .cred_prepare = selinux_cred_prepare, | ||
5625 | .cred_commit = selinux_cred_commit, | ||
5626 | .task_setuid = selinux_task_setuid, | 5626 | .task_setuid = selinux_task_setuid, |
5627 | .task_post_setuid = selinux_task_post_setuid, | 5627 | .task_fix_setuid = selinux_task_fix_setuid, |
5628 | .task_setgid = selinux_task_setgid, | 5628 | .task_setgid = selinux_task_setgid, |
5629 | .task_setpgid = selinux_task_setpgid, | 5629 | .task_setpgid = selinux_task_setpgid, |
5630 | .task_getpgid = selinux_task_getpgid, | 5630 | .task_getpgid = selinux_task_getpgid, |
@@ -5641,7 +5641,6 @@ static struct security_operations selinux_ops = { | |||
5641 | .task_kill = selinux_task_kill, | 5641 | .task_kill = selinux_task_kill, |
5642 | .task_wait = selinux_task_wait, | 5642 | .task_wait = selinux_task_wait, |
5643 | .task_prctl = selinux_task_prctl, | 5643 | .task_prctl = selinux_task_prctl, |
5644 | .task_reparent_to_init = selinux_task_reparent_to_init, | ||
5645 | .task_to_inode = selinux_task_to_inode, | 5644 | .task_to_inode = selinux_task_to_inode, |
5646 | 5645 | ||
5647 | .ipc_permission = selinux_ipc_permission, | 5646 | .ipc_permission = selinux_ipc_permission, |
@@ -5737,8 +5736,6 @@ static struct security_operations selinux_ops = { | |||
5737 | 5736 | ||
5738 | static __init int selinux_init(void) | 5737 | static __init int selinux_init(void) |
5739 | { | 5738 | { |
5740 | struct task_security_struct *tsec; | ||
5741 | |||
5742 | if (!security_module_enable(&selinux_ops)) { | 5739 | if (!security_module_enable(&selinux_ops)) { |
5743 | selinux_enabled = 0; | 5740 | selinux_enabled = 0; |
5744 | return 0; | 5741 | return 0; |
@@ -5752,10 +5749,7 @@ static __init int selinux_init(void) | |||
5752 | printk(KERN_INFO "SELinux: Initializing.\n"); | 5749 | printk(KERN_INFO "SELinux: Initializing.\n"); |
5753 | 5750 | ||
5754 | /* Set the security state for the initial task. */ | 5751 | /* Set the security state for the initial task. */ |
5755 | if (cred_alloc_security(current->cred)) | 5752 | cred_init_security(); |
5756 | panic("SELinux: Failed to initialize initial task.\n"); | ||
5757 | tsec = current->cred->security; | ||
5758 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | ||
5759 | 5753 | ||
5760 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5754 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
5761 | sizeof(struct inode_security_struct), | 5755 | sizeof(struct inode_security_struct), |