aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:23 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:23 -0500
commitd84f4f992cbd76e8f39c488cf0c5d123843923b1 (patch)
treefc4a0349c42995715b93d0f7a3c78e9ea9b3f36e /security/selinux/hooks.c
parent745ca2475a6ac596e3d8d37c2759c0fbe2586227 (diff)
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the credentials pointer in the task_struct with respect to accesses by other tasks. A process may only modify its own credentials, and so does not need locking to access or modify its own credentials. A mutex (cred_replace_mutex) is added to the task_struct to control the effect of PTRACE_ATTACHED on credential calculations, particularly with respect to execve(). With this patch, the contents of an active credentials struct may not be changed directly; rather a new set of credentials must be prepared, modified and committed using something like the following sequence of events: struct cred *new = prepare_creds(); int ret = blah(new); if (ret < 0) { abort_creds(new); return ret; } return commit_creds(new); There are some exceptions to this rule: the keyrings pointed to by the active credentials may be instantiated - keyrings violate the COW rule as managing COW keyrings is tricky, given that it is possible for a task to directly alter the keys in a keyring in use by another task. To help enforce this, various pointers to sets of credentials, such as those in the task_struct, are declared const. The purpose of this is compile-time discouragement of altering credentials through those pointers. Once a set of credentials has been made public through one of these pointers, it may not be modified, except under special circumstances: (1) Its reference count may incremented and decremented. (2) The keyrings to which it points may be modified, but not replaced. The only safe way to modify anything else is to create a replacement and commit using the functions described in Documentation/credentials.txt (which will be added by a later patch). This patch and the preceding patches have been tested with the LTP SELinux testsuite. This patch makes several logical sets of alteration: (1) execve(). This now prepares and commits credentials in various places in the security code rather than altering the current creds directly. (2) Temporary credential overrides. do_coredump() and sys_faccessat() now prepare their own credentials and temporarily override the ones currently on the acting thread, whilst preventing interference from other threads by holding cred_replace_mutex on the thread being dumped. This will be replaced in a future patch by something that hands down the credentials directly to the functions being called, rather than altering the task's objective credentials. (3) LSM interface. A number of functions have been changed, added or removed: (*) security_capset_check(), ->capset_check() (*) security_capset_set(), ->capset_set() Removed in favour of security_capset(). (*) security_capset(), ->capset() New. This is passed a pointer to the new creds, a pointer to the old creds and the proposed capability sets. It should fill in the new creds or return an error. All pointers, barring the pointer to the new creds, are now const. (*) security_bprm_apply_creds(), ->bprm_apply_creds() Changed; now returns a value, which will cause the process to be killed if it's an error. (*) security_task_alloc(), ->task_alloc_security() Removed in favour of security_prepare_creds(). (*) security_cred_free(), ->cred_free() New. Free security data attached to cred->security. (*) security_prepare_creds(), ->cred_prepare() New. Duplicate any security data attached to cred->security. (*) security_commit_creds(), ->cred_commit() New. Apply any security effects for the upcoming installation of new security by commit_creds(). (*) security_task_post_setuid(), ->task_post_setuid() Removed in favour of security_task_fix_setuid(). (*) security_task_fix_setuid(), ->task_fix_setuid() Fix up the proposed new credentials for setuid(). This is used by cap_set_fix_setuid() to implicitly adjust capabilities in line with setuid() changes. Changes are made to the new credentials, rather than the task itself as in security_task_post_setuid(). (*) security_task_reparent_to_init(), ->task_reparent_to_init() Removed. Instead the task being reparented to init is referred directly to init's credentials. NOTE! This results in the loss of some state: SELinux's osid no longer records the sid of the thread that forked it. (*) security_key_alloc(), ->key_alloc() (*) security_key_permission(), ->key_permission() Changed. These now take cred pointers rather than task pointers to refer to the security context. (4) sys_capset(). This has been simplified and uses less locking. The LSM functions it calls have been merged. (5) reparent_to_kthreadd(). This gives the current thread the same credentials as init by simply using commit_thread() to point that way. (6) __sigqueue_alloc() and switch_uid() __sigqueue_alloc() can't stop the target task from changing its creds beneath it, so this function gets a reference to the currently applicable user_struct which it then passes into the sigqueue struct it returns if successful. switch_uid() is now called from commit_creds(), and possibly should be folded into that. commit_creds() should take care of protecting __sigqueue_alloc(). (7) [sg]et[ug]id() and co and [sg]et_current_groups. The set functions now all use prepare_creds(), commit_creds() and abort_creds() to build and check a new set of credentials before applying it. security_task_set[ug]id() is called inside the prepared section. This guarantees that nothing else will affect the creds until we've finished. The calling of set_dumpable() has been moved into commit_creds(). Much of the functionality of set_user() has been moved into commit_creds(). The get functions all simply access the data directly. (8) security_task_prctl() and cap_task_prctl(). security_task_prctl() has been modified to return -ENOSYS if it doesn't want to handle a function, or otherwise return the return value directly rather than through an argument. Additionally, cap_task_prctl() now prepares a new set of credentials, even if it doesn't end up using it. (9) Keyrings. A number of changes have been made to the keyrings code: (a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have all been dropped and built in to the credentials functions directly. They may want separating out again later. (b) key_alloc() and search_process_keyrings() now take a cred pointer rather than a task pointer to specify the security context. (c) copy_creds() gives a new thread within the same thread group a new thread keyring if its parent had one, otherwise it discards the thread keyring. (d) The authorisation key now points directly to the credentials to extend the search into rather pointing to the task that carries them. (e) Installing thread, process or session keyrings causes a new set of credentials to be created, even though it's not strictly necessary for process or session keyrings (they're shared). (10) Usermode helper. The usermode helper code now carries a cred struct pointer in its subprocess_info struct instead of a new session keyring pointer. This set of credentials is derived from init_cred and installed on the new process after it has been cloned. call_usermodehelper_setup() allocates the new credentials and call_usermodehelper_freeinfo() discards them if they haven't been used. A special cred function (prepare_usermodeinfo_creds()) is provided specifically for call_usermodehelper_setup() to call. call_usermodehelper_setkeys() adjusts the credentials to sport the supplied keyring as the new session keyring. (11) SELinux. SELinux has a number of changes, in addition to those to support the LSM interface changes mentioned above: (a) selinux_setprocattr() no longer does its check for whether the current ptracer can access processes with the new SID inside the lock that covers getting the ptracer's SID. Whilst this lock ensures that the check is done with the ptracer pinned, the result is only valid until the lock is released, so there's no point doing it inside the lock. (12) is_single_threaded(). This function has been extracted from selinux_setprocattr() and put into a file of its own in the lib/ directory as join_session_keyring() now wants to use it too. The code in SELinux just checked to see whether a task shared mm_structs with other tasks (CLONE_VM), but that isn't good enough. We really want to know if they're part of the same thread group (CLONE_THREAD). (13) nfsd. The NFS server daemon now has to use the COW credentials to set the credentials it is going to use. It really needs to pass the credentials down to the functions it calls, but it can't do that until other patches in this series have been applied. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c286
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
161static int cred_alloc_security(struct cred *cred) 161 */
162static 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 */
1385static 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
1823static int selinux_capset_check(const kernel_cap_t *effective, 1836static 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
1836static 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
1843static int selinux_capable(struct task_struct *tsk, int cap, int audit) 1851static 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
2247static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) 2255static 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
2317out:
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,
3021static int file_map_prot_check(struct file *file, unsigned long prot, int shared) 3040static 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
3072error:
3073 return rc;
3052} 3074}
3053 3075
3054static int selinux_file_mmap(struct file *file, unsigned long reqprot, 3076static 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
3250static int selinux_cred_alloc_security(struct cred *cred) 3271/*
3272 * detach and free the LSM part of a set of credentials
3273 */
3274static 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; 3284static 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 */
3277static void selinux_cred_free(struct cred *cred) 3303static 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
3284static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) 3308static 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
3295static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) 3319static 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
3300static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) 3325static 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
3434static int selinux_task_wait(struct task_struct *p) 3458static 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
3439static 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
3451static void selinux_task_to_inode(struct task_struct *p, 3463static 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 }
5420boundary_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
5454abort_change:
5455 abort_creds(new);
5456 return error;
5455} 5457}
5456 5458
5457static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) 5459static 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
5474static int selinux_key_alloc(struct key *k, struct task_struct *tsk, 5476static 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
5504static int selinux_key_permission(key_ref_t key_ref, 5504static 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
5738static __init int selinux_init(void) 5737static __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),