diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 121 |
1 files changed, 42 insertions, 79 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5feecb41009d..5c9f25ba1c95 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -126,11 +126,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
| 126 | int selinux_enabled = 1; | 126 | int selinux_enabled = 1; |
| 127 | #endif | 127 | #endif |
| 128 | 128 | ||
| 129 | /* Lists of inode and superblock security structures initialized | ||
| 130 | before the policy was loaded. */ | ||
| 131 | static LIST_HEAD(superblock_security_head); | ||
| 132 | static DEFINE_SPINLOCK(sb_security_lock); | ||
| 133 | |||
| 134 | static struct kmem_cache *sel_inode_cache; | 129 | static struct kmem_cache *sel_inode_cache; |
| 135 | 130 | ||
| 136 | /** | 131 | /** |
| @@ -266,7 +261,6 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 266 | return -ENOMEM; | 261 | return -ENOMEM; |
| 267 | 262 | ||
| 268 | mutex_init(&sbsec->lock); | 263 | mutex_init(&sbsec->lock); |
| 269 | INIT_LIST_HEAD(&sbsec->list); | ||
| 270 | INIT_LIST_HEAD(&sbsec->isec_head); | 264 | INIT_LIST_HEAD(&sbsec->isec_head); |
| 271 | spin_lock_init(&sbsec->isec_lock); | 265 | spin_lock_init(&sbsec->isec_lock); |
| 272 | sbsec->sb = sb; | 266 | sbsec->sb = sb; |
| @@ -281,40 +275,34 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 281 | static void superblock_free_security(struct super_block *sb) | 275 | static void superblock_free_security(struct super_block *sb) |
| 282 | { | 276 | { |
| 283 | struct superblock_security_struct *sbsec = sb->s_security; | 277 | struct superblock_security_struct *sbsec = sb->s_security; |
| 284 | |||
| 285 | spin_lock(&sb_security_lock); | ||
| 286 | if (!list_empty(&sbsec->list)) | ||
| 287 | list_del_init(&sbsec->list); | ||
| 288 | spin_unlock(&sb_security_lock); | ||
| 289 | |||
| 290 | sb->s_security = NULL; | 278 | sb->s_security = NULL; |
| 291 | kfree(sbsec); | 279 | kfree(sbsec); |
| 292 | } | 280 | } |
| 293 | 281 | ||
| 294 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 282 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
| 295 | { | 283 | { |
| 296 | struct sk_security_struct *ssec; | 284 | struct sk_security_struct *sksec; |
| 297 | 285 | ||
| 298 | ssec = kzalloc(sizeof(*ssec), priority); | 286 | sksec = kzalloc(sizeof(*sksec), priority); |
| 299 | if (!ssec) | 287 | if (!sksec) |
| 300 | return -ENOMEM; | 288 | return -ENOMEM; |
| 301 | 289 | ||
| 302 | ssec->peer_sid = SECINITSID_UNLABELED; | 290 | sksec->peer_sid = SECINITSID_UNLABELED; |
| 303 | ssec->sid = SECINITSID_UNLABELED; | 291 | sksec->sid = SECINITSID_UNLABELED; |
| 304 | sk->sk_security = ssec; | 292 | sk->sk_security = sksec; |
| 305 | 293 | ||
| 306 | selinux_netlbl_sk_security_reset(ssec); | 294 | selinux_netlbl_sk_security_reset(sksec); |
| 307 | 295 | ||
| 308 | return 0; | 296 | return 0; |
| 309 | } | 297 | } |
| 310 | 298 | ||
| 311 | static void sk_free_security(struct sock *sk) | 299 | static void sk_free_security(struct sock *sk) |
| 312 | { | 300 | { |
| 313 | struct sk_security_struct *ssec = sk->sk_security; | 301 | struct sk_security_struct *sksec = sk->sk_security; |
| 314 | 302 | ||
| 315 | sk->sk_security = NULL; | 303 | sk->sk_security = NULL; |
| 316 | selinux_netlbl_sk_security_free(ssec); | 304 | selinux_netlbl_sk_security_free(sksec); |
| 317 | kfree(ssec); | 305 | kfree(sksec); |
| 318 | } | 306 | } |
| 319 | 307 | ||
| 320 | /* The security server must be initialized before | 308 | /* The security server must be initialized before |
| @@ -323,7 +311,7 @@ extern int ss_initialized; | |||
| 323 | 311 | ||
| 324 | /* The file system's label must be initialized prior to use. */ | 312 | /* The file system's label must be initialized prior to use. */ |
| 325 | 313 | ||
| 326 | static char *labeling_behaviors[6] = { | 314 | static const char *labeling_behaviors[6] = { |
| 327 | "uses xattr", | 315 | "uses xattr", |
| 328 | "uses transition SIDs", | 316 | "uses transition SIDs", |
| 329 | "uses task SIDs", | 317 | "uses task SIDs", |
| @@ -612,10 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 612 | /* Defer initialization until selinux_complete_init, | 600 | /* Defer initialization until selinux_complete_init, |
| 613 | after the initial policy is loaded and the security | 601 | after the initial policy is loaded and the security |
| 614 | server is ready to handle calls. */ | 602 | server is ready to handle calls. */ |
| 615 | spin_lock(&sb_security_lock); | ||
| 616 | if (list_empty(&sbsec->list)) | ||
| 617 | list_add(&sbsec->list, &superblock_security_head); | ||
| 618 | spin_unlock(&sb_security_lock); | ||
| 619 | goto out; | 603 | goto out; |
| 620 | } | 604 | } |
| 621 | rc = -EINVAL; | 605 | rc = -EINVAL; |
| @@ -806,16 +790,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
| 806 | 790 | ||
| 807 | /* | 791 | /* |
| 808 | * if the parent was able to be mounted it clearly had no special lsm | 792 | * if the parent was able to be mounted it clearly had no special lsm |
| 809 | * mount options. thus we can safely put this sb on the list and deal | 793 | * mount options. thus we can safely deal with this superblock later |
| 810 | * with it later | ||
| 811 | */ | 794 | */ |
| 812 | if (!ss_initialized) { | 795 | if (!ss_initialized) |
| 813 | spin_lock(&sb_security_lock); | ||
| 814 | if (list_empty(&newsbsec->list)) | ||
| 815 | list_add(&newsbsec->list, &superblock_security_head); | ||
| 816 | spin_unlock(&sb_security_lock); | ||
| 817 | return; | 796 | return; |
| 818 | } | ||
| 819 | 797 | ||
| 820 | /* how can we clone if the old one wasn't set up?? */ | 798 | /* how can we clone if the old one wasn't set up?? */ |
| 821 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 799 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
| @@ -2999,13 +2977,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
| 2999 | return file_has_perm(cred, file, av); | 2977 | return file_has_perm(cred, file, av); |
| 3000 | } | 2978 | } |
| 3001 | 2979 | ||
| 2980 | static int default_noexec; | ||
| 2981 | |||
| 3002 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 2982 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
| 3003 | { | 2983 | { |
| 3004 | const struct cred *cred = current_cred(); | 2984 | const struct cred *cred = current_cred(); |
| 3005 | int rc = 0; | 2985 | int rc = 0; |
| 3006 | 2986 | ||
| 3007 | #ifndef CONFIG_PPC32 | 2987 | if (default_noexec && |
| 3008 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 2988 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
| 3009 | /* | 2989 | /* |
| 3010 | * We are making executable an anonymous mapping or a | 2990 | * We are making executable an anonymous mapping or a |
| 3011 | * private file mapping that will also be writable. | 2991 | * private file mapping that will also be writable. |
| @@ -3015,7 +2995,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
| 3015 | if (rc) | 2995 | if (rc) |
| 3016 | goto error; | 2996 | goto error; |
| 3017 | } | 2997 | } |
| 3018 | #endif | ||
| 3019 | 2998 | ||
| 3020 | if (file) { | 2999 | if (file) { |
| 3021 | /* read access is always possible with a mapping */ | 3000 | /* read access is always possible with a mapping */ |
| @@ -3076,8 +3055,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3076 | if (selinux_checkreqprot) | 3055 | if (selinux_checkreqprot) |
| 3077 | prot = reqprot; | 3056 | prot = reqprot; |
| 3078 | 3057 | ||
| 3079 | #ifndef CONFIG_PPC32 | 3058 | if (default_noexec && |
| 3080 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3059 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
| 3081 | int rc = 0; | 3060 | int rc = 0; |
| 3082 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3061 | if (vma->vm_start >= vma->vm_mm->start_brk && |
| 3083 | vma->vm_end <= vma->vm_mm->brk) { | 3062 | vma->vm_end <= vma->vm_mm->brk) { |
| @@ -3099,7 +3078,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3099 | if (rc) | 3078 | if (rc) |
| 3100 | return rc; | 3079 | return rc; |
| 3101 | } | 3080 | } |
| 3102 | #endif | ||
| 3103 | 3081 | ||
| 3104 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3082 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
| 3105 | } | 3083 | } |
| @@ -4002,7 +3980,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
| 4002 | struct socket *other, | 3980 | struct socket *other, |
| 4003 | struct sock *newsk) | 3981 | struct sock *newsk) |
| 4004 | { | 3982 | { |
| 4005 | struct sk_security_struct *ssec; | 3983 | struct sk_security_struct *sksec; |
| 4006 | struct inode_security_struct *isec; | 3984 | struct inode_security_struct *isec; |
| 4007 | struct inode_security_struct *other_isec; | 3985 | struct inode_security_struct *other_isec; |
| 4008 | struct common_audit_data ad; | 3986 | struct common_audit_data ad; |
| @@ -4021,13 +3999,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
| 4021 | return err; | 3999 | return err; |
| 4022 | 4000 | ||
| 4023 | /* connecting socket */ | 4001 | /* connecting socket */ |
| 4024 | ssec = sock->sk->sk_security; | 4002 | sksec = sock->sk->sk_security; |
| 4025 | ssec->peer_sid = other_isec->sid; | 4003 | sksec->peer_sid = other_isec->sid; |
| 4026 | 4004 | ||
| 4027 | /* server child socket */ | 4005 | /* server child socket */ |
| 4028 | ssec = newsk->sk_security; | 4006 | sksec = newsk->sk_security; |
| 4029 | ssec->peer_sid = isec->sid; | 4007 | sksec->peer_sid = isec->sid; |
| 4030 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 4008 | err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); |
| 4031 | 4009 | ||
| 4032 | return err; | 4010 | return err; |
| 4033 | } | 4011 | } |
| @@ -4190,7 +4168,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4190 | int err = 0; | 4168 | int err = 0; |
| 4191 | char *scontext; | 4169 | char *scontext; |
| 4192 | u32 scontext_len; | 4170 | u32 scontext_len; |
| 4193 | struct sk_security_struct *ssec; | 4171 | struct sk_security_struct *sksec; |
| 4194 | struct inode_security_struct *isec; | 4172 | struct inode_security_struct *isec; |
| 4195 | u32 peer_sid = SECSID_NULL; | 4173 | u32 peer_sid = SECSID_NULL; |
| 4196 | 4174 | ||
| @@ -4198,8 +4176,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4198 | 4176 | ||
| 4199 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4177 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
| 4200 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4178 | isec->sclass == SECCLASS_TCP_SOCKET) { |
| 4201 | ssec = sock->sk->sk_security; | 4179 | sksec = sock->sk->sk_security; |
| 4202 | peer_sid = ssec->peer_sid; | 4180 | peer_sid = sksec->peer_sid; |
| 4203 | } | 4181 | } |
| 4204 | if (peer_sid == SECSID_NULL) { | 4182 | if (peer_sid == SECSID_NULL) { |
| 4205 | err = -ENOPROTOOPT; | 4183 | err = -ENOPROTOOPT; |
| @@ -4266,14 +4244,14 @@ static void selinux_sk_free_security(struct sock *sk) | |||
| 4266 | 4244 | ||
| 4267 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4245 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
| 4268 | { | 4246 | { |
| 4269 | struct sk_security_struct *ssec = sk->sk_security; | 4247 | struct sk_security_struct *sksec = sk->sk_security; |
| 4270 | struct sk_security_struct *newssec = newsk->sk_security; | 4248 | struct sk_security_struct *newsksec = newsk->sk_security; |
| 4271 | 4249 | ||
| 4272 | newssec->sid = ssec->sid; | 4250 | newsksec->sid = sksec->sid; |
| 4273 | newssec->peer_sid = ssec->peer_sid; | 4251 | newsksec->peer_sid = sksec->peer_sid; |
| 4274 | newssec->sclass = ssec->sclass; | 4252 | newsksec->sclass = sksec->sclass; |
| 4275 | 4253 | ||
| 4276 | selinux_netlbl_sk_security_reset(newssec); | 4254 | selinux_netlbl_sk_security_reset(newsksec); |
| 4277 | } | 4255 | } |
| 4278 | 4256 | ||
| 4279 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4257 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
| @@ -5662,6 +5640,8 @@ static __init int selinux_init(void) | |||
| 5662 | /* Set the security state for the initial task. */ | 5640 | /* Set the security state for the initial task. */ |
| 5663 | cred_init_security(); | 5641 | cred_init_security(); |
| 5664 | 5642 | ||
| 5643 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
| 5644 | |||
| 5665 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5645 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
| 5666 | sizeof(struct inode_security_struct), | 5646 | sizeof(struct inode_security_struct), |
| 5667 | 0, SLAB_PANIC, NULL); | 5647 | 0, SLAB_PANIC, NULL); |
| @@ -5678,35 +5658,18 @@ static __init int selinux_init(void) | |||
| 5678 | return 0; | 5658 | return 0; |
| 5679 | } | 5659 | } |
| 5680 | 5660 | ||
| 5661 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
| 5662 | { | ||
| 5663 | superblock_doinit(sb, NULL); | ||
| 5664 | } | ||
| 5665 | |||
| 5681 | void selinux_complete_init(void) | 5666 | void selinux_complete_init(void) |
| 5682 | { | 5667 | { |
| 5683 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5668 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
| 5684 | 5669 | ||
| 5685 | /* Set up any superblocks initialized prior to the policy load. */ | 5670 | /* Set up any superblocks initialized prior to the policy load. */ |
| 5686 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5671 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
| 5687 | spin_lock(&sb_lock); | 5672 | iterate_supers(delayed_superblock_init, NULL); |
| 5688 | spin_lock(&sb_security_lock); | ||
| 5689 | next_sb: | ||
| 5690 | if (!list_empty(&superblock_security_head)) { | ||
| 5691 | struct superblock_security_struct *sbsec = | ||
| 5692 | list_entry(superblock_security_head.next, | ||
| 5693 | struct superblock_security_struct, | ||
| 5694 | list); | ||
| 5695 | struct super_block *sb = sbsec->sb; | ||
| 5696 | sb->s_count++; | ||
| 5697 | spin_unlock(&sb_security_lock); | ||
| 5698 | spin_unlock(&sb_lock); | ||
| 5699 | down_read(&sb->s_umount); | ||
| 5700 | if (sb->s_root) | ||
| 5701 | superblock_doinit(sb, NULL); | ||
| 5702 | drop_super(sb); | ||
| 5703 | spin_lock(&sb_lock); | ||
| 5704 | spin_lock(&sb_security_lock); | ||
| 5705 | list_del_init(&sbsec->list); | ||
| 5706 | goto next_sb; | ||
| 5707 | } | ||
| 5708 | spin_unlock(&sb_security_lock); | ||
| 5709 | spin_unlock(&sb_lock); | ||
| 5710 | } | 5673 | } |
| 5711 | 5674 | ||
| 5712 | /* SELinux requires early initialization in order to label | 5675 | /* SELinux requires early initialization in order to label |
