diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 347 |
1 files changed, 122 insertions, 225 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a03fd74602b4..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,42 +272,10 @@ 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 *sksec; | ||
297 | |||
298 | sksec = kzalloc(sizeof(*sksec), priority); | ||
299 | if (!sksec) | ||
300 | return -ENOMEM; | ||
301 | |||
302 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
303 | sksec->sid = SECINITSID_UNLABELED; | ||
304 | sk->sk_security = sksec; | ||
305 | |||
306 | selinux_netlbl_sk_security_reset(sksec); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static void sk_free_security(struct sock *sk) | ||
312 | { | ||
313 | struct sk_security_struct *sksec = sk->sk_security; | ||
314 | |||
315 | sk->sk_security = NULL; | ||
316 | selinux_netlbl_sk_security_free(sksec); | ||
317 | kfree(sksec); | ||
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; |
@@ -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) |
@@ -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 *sksec; | 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 | sksec = sock->sk->sk_security; | ||
4025 | sksec->peer_sid = other_isec->sid; | ||
4026 | |||
4027 | /* server child socket */ | 3940 | /* server child socket */ |
4028 | sksec = newsk->sk_security; | 3941 | sksec_new->peer_sid = sksec_sock->sid; |
4029 | sksec->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, sksec->peer_sid, &sksec->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 *sksec; | 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 || | ||
4200 | isec->sclass == SECCLASS_TCP_SOCKET) { | ||
4201 | sksec = sock->sk->sk_security; | ||
4202 | peer_sid = sksec->peer_sid; | 4108 | peer_sid = sksec->peer_sid; |
4203 | } | 4109 | if (peer_sid == SECSID_NULL) |
4204 | if (peer_sid == SECSID_NULL) { | 4110 | return -ENOPROTOOPT; |
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,12 +4156,27 @@ 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) |
@@ -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 | } |
@@ -5680,35 +5594,18 @@ static __init int selinux_init(void) | |||
5680 | return 0; | 5594 | return 0; |
5681 | } | 5595 | } |
5682 | 5596 | ||
5597 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
5598 | { | ||
5599 | superblock_doinit(sb, NULL); | ||
5600 | } | ||
5601 | |||
5683 | void selinux_complete_init(void) | 5602 | void selinux_complete_init(void) |
5684 | { | 5603 | { |
5685 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5604 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
5686 | 5605 | ||
5687 | /* Set up any superblocks initialized prior to the policy load. */ | 5606 | /* Set up any superblocks initialized prior to the policy load. */ |
5688 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5607 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
5689 | spin_lock(&sb_lock); | 5608 | iterate_supers(delayed_superblock_init, NULL); |
5690 | spin_lock(&sb_security_lock); | ||
5691 | next_sb: | ||
5692 | if (!list_empty(&superblock_security_head)) { | ||
5693 | struct superblock_security_struct *sbsec = | ||
5694 | list_entry(superblock_security_head.next, | ||
5695 | struct superblock_security_struct, | ||
5696 | list); | ||
5697 | struct super_block *sb = sbsec->sb; | ||
5698 | sb->s_count++; | ||
5699 | spin_unlock(&sb_security_lock); | ||
5700 | spin_unlock(&sb_lock); | ||
5701 | down_read(&sb->s_umount); | ||
5702 | if (sb->s_root) | ||
5703 | superblock_doinit(sb, NULL); | ||
5704 | drop_super(sb); | ||
5705 | spin_lock(&sb_lock); | ||
5706 | spin_lock(&sb_security_lock); | ||
5707 | list_del_init(&sbsec->list); | ||
5708 | goto next_sb; | ||
5709 | } | ||
5710 | spin_unlock(&sb_security_lock); | ||
5711 | spin_unlock(&sb_lock); | ||
5712 | } | 5609 | } |
5713 | 5610 | ||
5714 | /* SELinux requires early initialization in order to label | 5611 | /* SELinux requires early initialization in order to label |