diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 292 |
1 files changed, 114 insertions, 178 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2a8a0a915ff3..42043f96e54f 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); |
@@ -188,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
188 | */ | 185 | */ |
189 | static inline u32 current_sid(void) | 186 | static inline u32 current_sid(void) |
190 | { | 187 | { |
191 | const struct task_security_struct *tsec = current_cred()->security; | 188 | const struct task_security_struct *tsec = current_security(); |
192 | 189 | ||
193 | return tsec->sid; | 190 | return tsec->sid; |
194 | } | 191 | } |
@@ -279,32 +276,6 @@ static void superblock_free_security(struct super_block *sb) | |||
279 | kfree(sbsec); | 276 | kfree(sbsec); |
280 | } | 277 | } |
281 | 278 | ||
282 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | ||
283 | { | ||
284 | struct sk_security_struct *sksec; | ||
285 | |||
286 | sksec = kzalloc(sizeof(*sksec), priority); | ||
287 | if (!sksec) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
291 | sksec->sid = SECINITSID_UNLABELED; | ||
292 | sk->sk_security = sksec; | ||
293 | |||
294 | selinux_netlbl_sk_security_reset(sksec); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static void sk_free_security(struct sock *sk) | ||
300 | { | ||
301 | struct sk_security_struct *sksec = sk->sk_security; | ||
302 | |||
303 | sk->sk_security = NULL; | ||
304 | selinux_netlbl_sk_security_free(sksec); | ||
305 | kfree(sksec); | ||
306 | } | ||
307 | |||
308 | /* The security server must be initialized before | 279 | /* The security server must be initialized before |
309 | any labeling or access decisions can be provided. */ | 280 | any labeling or access decisions can be provided. */ |
310 | extern int ss_initialized; | 281 | extern int ss_initialized; |
@@ -1584,8 +1555,7 @@ static int may_create(struct inode *dir, | |||
1584 | struct dentry *dentry, | 1555 | struct dentry *dentry, |
1585 | u16 tclass) | 1556 | u16 tclass) |
1586 | { | 1557 | { |
1587 | const struct cred *cred = current_cred(); | 1558 | const struct task_security_struct *tsec = current_security(); |
1588 | const struct task_security_struct *tsec = cred->security; | ||
1589 | struct inode_security_struct *dsec; | 1559 | struct inode_security_struct *dsec; |
1590 | struct superblock_security_struct *sbsec; | 1560 | struct superblock_security_struct *sbsec; |
1591 | u32 sid, newsid; | 1561 | u32 sid, newsid; |
@@ -1806,27 +1776,9 @@ static inline u32 open_file_to_av(struct file *file) | |||
1806 | { | 1776 | { |
1807 | u32 av = file_to_av(file); | 1777 | u32 av = file_to_av(file); |
1808 | 1778 | ||
1809 | if (selinux_policycap_openperm) { | 1779 | if (selinux_policycap_openperm) |
1810 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | 1780 | av |= FILE__OPEN; |
1811 | /* | 1781 | |
1812 | * lnk files and socks do not really have an 'open' | ||
1813 | */ | ||
1814 | if (S_ISREG(mode)) | ||
1815 | av |= FILE__OPEN; | ||
1816 | else if (S_ISCHR(mode)) | ||
1817 | av |= CHR_FILE__OPEN; | ||
1818 | else if (S_ISBLK(mode)) | ||
1819 | av |= BLK_FILE__OPEN; | ||
1820 | else if (S_ISFIFO(mode)) | ||
1821 | av |= FIFO_FILE__OPEN; | ||
1822 | else if (S_ISDIR(mode)) | ||
1823 | av |= DIR__OPEN; | ||
1824 | else if (S_ISSOCK(mode)) | ||
1825 | av |= SOCK_FILE__OPEN; | ||
1826 | else | ||
1827 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | ||
1828 | "unknown mode:%o\n", __func__, mode); | ||
1829 | } | ||
1830 | return av; | 1782 | return av; |
1831 | } | 1783 | } |
1832 | 1784 | ||
@@ -2183,8 +2135,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2183 | 2135 | ||
2184 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2136 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
2185 | { | 2137 | { |
2186 | const struct cred *cred = current_cred(); | 2138 | const struct task_security_struct *tsec = current_security(); |
2187 | const struct task_security_struct *tsec = cred->security; | ||
2188 | u32 sid, osid; | 2139 | u32 sid, osid; |
2189 | int atsecure = 0; | 2140 | int atsecure = 0; |
2190 | 2141 | ||
@@ -2562,8 +2513,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2562 | char **name, void **value, | 2513 | char **name, void **value, |
2563 | size_t *len) | 2514 | size_t *len) |
2564 | { | 2515 | { |
2565 | const struct cred *cred = current_cred(); | 2516 | const struct task_security_struct *tsec = current_security(); |
2566 | const struct task_security_struct *tsec = cred->security; | ||
2567 | struct inode_security_struct *dsec; | 2517 | struct inode_security_struct *dsec; |
2568 | struct superblock_security_struct *sbsec; | 2518 | struct superblock_security_struct *sbsec; |
2569 | u32 sid, newsid, clen; | 2519 | u32 sid, newsid, clen; |
@@ -2679,14 +2629,26 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2679 | static int selinux_inode_permission(struct inode *inode, int mask) | 2629 | static int selinux_inode_permission(struct inode *inode, int mask) |
2680 | { | 2630 | { |
2681 | const struct cred *cred = current_cred(); | 2631 | const struct cred *cred = current_cred(); |
2632 | struct common_audit_data ad; | ||
2633 | u32 perms; | ||
2634 | bool from_access; | ||
2682 | 2635 | ||
2683 | if (!mask) { | 2636 | from_access = mask & MAY_ACCESS; |
2684 | /* No permission to check. Existence test. */ | 2637 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
2638 | |||
2639 | /* No permission to check. Existence test. */ | ||
2640 | if (!mask) | ||
2685 | return 0; | 2641 | return 0; |
2686 | } | ||
2687 | 2642 | ||
2688 | return inode_has_perm(cred, inode, | 2643 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2689 | file_mask_to_av(inode->i_mode, mask), NULL); | 2644 | ad.u.fs.inode = inode; |
2645 | |||
2646 | if (from_access) | ||
2647 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
2648 | |||
2649 | perms = file_mask_to_av(inode->i_mode, mask); | ||
2650 | |||
2651 | return inode_has_perm(cred, inode, perms, &ad); | ||
2690 | } | 2652 | } |
2691 | 2653 | ||
2692 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2654 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
@@ -3675,71 +3637,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3675 | } | 3637 | } |
3676 | 3638 | ||
3677 | /* socket security operations */ | 3639 | /* socket security operations */ |
3678 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3640 | |
3679 | u32 perms) | 3641 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
3680 | { | 3642 | { |
3681 | struct inode_security_struct *isec; | 3643 | return tsec->sockcreate_sid ? : tsec->sid; |
3682 | struct common_audit_data ad; | 3644 | } |
3683 | u32 sid; | ||
3684 | int err = 0; | ||
3685 | 3645 | ||
3686 | isec = SOCK_INODE(sock)->i_security; | 3646 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
3647 | { | ||
3648 | struct sk_security_struct *sksec = sk->sk_security; | ||
3649 | struct common_audit_data ad; | ||
3650 | u32 tsid = task_sid(task); | ||
3687 | 3651 | ||
3688 | if (isec->sid == SECINITSID_KERNEL) | 3652 | if (sksec->sid == SECINITSID_KERNEL) |
3689 | goto out; | 3653 | return 0; |
3690 | sid = task_sid(task); | ||
3691 | 3654 | ||
3692 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3655 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3693 | ad.u.net.sk = sock->sk; | 3656 | ad.u.net.sk = sk; |
3694 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
3695 | 3657 | ||
3696 | out: | 3658 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
3697 | return err; | ||
3698 | } | 3659 | } |
3699 | 3660 | ||
3700 | static int selinux_socket_create(int family, int type, | 3661 | static int selinux_socket_create(int family, int type, |
3701 | int protocol, int kern) | 3662 | int protocol, int kern) |
3702 | { | 3663 | { |
3703 | const struct cred *cred = current_cred(); | 3664 | const struct task_security_struct *tsec = current_security(); |
3704 | const struct task_security_struct *tsec = cred->security; | 3665 | u32 newsid; |
3705 | u32 sid, newsid; | ||
3706 | u16 secclass; | 3666 | u16 secclass; |
3707 | int err = 0; | ||
3708 | 3667 | ||
3709 | if (kern) | 3668 | if (kern) |
3710 | goto out; | 3669 | return 0; |
3711 | |||
3712 | sid = tsec->sid; | ||
3713 | newsid = tsec->sockcreate_sid ?: sid; | ||
3714 | 3670 | ||
3671 | newsid = socket_sockcreate_sid(tsec); | ||
3715 | secclass = socket_type_to_security_class(family, type, protocol); | 3672 | secclass = socket_type_to_security_class(family, type, protocol); |
3716 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3673 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
3717 | |||
3718 | out: | ||
3719 | return err; | ||
3720 | } | 3674 | } |
3721 | 3675 | ||
3722 | static int selinux_socket_post_create(struct socket *sock, int family, | 3676 | static int selinux_socket_post_create(struct socket *sock, int family, |
3723 | int type, int protocol, int kern) | 3677 | int type, int protocol, int kern) |
3724 | { | 3678 | { |
3725 | const struct cred *cred = current_cred(); | 3679 | const struct task_security_struct *tsec = current_security(); |
3726 | const struct task_security_struct *tsec = cred->security; | 3680 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
3727 | struct inode_security_struct *isec; | ||
3728 | struct sk_security_struct *sksec; | 3681 | struct sk_security_struct *sksec; |
3729 | u32 sid, newsid; | ||
3730 | int err = 0; | 3682 | int err = 0; |
3731 | 3683 | ||
3732 | sid = tsec->sid; | ||
3733 | newsid = tsec->sockcreate_sid; | ||
3734 | |||
3735 | isec = SOCK_INODE(sock)->i_security; | ||
3736 | |||
3737 | if (kern) | 3684 | if (kern) |
3738 | isec->sid = SECINITSID_KERNEL; | 3685 | isec->sid = SECINITSID_KERNEL; |
3739 | else if (newsid) | ||
3740 | isec->sid = newsid; | ||
3741 | else | 3686 | else |
3742 | isec->sid = sid; | 3687 | isec->sid = socket_sockcreate_sid(tsec); |
3743 | 3688 | ||
3744 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3689 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
3745 | isec->initialized = 1; | 3690 | isec->initialized = 1; |
@@ -3760,10 +3705,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3760 | 3705 | ||
3761 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3706 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3762 | { | 3707 | { |
3708 | struct sock *sk = sock->sk; | ||
3763 | u16 family; | 3709 | u16 family; |
3764 | int err; | 3710 | int err; |
3765 | 3711 | ||
3766 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3712 | err = sock_has_perm(current, sk, SOCKET__BIND); |
3767 | if (err) | 3713 | if (err) |
3768 | goto out; | 3714 | goto out; |
3769 | 3715 | ||
@@ -3772,19 +3718,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3772 | * Multiple address binding for SCTP is not supported yet: we just | 3718 | * Multiple address binding for SCTP is not supported yet: we just |
3773 | * check the first address now. | 3719 | * check the first address now. |
3774 | */ | 3720 | */ |
3775 | family = sock->sk->sk_family; | 3721 | family = sk->sk_family; |
3776 | if (family == PF_INET || family == PF_INET6) { | 3722 | if (family == PF_INET || family == PF_INET6) { |
3777 | char *addrp; | 3723 | char *addrp; |
3778 | struct inode_security_struct *isec; | 3724 | struct sk_security_struct *sksec = sk->sk_security; |
3779 | struct common_audit_data ad; | 3725 | struct common_audit_data ad; |
3780 | struct sockaddr_in *addr4 = NULL; | 3726 | struct sockaddr_in *addr4 = NULL; |
3781 | struct sockaddr_in6 *addr6 = NULL; | 3727 | struct sockaddr_in6 *addr6 = NULL; |
3782 | unsigned short snum; | 3728 | unsigned short snum; |
3783 | struct sock *sk = sock->sk; | ||
3784 | u32 sid, node_perm; | 3729 | u32 sid, node_perm; |
3785 | 3730 | ||
3786 | isec = SOCK_INODE(sock)->i_security; | ||
3787 | |||
3788 | if (family == PF_INET) { | 3731 | if (family == PF_INET) { |
3789 | addr4 = (struct sockaddr_in *)address; | 3732 | addr4 = (struct sockaddr_in *)address; |
3790 | snum = ntohs(addr4->sin_port); | 3733 | snum = ntohs(addr4->sin_port); |
@@ -3808,15 +3751,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3808 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3751 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3809 | ad.u.net.sport = htons(snum); | 3752 | ad.u.net.sport = htons(snum); |
3810 | ad.u.net.family = family; | 3753 | ad.u.net.family = family; |
3811 | err = avc_has_perm(isec->sid, sid, | 3754 | err = avc_has_perm(sksec->sid, sid, |
3812 | isec->sclass, | 3755 | sksec->sclass, |
3813 | SOCKET__NAME_BIND, &ad); | 3756 | SOCKET__NAME_BIND, &ad); |
3814 | if (err) | 3757 | if (err) |
3815 | goto out; | 3758 | goto out; |
3816 | } | 3759 | } |
3817 | } | 3760 | } |
3818 | 3761 | ||
3819 | switch (isec->sclass) { | 3762 | switch (sksec->sclass) { |
3820 | case SECCLASS_TCP_SOCKET: | 3763 | case SECCLASS_TCP_SOCKET: |
3821 | node_perm = TCP_SOCKET__NODE_BIND; | 3764 | node_perm = TCP_SOCKET__NODE_BIND; |
3822 | break; | 3765 | break; |
@@ -3847,8 +3790,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3847 | else | 3790 | else |
3848 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3791 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
3849 | 3792 | ||
3850 | err = avc_has_perm(isec->sid, sid, | 3793 | err = avc_has_perm(sksec->sid, sid, |
3851 | isec->sclass, node_perm, &ad); | 3794 | sksec->sclass, node_perm, &ad); |
3852 | if (err) | 3795 | if (err) |
3853 | goto out; | 3796 | goto out; |
3854 | } | 3797 | } |
@@ -3859,19 +3802,18 @@ out: | |||
3859 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3802 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3860 | { | 3803 | { |
3861 | struct sock *sk = sock->sk; | 3804 | struct sock *sk = sock->sk; |
3862 | struct inode_security_struct *isec; | 3805 | struct sk_security_struct *sksec = sk->sk_security; |
3863 | int err; | 3806 | int err; |
3864 | 3807 | ||
3865 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3808 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
3866 | if (err) | 3809 | if (err) |
3867 | return err; | 3810 | return err; |
3868 | 3811 | ||
3869 | /* | 3812 | /* |
3870 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3813 | * If a TCP or DCCP socket, check name_connect permission for the port. |
3871 | */ | 3814 | */ |
3872 | isec = SOCK_INODE(sock)->i_security; | 3815 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3873 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3816 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3874 | isec->sclass == SECCLASS_DCCP_SOCKET) { | ||
3875 | struct common_audit_data ad; | 3817 | struct common_audit_data ad; |
3876 | struct sockaddr_in *addr4 = NULL; | 3818 | struct sockaddr_in *addr4 = NULL; |
3877 | struct sockaddr_in6 *addr6 = NULL; | 3819 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3894,13 +3836,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3894 | if (err) | 3836 | if (err) |
3895 | goto out; | 3837 | goto out; |
3896 | 3838 | ||
3897 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3839 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3898 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3840 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3899 | 3841 | ||
3900 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3842 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3901 | ad.u.net.dport = htons(snum); | 3843 | ad.u.net.dport = htons(snum); |
3902 | ad.u.net.family = sk->sk_family; | 3844 | ad.u.net.family = sk->sk_family; |
3903 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3845 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
3904 | if (err) | 3846 | if (err) |
3905 | goto out; | 3847 | goto out; |
3906 | } | 3848 | } |
@@ -3913,7 +3855,7 @@ out: | |||
3913 | 3855 | ||
3914 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3856 | static int selinux_socket_listen(struct socket *sock, int backlog) |
3915 | { | 3857 | { |
3916 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3858 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
3917 | } | 3859 | } |
3918 | 3860 | ||
3919 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3861 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
@@ -3922,7 +3864,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3922 | struct inode_security_struct *isec; | 3864 | struct inode_security_struct *isec; |
3923 | struct inode_security_struct *newisec; | 3865 | struct inode_security_struct *newisec; |
3924 | 3866 | ||
3925 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3867 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
3926 | if (err) | 3868 | if (err) |
3927 | return err; | 3869 | return err; |
3928 | 3870 | ||
@@ -3939,30 +3881,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3939 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3881 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
3940 | int size) | 3882 | int size) |
3941 | { | 3883 | { |
3942 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3884 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
3943 | } | 3885 | } |
3944 | 3886 | ||
3945 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3887 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
3946 | int size, int flags) | 3888 | int size, int flags) |
3947 | { | 3889 | { |
3948 | return socket_has_perm(current, sock, SOCKET__READ); | 3890 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
3949 | } | 3891 | } |
3950 | 3892 | ||
3951 | static int selinux_socket_getsockname(struct socket *sock) | 3893 | static int selinux_socket_getsockname(struct socket *sock) |
3952 | { | 3894 | { |
3953 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3895 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3954 | } | 3896 | } |
3955 | 3897 | ||
3956 | static int selinux_socket_getpeername(struct socket *sock) | 3898 | static int selinux_socket_getpeername(struct socket *sock) |
3957 | { | 3899 | { |
3958 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3900 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3959 | } | 3901 | } |
3960 | 3902 | ||
3961 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3903 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
3962 | { | 3904 | { |
3963 | int err; | 3905 | int err; |
3964 | 3906 | ||
3965 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3907 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
3966 | if (err) | 3908 | if (err) |
3967 | return err; | 3909 | return err; |
3968 | 3910 | ||
@@ -3972,68 +3914,58 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
3972 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3914 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
3973 | int optname) | 3915 | int optname) |
3974 | { | 3916 | { |
3975 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3917 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
3976 | } | 3918 | } |
3977 | 3919 | ||
3978 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3920 | static int selinux_socket_shutdown(struct socket *sock, int how) |
3979 | { | 3921 | { |
3980 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3922 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
3981 | } | 3923 | } |
3982 | 3924 | ||
3983 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3925 | static int selinux_socket_unix_stream_connect(struct socket *sock, |
3984 | struct socket *other, | 3926 | struct socket *other, |
3985 | struct sock *newsk) | 3927 | struct sock *newsk) |
3986 | { | 3928 | { |
3987 | struct sk_security_struct *sksec; | 3929 | struct sk_security_struct *sksec_sock = sock->sk->sk_security; |
3988 | struct inode_security_struct *isec; | 3930 | struct sk_security_struct *sksec_other = other->sk->sk_security; |
3989 | struct inode_security_struct *other_isec; | 3931 | struct sk_security_struct *sksec_new = newsk->sk_security; |
3990 | struct common_audit_data ad; | 3932 | struct common_audit_data ad; |
3991 | int err; | 3933 | int err; |
3992 | 3934 | ||
3993 | isec = SOCK_INODE(sock)->i_security; | ||
3994 | other_isec = SOCK_INODE(other)->i_security; | ||
3995 | |||
3996 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3935 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3997 | ad.u.net.sk = other->sk; | 3936 | ad.u.net.sk = other->sk; |
3998 | 3937 | ||
3999 | err = avc_has_perm(isec->sid, other_isec->sid, | 3938 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
4000 | isec->sclass, | 3939 | sksec_other->sclass, |
4001 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3940 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
4002 | if (err) | 3941 | if (err) |
4003 | return err; | 3942 | return err; |
4004 | 3943 | ||
4005 | /* connecting socket */ | ||
4006 | sksec = sock->sk->sk_security; | ||
4007 | sksec->peer_sid = other_isec->sid; | ||
4008 | |||
4009 | /* server child socket */ | 3944 | /* server child socket */ |
4010 | sksec = newsk->sk_security; | 3945 | sksec_new->peer_sid = sksec_sock->sid; |
4011 | sksec->peer_sid = isec->sid; | 3946 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
4012 | err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); | 3947 | &sksec_new->sid); |
3948 | if (err) | ||
3949 | return err; | ||
4013 | 3950 | ||
4014 | return err; | 3951 | /* connecting socket */ |
3952 | sksec_sock->peer_sid = sksec_new->sid; | ||
3953 | |||
3954 | return 0; | ||
4015 | } | 3955 | } |
4016 | 3956 | ||
4017 | static int selinux_socket_unix_may_send(struct socket *sock, | 3957 | static int selinux_socket_unix_may_send(struct socket *sock, |
4018 | struct socket *other) | 3958 | struct socket *other) |
4019 | { | 3959 | { |
4020 | struct inode_security_struct *isec; | 3960 | struct sk_security_struct *ssec = sock->sk->sk_security; |
4021 | struct inode_security_struct *other_isec; | 3961 | struct sk_security_struct *osec = other->sk->sk_security; |
4022 | struct common_audit_data ad; | 3962 | struct common_audit_data ad; |
4023 | int err; | ||
4024 | |||
4025 | isec = SOCK_INODE(sock)->i_security; | ||
4026 | other_isec = SOCK_INODE(other)->i_security; | ||
4027 | 3963 | ||
4028 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3964 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4029 | ad.u.net.sk = other->sk; | 3965 | ad.u.net.sk = other->sk; |
4030 | 3966 | ||
4031 | err = avc_has_perm(isec->sid, other_isec->sid, | 3967 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
4032 | isec->sclass, SOCKET__SENDTO, &ad); | 3968 | &ad); |
4033 | if (err) | ||
4034 | return err; | ||
4035 | |||
4036 | return 0; | ||
4037 | } | 3969 | } |
4038 | 3970 | ||
4039 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3971 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
@@ -4172,26 +4104,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4172 | int err = 0; | 4104 | int err = 0; |
4173 | char *scontext; | 4105 | char *scontext; |
4174 | u32 scontext_len; | 4106 | u32 scontext_len; |
4175 | struct sk_security_struct *sksec; | 4107 | struct sk_security_struct *sksec = sock->sk->sk_security; |
4176 | struct inode_security_struct *isec; | ||
4177 | u32 peer_sid = SECSID_NULL; | 4108 | u32 peer_sid = SECSID_NULL; |
4178 | 4109 | ||
4179 | isec = SOCK_INODE(sock)->i_security; | 4110 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4180 | 4111 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
4181 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | ||
4182 | isec->sclass == SECCLASS_TCP_SOCKET) { | ||
4183 | sksec = sock->sk->sk_security; | ||
4184 | peer_sid = sksec->peer_sid; | 4112 | peer_sid = sksec->peer_sid; |
4185 | } | 4113 | if (peer_sid == SECSID_NULL) |
4186 | if (peer_sid == SECSID_NULL) { | 4114 | return -ENOPROTOOPT; |
4187 | err = -ENOPROTOOPT; | ||
4188 | goto out; | ||
4189 | } | ||
4190 | 4115 | ||
4191 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4116 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
4192 | |||
4193 | if (err) | 4117 | if (err) |
4194 | goto out; | 4118 | return err; |
4195 | 4119 | ||
4196 | if (scontext_len > len) { | 4120 | if (scontext_len > len) { |
4197 | err = -ERANGE; | 4121 | err = -ERANGE; |
@@ -4204,9 +4128,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4204 | out_len: | 4128 | out_len: |
4205 | if (put_user(scontext_len, optlen)) | 4129 | if (put_user(scontext_len, optlen)) |
4206 | err = -EFAULT; | 4130 | err = -EFAULT; |
4207 | |||
4208 | kfree(scontext); | 4131 | kfree(scontext); |
4209 | out: | ||
4210 | return err; | 4132 | return err; |
4211 | } | 4133 | } |
4212 | 4134 | ||
@@ -4238,12 +4160,27 @@ out: | |||
4238 | 4160 | ||
4239 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4161 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
4240 | { | 4162 | { |
4241 | return sk_alloc_security(sk, family, priority); | 4163 | struct sk_security_struct *sksec; |
4164 | |||
4165 | sksec = kzalloc(sizeof(*sksec), priority); | ||
4166 | if (!sksec) | ||
4167 | return -ENOMEM; | ||
4168 | |||
4169 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
4170 | sksec->sid = SECINITSID_UNLABELED; | ||
4171 | selinux_netlbl_sk_security_reset(sksec); | ||
4172 | sk->sk_security = sksec; | ||
4173 | |||
4174 | return 0; | ||
4242 | } | 4175 | } |
4243 | 4176 | ||
4244 | static void selinux_sk_free_security(struct sock *sk) | 4177 | static void selinux_sk_free_security(struct sock *sk) |
4245 | { | 4178 | { |
4246 | sk_free_security(sk); | 4179 | struct sk_security_struct *sksec = sk->sk_security; |
4180 | |||
4181 | sk->sk_security = NULL; | ||
4182 | selinux_netlbl_sk_security_free(sksec); | ||
4183 | kfree(sksec); | ||
4247 | } | 4184 | } |
4248 | 4185 | ||
4249 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4186 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
@@ -4403,8 +4340,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4403 | int err = 0; | 4340 | int err = 0; |
4404 | u32 perm; | 4341 | u32 perm; |
4405 | struct nlmsghdr *nlh; | 4342 | struct nlmsghdr *nlh; |
4406 | struct socket *sock = sk->sk_socket; | 4343 | struct sk_security_struct *sksec = sk->sk_security; |
4407 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
4408 | 4344 | ||
4409 | if (skb->len < NLMSG_SPACE(0)) { | 4345 | if (skb->len < NLMSG_SPACE(0)) { |
4410 | err = -EINVAL; | 4346 | err = -EINVAL; |
@@ -4412,13 +4348,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4412 | } | 4348 | } |
4413 | nlh = nlmsg_hdr(skb); | 4349 | nlh = nlmsg_hdr(skb); |
4414 | 4350 | ||
4415 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4351 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
4416 | if (err) { | 4352 | if (err) { |
4417 | if (err == -EINVAL) { | 4353 | if (err == -EINVAL) { |
4418 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4354 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
4419 | "SELinux: unrecognized netlink message" | 4355 | "SELinux: unrecognized netlink message" |
4420 | " type=%hu for sclass=%hu\n", | 4356 | " type=%hu for sclass=%hu\n", |
4421 | nlh->nlmsg_type, isec->sclass); | 4357 | nlh->nlmsg_type, sksec->sclass); |
4422 | if (!selinux_enforcing || security_get_allow_unknown()) | 4358 | if (!selinux_enforcing || security_get_allow_unknown()) |
4423 | err = 0; | 4359 | err = 0; |
4424 | } | 4360 | } |
@@ -4429,7 +4365,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4429 | goto out; | 4365 | goto out; |
4430 | } | 4366 | } |
4431 | 4367 | ||
4432 | err = socket_has_perm(current, sock, perm); | 4368 | err = sock_has_perm(current, sk, perm); |
4433 | out: | 4369 | out: |
4434 | return err; | 4370 | return err; |
4435 | } | 4371 | } |