diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 377 |
1 files changed, 138 insertions, 239 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5feecb41009d..9b40f4c0ac70 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -87,9 +87,6 @@ | |||
| 87 | #include "netlabel.h" | 87 | #include "netlabel.h" |
| 88 | #include "audit.h" | 88 | #include "audit.h" |
| 89 | 89 | ||
| 90 | #define XATTR_SELINUX_SUFFIX "selinux" | ||
| 91 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | ||
| 92 | |||
| 93 | #define NUM_SEL_MNT_OPTS 5 | 90 | #define NUM_SEL_MNT_OPTS 5 |
| 94 | 91 | ||
| 95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 92 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
| @@ -126,11 +123,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
| 126 | int selinux_enabled = 1; | 123 | int selinux_enabled = 1; |
| 127 | #endif | 124 | #endif |
| 128 | 125 | ||
| 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; | 126 | static struct kmem_cache *sel_inode_cache; |
| 135 | 127 | ||
| 136 | /** | 128 | /** |
| @@ -193,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
| 193 | */ | 185 | */ |
| 194 | static inline u32 current_sid(void) | 186 | static inline u32 current_sid(void) |
| 195 | { | 187 | { |
| 196 | const struct task_security_struct *tsec = current_cred()->security; | 188 | const struct task_security_struct *tsec = current_security(); |
| 197 | 189 | ||
| 198 | return tsec->sid; | 190 | return tsec->sid; |
| 199 | } | 191 | } |
| @@ -266,7 +258,6 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 266 | return -ENOMEM; | 258 | return -ENOMEM; |
| 267 | 259 | ||
| 268 | mutex_init(&sbsec->lock); | 260 | mutex_init(&sbsec->lock); |
| 269 | INIT_LIST_HEAD(&sbsec->list); | ||
| 270 | INIT_LIST_HEAD(&sbsec->isec_head); | 261 | INIT_LIST_HEAD(&sbsec->isec_head); |
| 271 | spin_lock_init(&sbsec->isec_lock); | 262 | spin_lock_init(&sbsec->isec_lock); |
| 272 | sbsec->sb = sb; | 263 | sbsec->sb = sb; |
| @@ -281,49 +272,17 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 281 | static void superblock_free_security(struct super_block *sb) | 272 | static void superblock_free_security(struct super_block *sb) |
| 282 | { | 273 | { |
| 283 | struct superblock_security_struct *sbsec = sb->s_security; | 274 | 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; | 275 | sb->s_security = NULL; |
| 291 | kfree(sbsec); | 276 | kfree(sbsec); |
| 292 | } | 277 | } |
| 293 | 278 | ||
| 294 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | ||
| 295 | { | ||
| 296 | struct sk_security_struct *ssec; | ||
| 297 | |||
| 298 | ssec = kzalloc(sizeof(*ssec), priority); | ||
| 299 | if (!ssec) | ||
| 300 | return -ENOMEM; | ||
| 301 | |||
| 302 | ssec->peer_sid = SECINITSID_UNLABELED; | ||
| 303 | ssec->sid = SECINITSID_UNLABELED; | ||
| 304 | sk->sk_security = ssec; | ||
| 305 | |||
| 306 | selinux_netlbl_sk_security_reset(ssec); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static void sk_free_security(struct sock *sk) | ||
| 312 | { | ||
| 313 | struct sk_security_struct *ssec = sk->sk_security; | ||
| 314 | |||
| 315 | sk->sk_security = NULL; | ||
| 316 | selinux_netlbl_sk_security_free(ssec); | ||
| 317 | kfree(ssec); | ||
| 318 | } | ||
| 319 | |||
| 320 | /* The security server must be initialized before | 279 | /* The security server must be initialized before |
| 321 | any labeling or access decisions can be provided. */ | 280 | any labeling or access decisions can be provided. */ |
| 322 | extern int ss_initialized; | 281 | extern int ss_initialized; |
| 323 | 282 | ||
| 324 | /* The file system's label must be initialized prior to use. */ | 283 | /* The file system's label must be initialized prior to use. */ |
| 325 | 284 | ||
| 326 | static char *labeling_behaviors[6] = { | 285 | static const char *labeling_behaviors[6] = { |
| 327 | "uses xattr", | 286 | "uses xattr", |
| 328 | "uses transition SIDs", | 287 | "uses transition SIDs", |
| 329 | "uses task SIDs", | 288 | "uses task SIDs", |
| @@ -612,10 +571,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 612 | /* Defer initialization until selinux_complete_init, | 571 | /* Defer initialization until selinux_complete_init, |
| 613 | after the initial policy is loaded and the security | 572 | after the initial policy is loaded and the security |
| 614 | server is ready to handle calls. */ | 573 | 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; | 574 | goto out; |
| 620 | } | 575 | } |
| 621 | rc = -EINVAL; | 576 | rc = -EINVAL; |
| @@ -806,16 +761,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
| 806 | 761 | ||
| 807 | /* | 762 | /* |
| 808 | * if the parent was able to be mounted it clearly had no special lsm | 763 | * 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 | 764 | * mount options. thus we can safely deal with this superblock later |
| 810 | * with it later | ||
| 811 | */ | 765 | */ |
| 812 | if (!ss_initialized) { | 766 | 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; | 767 | return; |
| 818 | } | ||
| 819 | 768 | ||
| 820 | /* how can we clone if the old one wasn't set up?? */ | 769 | /* how can we clone if the old one wasn't set up?? */ |
| 821 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 770 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
| @@ -1606,8 +1555,7 @@ static int may_create(struct inode *dir, | |||
| 1606 | struct dentry *dentry, | 1555 | struct dentry *dentry, |
| 1607 | u16 tclass) | 1556 | u16 tclass) |
| 1608 | { | 1557 | { |
| 1609 | const struct cred *cred = current_cred(); | 1558 | const struct task_security_struct *tsec = current_security(); |
| 1610 | const struct task_security_struct *tsec = cred->security; | ||
| 1611 | struct inode_security_struct *dsec; | 1559 | struct inode_security_struct *dsec; |
| 1612 | struct superblock_security_struct *sbsec; | 1560 | struct superblock_security_struct *sbsec; |
| 1613 | u32 sid, newsid; | 1561 | u32 sid, newsid; |
| @@ -1828,27 +1776,9 @@ static inline u32 open_file_to_av(struct file *file) | |||
| 1828 | { | 1776 | { |
| 1829 | u32 av = file_to_av(file); | 1777 | u32 av = file_to_av(file); |
| 1830 | 1778 | ||
| 1831 | if (selinux_policycap_openperm) { | 1779 | if (selinux_policycap_openperm) |
| 1832 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | 1780 | av |= FILE__OPEN; |
| 1833 | /* | 1781 | |
| 1834 | * lnk files and socks do not really have an 'open' | ||
| 1835 | */ | ||
| 1836 | if (S_ISREG(mode)) | ||
| 1837 | av |= FILE__OPEN; | ||
| 1838 | else if (S_ISCHR(mode)) | ||
| 1839 | av |= CHR_FILE__OPEN; | ||
| 1840 | else if (S_ISBLK(mode)) | ||
| 1841 | av |= BLK_FILE__OPEN; | ||
| 1842 | else if (S_ISFIFO(mode)) | ||
| 1843 | av |= FIFO_FILE__OPEN; | ||
| 1844 | else if (S_ISDIR(mode)) | ||
| 1845 | av |= DIR__OPEN; | ||
| 1846 | else if (S_ISSOCK(mode)) | ||
| 1847 | av |= SOCK_FILE__OPEN; | ||
| 1848 | else | ||
| 1849 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | ||
| 1850 | "unknown mode:%o\n", __func__, mode); | ||
| 1851 | } | ||
| 1852 | return av; | 1782 | return av; |
| 1853 | } | 1783 | } |
| 1854 | 1784 | ||
| @@ -2205,8 +2135,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2205 | 2135 | ||
| 2206 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2136 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
| 2207 | { | 2137 | { |
| 2208 | const struct cred *cred = current_cred(); | 2138 | const struct task_security_struct *tsec = current_security(); |
| 2209 | const struct task_security_struct *tsec = cred->security; | ||
| 2210 | u32 sid, osid; | 2139 | u32 sid, osid; |
| 2211 | int atsecure = 0; | 2140 | int atsecure = 0; |
| 2212 | 2141 | ||
| @@ -2581,8 +2510,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2581 | char **name, void **value, | 2510 | char **name, void **value, |
| 2582 | size_t *len) | 2511 | size_t *len) |
| 2583 | { | 2512 | { |
| 2584 | const struct cred *cred = current_cred(); | 2513 | const struct task_security_struct *tsec = current_security(); |
| 2585 | const struct task_security_struct *tsec = cred->security; | ||
| 2586 | struct inode_security_struct *dsec; | 2514 | struct inode_security_struct *dsec; |
| 2587 | struct superblock_security_struct *sbsec; | 2515 | struct superblock_security_struct *sbsec; |
| 2588 | u32 sid, newsid, clen; | 2516 | u32 sid, newsid, clen; |
| @@ -2698,14 +2626,26 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
| 2698 | static int selinux_inode_permission(struct inode *inode, int mask) | 2626 | static int selinux_inode_permission(struct inode *inode, int mask) |
| 2699 | { | 2627 | { |
| 2700 | const struct cred *cred = current_cred(); | 2628 | const struct cred *cred = current_cred(); |
| 2629 | struct common_audit_data ad; | ||
| 2630 | u32 perms; | ||
| 2631 | bool from_access; | ||
| 2701 | 2632 | ||
| 2702 | if (!mask) { | 2633 | from_access = mask & MAY_ACCESS; |
| 2703 | /* No permission to check. Existence test. */ | 2634 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
| 2635 | |||
| 2636 | /* No permission to check. Existence test. */ | ||
| 2637 | if (!mask) | ||
| 2704 | return 0; | 2638 | return 0; |
| 2705 | } | ||
| 2706 | 2639 | ||
| 2707 | return inode_has_perm(cred, inode, | 2640 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2708 | file_mask_to_av(inode->i_mode, mask), NULL); | 2641 | ad.u.fs.inode = inode; |
| 2642 | |||
| 2643 | if (from_access) | ||
| 2644 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
| 2645 | |||
| 2646 | perms = file_mask_to_av(inode->i_mode, mask); | ||
| 2647 | |||
| 2648 | return inode_has_perm(cred, inode, perms, &ad); | ||
| 2709 | } | 2649 | } |
| 2710 | 2650 | ||
| 2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2651 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
| @@ -2999,13 +2939,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
| 2999 | return file_has_perm(cred, file, av); | 2939 | return file_has_perm(cred, file, av); |
| 3000 | } | 2940 | } |
| 3001 | 2941 | ||
| 2942 | static int default_noexec; | ||
| 2943 | |||
| 3002 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 2944 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
| 3003 | { | 2945 | { |
| 3004 | const struct cred *cred = current_cred(); | 2946 | const struct cred *cred = current_cred(); |
| 3005 | int rc = 0; | 2947 | int rc = 0; |
| 3006 | 2948 | ||
| 3007 | #ifndef CONFIG_PPC32 | 2949 | if (default_noexec && |
| 3008 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 2950 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
| 3009 | /* | 2951 | /* |
| 3010 | * We are making executable an anonymous mapping or a | 2952 | * We are making executable an anonymous mapping or a |
| 3011 | * private file mapping that will also be writable. | 2953 | * private file mapping that will also be writable. |
| @@ -3015,7 +2957,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
| 3015 | if (rc) | 2957 | if (rc) |
| 3016 | goto error; | 2958 | goto error; |
| 3017 | } | 2959 | } |
| 3018 | #endif | ||
| 3019 | 2960 | ||
| 3020 | if (file) { | 2961 | if (file) { |
| 3021 | /* read access is always possible with a mapping */ | 2962 | /* read access is always possible with a mapping */ |
| @@ -3076,8 +3017,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3076 | if (selinux_checkreqprot) | 3017 | if (selinux_checkreqprot) |
| 3077 | prot = reqprot; | 3018 | prot = reqprot; |
| 3078 | 3019 | ||
| 3079 | #ifndef CONFIG_PPC32 | 3020 | if (default_noexec && |
| 3080 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3021 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
| 3081 | int rc = 0; | 3022 | int rc = 0; |
| 3082 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3023 | if (vma->vm_start >= vma->vm_mm->start_brk && |
| 3083 | vma->vm_end <= vma->vm_mm->brk) { | 3024 | vma->vm_end <= vma->vm_mm->brk) { |
| @@ -3099,7 +3040,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3099 | if (rc) | 3040 | if (rc) |
| 3100 | return rc; | 3041 | return rc; |
| 3101 | } | 3042 | } |
| 3102 | #endif | ||
| 3103 | 3043 | ||
| 3104 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3044 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
| 3105 | } | 3045 | } |
| @@ -3693,71 +3633,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
| 3693 | } | 3633 | } |
| 3694 | 3634 | ||
| 3695 | /* socket security operations */ | 3635 | /* socket security operations */ |
| 3696 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3636 | |
| 3697 | u32 perms) | 3637 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
| 3698 | { | 3638 | { |
| 3699 | struct inode_security_struct *isec; | 3639 | return tsec->sockcreate_sid ? : tsec->sid; |
| 3700 | struct common_audit_data ad; | 3640 | } |
| 3701 | u32 sid; | ||
| 3702 | int err = 0; | ||
| 3703 | 3641 | ||
| 3704 | isec = SOCK_INODE(sock)->i_security; | 3642 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
| 3643 | { | ||
| 3644 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 3645 | struct common_audit_data ad; | ||
| 3646 | u32 tsid = task_sid(task); | ||
| 3705 | 3647 | ||
| 3706 | if (isec->sid == SECINITSID_KERNEL) | 3648 | if (sksec->sid == SECINITSID_KERNEL) |
| 3707 | goto out; | 3649 | return 0; |
| 3708 | sid = task_sid(task); | ||
| 3709 | 3650 | ||
| 3710 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3651 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3711 | ad.u.net.sk = sock->sk; | 3652 | ad.u.net.sk = sk; |
| 3712 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
| 3713 | 3653 | ||
| 3714 | out: | 3654 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
| 3715 | return err; | ||
| 3716 | } | 3655 | } |
| 3717 | 3656 | ||
| 3718 | static int selinux_socket_create(int family, int type, | 3657 | static int selinux_socket_create(int family, int type, |
| 3719 | int protocol, int kern) | 3658 | int protocol, int kern) |
| 3720 | { | 3659 | { |
| 3721 | const struct cred *cred = current_cred(); | 3660 | const struct task_security_struct *tsec = current_security(); |
| 3722 | const struct task_security_struct *tsec = cred->security; | 3661 | u32 newsid; |
| 3723 | u32 sid, newsid; | ||
| 3724 | u16 secclass; | 3662 | u16 secclass; |
| 3725 | int err = 0; | ||
| 3726 | 3663 | ||
| 3727 | if (kern) | 3664 | if (kern) |
| 3728 | goto out; | 3665 | return 0; |
| 3729 | |||
| 3730 | sid = tsec->sid; | ||
| 3731 | newsid = tsec->sockcreate_sid ?: sid; | ||
| 3732 | 3666 | ||
| 3667 | newsid = socket_sockcreate_sid(tsec); | ||
| 3733 | secclass = socket_type_to_security_class(family, type, protocol); | 3668 | secclass = socket_type_to_security_class(family, type, protocol); |
| 3734 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3669 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
| 3735 | |||
| 3736 | out: | ||
| 3737 | return err; | ||
| 3738 | } | 3670 | } |
| 3739 | 3671 | ||
| 3740 | static int selinux_socket_post_create(struct socket *sock, int family, | 3672 | static int selinux_socket_post_create(struct socket *sock, int family, |
| 3741 | int type, int protocol, int kern) | 3673 | int type, int protocol, int kern) |
| 3742 | { | 3674 | { |
| 3743 | const struct cred *cred = current_cred(); | 3675 | const struct task_security_struct *tsec = current_security(); |
| 3744 | const struct task_security_struct *tsec = cred->security; | 3676 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
| 3745 | struct inode_security_struct *isec; | ||
| 3746 | struct sk_security_struct *sksec; | 3677 | struct sk_security_struct *sksec; |
| 3747 | u32 sid, newsid; | ||
| 3748 | int err = 0; | 3678 | int err = 0; |
| 3749 | 3679 | ||
| 3750 | sid = tsec->sid; | ||
| 3751 | newsid = tsec->sockcreate_sid; | ||
| 3752 | |||
| 3753 | isec = SOCK_INODE(sock)->i_security; | ||
| 3754 | |||
| 3755 | if (kern) | 3680 | if (kern) |
| 3756 | isec->sid = SECINITSID_KERNEL; | 3681 | isec->sid = SECINITSID_KERNEL; |
| 3757 | else if (newsid) | ||
| 3758 | isec->sid = newsid; | ||
| 3759 | else | 3682 | else |
| 3760 | isec->sid = sid; | 3683 | isec->sid = socket_sockcreate_sid(tsec); |
| 3761 | 3684 | ||
| 3762 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3685 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
| 3763 | isec->initialized = 1; | 3686 | isec->initialized = 1; |
| @@ -3778,10 +3701,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
| 3778 | 3701 | ||
| 3779 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3702 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
| 3780 | { | 3703 | { |
| 3704 | struct sock *sk = sock->sk; | ||
| 3781 | u16 family; | 3705 | u16 family; |
| 3782 | int err; | 3706 | int err; |
| 3783 | 3707 | ||
| 3784 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3708 | err = sock_has_perm(current, sk, SOCKET__BIND); |
| 3785 | if (err) | 3709 | if (err) |
| 3786 | goto out; | 3710 | goto out; |
| 3787 | 3711 | ||
| @@ -3790,19 +3714,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3790 | * Multiple address binding for SCTP is not supported yet: we just | 3714 | * Multiple address binding for SCTP is not supported yet: we just |
| 3791 | * check the first address now. | 3715 | * check the first address now. |
| 3792 | */ | 3716 | */ |
| 3793 | family = sock->sk->sk_family; | 3717 | family = sk->sk_family; |
| 3794 | if (family == PF_INET || family == PF_INET6) { | 3718 | if (family == PF_INET || family == PF_INET6) { |
| 3795 | char *addrp; | 3719 | char *addrp; |
| 3796 | struct inode_security_struct *isec; | 3720 | struct sk_security_struct *sksec = sk->sk_security; |
| 3797 | struct common_audit_data ad; | 3721 | struct common_audit_data ad; |
| 3798 | struct sockaddr_in *addr4 = NULL; | 3722 | struct sockaddr_in *addr4 = NULL; |
| 3799 | struct sockaddr_in6 *addr6 = NULL; | 3723 | struct sockaddr_in6 *addr6 = NULL; |
| 3800 | unsigned short snum; | 3724 | unsigned short snum; |
| 3801 | struct sock *sk = sock->sk; | ||
| 3802 | u32 sid, node_perm; | 3725 | u32 sid, node_perm; |
| 3803 | 3726 | ||
| 3804 | isec = SOCK_INODE(sock)->i_security; | ||
| 3805 | |||
| 3806 | if (family == PF_INET) { | 3727 | if (family == PF_INET) { |
| 3807 | addr4 = (struct sockaddr_in *)address; | 3728 | addr4 = (struct sockaddr_in *)address; |
| 3808 | snum = ntohs(addr4->sin_port); | 3729 | snum = ntohs(addr4->sin_port); |
| @@ -3826,15 +3747,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3826 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3747 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3827 | ad.u.net.sport = htons(snum); | 3748 | ad.u.net.sport = htons(snum); |
| 3828 | ad.u.net.family = family; | 3749 | ad.u.net.family = family; |
| 3829 | err = avc_has_perm(isec->sid, sid, | 3750 | err = avc_has_perm(sksec->sid, sid, |
| 3830 | isec->sclass, | 3751 | sksec->sclass, |
| 3831 | SOCKET__NAME_BIND, &ad); | 3752 | SOCKET__NAME_BIND, &ad); |
| 3832 | if (err) | 3753 | if (err) |
| 3833 | goto out; | 3754 | goto out; |
| 3834 | } | 3755 | } |
| 3835 | } | 3756 | } |
| 3836 | 3757 | ||
| 3837 | switch (isec->sclass) { | 3758 | switch (sksec->sclass) { |
| 3838 | case SECCLASS_TCP_SOCKET: | 3759 | case SECCLASS_TCP_SOCKET: |
| 3839 | node_perm = TCP_SOCKET__NODE_BIND; | 3760 | node_perm = TCP_SOCKET__NODE_BIND; |
| 3840 | break; | 3761 | break; |
| @@ -3865,8 +3786,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3865 | else | 3786 | else |
| 3866 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3787 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
| 3867 | 3788 | ||
| 3868 | err = avc_has_perm(isec->sid, sid, | 3789 | err = avc_has_perm(sksec->sid, sid, |
| 3869 | isec->sclass, node_perm, &ad); | 3790 | sksec->sclass, node_perm, &ad); |
| 3870 | if (err) | 3791 | if (err) |
| 3871 | goto out; | 3792 | goto out; |
| 3872 | } | 3793 | } |
| @@ -3877,19 +3798,18 @@ out: | |||
| 3877 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3798 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
| 3878 | { | 3799 | { |
| 3879 | struct sock *sk = sock->sk; | 3800 | struct sock *sk = sock->sk; |
| 3880 | struct inode_security_struct *isec; | 3801 | struct sk_security_struct *sksec = sk->sk_security; |
| 3881 | int err; | 3802 | int err; |
| 3882 | 3803 | ||
| 3883 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3804 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
| 3884 | if (err) | 3805 | if (err) |
| 3885 | return err; | 3806 | return err; |
| 3886 | 3807 | ||
| 3887 | /* | 3808 | /* |
| 3888 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3809 | * If a TCP or DCCP socket, check name_connect permission for the port. |
| 3889 | */ | 3810 | */ |
| 3890 | isec = SOCK_INODE(sock)->i_security; | 3811 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
| 3891 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3812 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
| 3892 | isec->sclass == SECCLASS_DCCP_SOCKET) { | ||
| 3893 | struct common_audit_data ad; | 3813 | struct common_audit_data ad; |
| 3894 | struct sockaddr_in *addr4 = NULL; | 3814 | struct sockaddr_in *addr4 = NULL; |
| 3895 | struct sockaddr_in6 *addr6 = NULL; | 3815 | struct sockaddr_in6 *addr6 = NULL; |
| @@ -3912,13 +3832,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
| 3912 | if (err) | 3832 | if (err) |
| 3913 | goto out; | 3833 | goto out; |
| 3914 | 3834 | ||
| 3915 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3835 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
| 3916 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3836 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
| 3917 | 3837 | ||
| 3918 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3838 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3919 | ad.u.net.dport = htons(snum); | 3839 | ad.u.net.dport = htons(snum); |
| 3920 | ad.u.net.family = sk->sk_family; | 3840 | ad.u.net.family = sk->sk_family; |
| 3921 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3841 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
| 3922 | if (err) | 3842 | if (err) |
| 3923 | goto out; | 3843 | goto out; |
| 3924 | } | 3844 | } |
| @@ -3931,7 +3851,7 @@ out: | |||
| 3931 | 3851 | ||
| 3932 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3852 | static int selinux_socket_listen(struct socket *sock, int backlog) |
| 3933 | { | 3853 | { |
| 3934 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3854 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
| 3935 | } | 3855 | } |
| 3936 | 3856 | ||
| 3937 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3857 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
| @@ -3940,7 +3860,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 3940 | struct inode_security_struct *isec; | 3860 | struct inode_security_struct *isec; |
| 3941 | struct inode_security_struct *newisec; | 3861 | struct inode_security_struct *newisec; |
| 3942 | 3862 | ||
| 3943 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3863 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
| 3944 | if (err) | 3864 | if (err) |
| 3945 | return err; | 3865 | return err; |
| 3946 | 3866 | ||
| @@ -3957,30 +3877,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 3957 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3877 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
| 3958 | int size) | 3878 | int size) |
| 3959 | { | 3879 | { |
| 3960 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3880 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
| 3961 | } | 3881 | } |
| 3962 | 3882 | ||
| 3963 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3883 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
| 3964 | int size, int flags) | 3884 | int size, int flags) |
| 3965 | { | 3885 | { |
| 3966 | return socket_has_perm(current, sock, SOCKET__READ); | 3886 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
| 3967 | } | 3887 | } |
| 3968 | 3888 | ||
| 3969 | static int selinux_socket_getsockname(struct socket *sock) | 3889 | static int selinux_socket_getsockname(struct socket *sock) |
| 3970 | { | 3890 | { |
| 3971 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3891 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
| 3972 | } | 3892 | } |
| 3973 | 3893 | ||
| 3974 | static int selinux_socket_getpeername(struct socket *sock) | 3894 | static int selinux_socket_getpeername(struct socket *sock) |
| 3975 | { | 3895 | { |
| 3976 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3896 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
| 3977 | } | 3897 | } |
| 3978 | 3898 | ||
| 3979 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3899 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
| 3980 | { | 3900 | { |
| 3981 | int err; | 3901 | int err; |
| 3982 | 3902 | ||
| 3983 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3903 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
| 3984 | if (err) | 3904 | if (err) |
| 3985 | return err; | 3905 | return err; |
| 3986 | 3906 | ||
| @@ -3990,68 +3910,58 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
| 3990 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3910 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
| 3991 | int optname) | 3911 | int optname) |
| 3992 | { | 3912 | { |
| 3993 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3913 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
| 3994 | } | 3914 | } |
| 3995 | 3915 | ||
| 3996 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3916 | static int selinux_socket_shutdown(struct socket *sock, int how) |
| 3997 | { | 3917 | { |
| 3998 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3918 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
| 3999 | } | 3919 | } |
| 4000 | 3920 | ||
| 4001 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3921 | static int selinux_socket_unix_stream_connect(struct socket *sock, |
| 4002 | struct socket *other, | 3922 | struct socket *other, |
| 4003 | struct sock *newsk) | 3923 | struct sock *newsk) |
| 4004 | { | 3924 | { |
| 4005 | struct sk_security_struct *ssec; | 3925 | struct sk_security_struct *sksec_sock = sock->sk->sk_security; |
| 4006 | struct inode_security_struct *isec; | 3926 | struct sk_security_struct *sksec_other = other->sk->sk_security; |
| 4007 | struct inode_security_struct *other_isec; | 3927 | struct sk_security_struct *sksec_new = newsk->sk_security; |
| 4008 | struct common_audit_data ad; | 3928 | struct common_audit_data ad; |
| 4009 | int err; | 3929 | int err; |
| 4010 | 3930 | ||
| 4011 | isec = SOCK_INODE(sock)->i_security; | ||
| 4012 | other_isec = SOCK_INODE(other)->i_security; | ||
| 4013 | |||
| 4014 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3931 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4015 | ad.u.net.sk = other->sk; | 3932 | ad.u.net.sk = other->sk; |
| 4016 | 3933 | ||
| 4017 | err = avc_has_perm(isec->sid, other_isec->sid, | 3934 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
| 4018 | isec->sclass, | 3935 | sksec_other->sclass, |
| 4019 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3936 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
| 4020 | if (err) | 3937 | if (err) |
| 4021 | return err; | 3938 | return err; |
| 4022 | 3939 | ||
| 4023 | /* connecting socket */ | ||
| 4024 | ssec = sock->sk->sk_security; | ||
| 4025 | ssec->peer_sid = other_isec->sid; | ||
| 4026 | |||
| 4027 | /* server child socket */ | 3940 | /* server child socket */ |
| 4028 | ssec = newsk->sk_security; | 3941 | sksec_new->peer_sid = sksec_sock->sid; |
| 4029 | ssec->peer_sid = isec->sid; | 3942 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
| 4030 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 3943 | &sksec_new->sid); |
| 3944 | if (err) | ||
| 3945 | return err; | ||
| 4031 | 3946 | ||
| 4032 | return err; | 3947 | /* connecting socket */ |
| 3948 | sksec_sock->peer_sid = sksec_new->sid; | ||
| 3949 | |||
| 3950 | return 0; | ||
| 4033 | } | 3951 | } |
| 4034 | 3952 | ||
| 4035 | static int selinux_socket_unix_may_send(struct socket *sock, | 3953 | static int selinux_socket_unix_may_send(struct socket *sock, |
| 4036 | struct socket *other) | 3954 | struct socket *other) |
| 4037 | { | 3955 | { |
| 4038 | struct inode_security_struct *isec; | 3956 | struct sk_security_struct *ssec = sock->sk->sk_security; |
| 4039 | struct inode_security_struct *other_isec; | 3957 | struct sk_security_struct *osec = other->sk->sk_security; |
| 4040 | struct common_audit_data ad; | 3958 | struct common_audit_data ad; |
| 4041 | int err; | ||
| 4042 | |||
| 4043 | isec = SOCK_INODE(sock)->i_security; | ||
| 4044 | other_isec = SOCK_INODE(other)->i_security; | ||
| 4045 | 3959 | ||
| 4046 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3960 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4047 | ad.u.net.sk = other->sk; | 3961 | ad.u.net.sk = other->sk; |
| 4048 | 3962 | ||
| 4049 | err = avc_has_perm(isec->sid, other_isec->sid, | 3963 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
| 4050 | isec->sclass, SOCKET__SENDTO, &ad); | 3964 | &ad); |
| 4051 | if (err) | ||
| 4052 | return err; | ||
| 4053 | |||
| 4054 | return 0; | ||
| 4055 | } | 3965 | } |
| 4056 | 3966 | ||
| 4057 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3967 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
| @@ -4190,26 +4100,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4190 | int err = 0; | 4100 | int err = 0; |
| 4191 | char *scontext; | 4101 | char *scontext; |
| 4192 | u32 scontext_len; | 4102 | u32 scontext_len; |
| 4193 | struct sk_security_struct *ssec; | 4103 | struct sk_security_struct *sksec = sock->sk->sk_security; |
| 4194 | struct inode_security_struct *isec; | ||
| 4195 | u32 peer_sid = SECSID_NULL; | 4104 | u32 peer_sid = SECSID_NULL; |
| 4196 | 4105 | ||
| 4197 | isec = SOCK_INODE(sock)->i_security; | 4106 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
| 4198 | 4107 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
| 4199 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4108 | peer_sid = sksec->peer_sid; |
| 4200 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4109 | if (peer_sid == SECSID_NULL) |
| 4201 | ssec = sock->sk->sk_security; | 4110 | return -ENOPROTOOPT; |
| 4202 | peer_sid = ssec->peer_sid; | ||
| 4203 | } | ||
| 4204 | if (peer_sid == SECSID_NULL) { | ||
| 4205 | err = -ENOPROTOOPT; | ||
| 4206 | goto out; | ||
| 4207 | } | ||
| 4208 | 4111 | ||
| 4209 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4112 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
| 4210 | |||
| 4211 | if (err) | 4113 | if (err) |
| 4212 | goto out; | 4114 | return err; |
| 4213 | 4115 | ||
| 4214 | if (scontext_len > len) { | 4116 | if (scontext_len > len) { |
| 4215 | err = -ERANGE; | 4117 | err = -ERANGE; |
| @@ -4222,9 +4124,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4222 | out_len: | 4124 | out_len: |
| 4223 | if (put_user(scontext_len, optlen)) | 4125 | if (put_user(scontext_len, optlen)) |
| 4224 | err = -EFAULT; | 4126 | err = -EFAULT; |
| 4225 | |||
| 4226 | kfree(scontext); | 4127 | kfree(scontext); |
| 4227 | out: | ||
| 4228 | return err; | 4128 | return err; |
| 4229 | } | 4129 | } |
| 4230 | 4130 | ||
| @@ -4256,24 +4156,39 @@ out: | |||
| 4256 | 4156 | ||
| 4257 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4157 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
| 4258 | { | 4158 | { |
| 4259 | return sk_alloc_security(sk, family, priority); | 4159 | struct sk_security_struct *sksec; |
| 4160 | |||
| 4161 | sksec = kzalloc(sizeof(*sksec), priority); | ||
| 4162 | if (!sksec) | ||
| 4163 | return -ENOMEM; | ||
| 4164 | |||
| 4165 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
| 4166 | sksec->sid = SECINITSID_UNLABELED; | ||
| 4167 | selinux_netlbl_sk_security_reset(sksec); | ||
| 4168 | sk->sk_security = sksec; | ||
| 4169 | |||
| 4170 | return 0; | ||
| 4260 | } | 4171 | } |
| 4261 | 4172 | ||
| 4262 | static void selinux_sk_free_security(struct sock *sk) | 4173 | static void selinux_sk_free_security(struct sock *sk) |
| 4263 | { | 4174 | { |
| 4264 | sk_free_security(sk); | 4175 | struct sk_security_struct *sksec = sk->sk_security; |
| 4176 | |||
| 4177 | sk->sk_security = NULL; | ||
| 4178 | selinux_netlbl_sk_security_free(sksec); | ||
| 4179 | kfree(sksec); | ||
| 4265 | } | 4180 | } |
| 4266 | 4181 | ||
| 4267 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4182 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
| 4268 | { | 4183 | { |
| 4269 | struct sk_security_struct *ssec = sk->sk_security; | 4184 | struct sk_security_struct *sksec = sk->sk_security; |
| 4270 | struct sk_security_struct *newssec = newsk->sk_security; | 4185 | struct sk_security_struct *newsksec = newsk->sk_security; |
| 4271 | 4186 | ||
| 4272 | newssec->sid = ssec->sid; | 4187 | newsksec->sid = sksec->sid; |
| 4273 | newssec->peer_sid = ssec->peer_sid; | 4188 | newsksec->peer_sid = sksec->peer_sid; |
| 4274 | newssec->sclass = ssec->sclass; | 4189 | newsksec->sclass = sksec->sclass; |
| 4275 | 4190 | ||
| 4276 | selinux_netlbl_sk_security_reset(newssec); | 4191 | selinux_netlbl_sk_security_reset(newsksec); |
| 4277 | } | 4192 | } |
| 4278 | 4193 | ||
| 4279 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4194 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
| @@ -4421,8 +4336,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4421 | int err = 0; | 4336 | int err = 0; |
| 4422 | u32 perm; | 4337 | u32 perm; |
| 4423 | struct nlmsghdr *nlh; | 4338 | struct nlmsghdr *nlh; |
| 4424 | struct socket *sock = sk->sk_socket; | 4339 | struct sk_security_struct *sksec = sk->sk_security; |
| 4425 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
| 4426 | 4340 | ||
| 4427 | if (skb->len < NLMSG_SPACE(0)) { | 4341 | if (skb->len < NLMSG_SPACE(0)) { |
| 4428 | err = -EINVAL; | 4342 | err = -EINVAL; |
| @@ -4430,13 +4344,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4430 | } | 4344 | } |
| 4431 | nlh = nlmsg_hdr(skb); | 4345 | nlh = nlmsg_hdr(skb); |
| 4432 | 4346 | ||
| 4433 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4347 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
| 4434 | if (err) { | 4348 | if (err) { |
| 4435 | if (err == -EINVAL) { | 4349 | if (err == -EINVAL) { |
| 4436 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4350 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
| 4437 | "SELinux: unrecognized netlink message" | 4351 | "SELinux: unrecognized netlink message" |
| 4438 | " type=%hu for sclass=%hu\n", | 4352 | " type=%hu for sclass=%hu\n", |
| 4439 | nlh->nlmsg_type, isec->sclass); | 4353 | nlh->nlmsg_type, sksec->sclass); |
| 4440 | if (!selinux_enforcing || security_get_allow_unknown()) | 4354 | if (!selinux_enforcing || security_get_allow_unknown()) |
| 4441 | err = 0; | 4355 | err = 0; |
| 4442 | } | 4356 | } |
| @@ -4447,7 +4361,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4447 | goto out; | 4361 | goto out; |
| 4448 | } | 4362 | } |
| 4449 | 4363 | ||
| 4450 | err = socket_has_perm(current, sock, perm); | 4364 | err = sock_has_perm(current, sk, perm); |
| 4451 | out: | 4365 | out: |
| 4452 | return err; | 4366 | return err; |
| 4453 | } | 4367 | } |
| @@ -5662,6 +5576,8 @@ static __init int selinux_init(void) | |||
| 5662 | /* Set the security state for the initial task. */ | 5576 | /* Set the security state for the initial task. */ |
| 5663 | cred_init_security(); | 5577 | cred_init_security(); |
| 5664 | 5578 | ||
| 5579 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
| 5580 | |||
| 5665 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5581 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
| 5666 | sizeof(struct inode_security_struct), | 5582 | sizeof(struct inode_security_struct), |
| 5667 | 0, SLAB_PANIC, NULL); | 5583 | 0, SLAB_PANIC, NULL); |
| @@ -5678,35 +5594,18 @@ static __init int selinux_init(void) | |||
| 5678 | return 0; | 5594 | return 0; |
| 5679 | } | 5595 | } |
| 5680 | 5596 | ||
| 5597 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
| 5598 | { | ||
| 5599 | superblock_doinit(sb, NULL); | ||
| 5600 | } | ||
| 5601 | |||
| 5681 | void selinux_complete_init(void) | 5602 | void selinux_complete_init(void) |
| 5682 | { | 5603 | { |
| 5683 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5604 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
| 5684 | 5605 | ||
| 5685 | /* Set up any superblocks initialized prior to the policy load. */ | 5606 | /* Set up any superblocks initialized prior to the policy load. */ |
| 5686 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5607 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
| 5687 | spin_lock(&sb_lock); | 5608 | 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 | } | 5609 | } |
| 5711 | 5610 | ||
| 5712 | /* SELinux requires early initialization in order to label | 5611 | /* SELinux requires early initialization in order to label |
