aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c119
1 files changed, 45 insertions, 74 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 01f52424cfe5..e95004010c8b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3651,26 +3651,19 @@ static u32 socket_sockcreate_sid(const struct task_security_struct *tsec)
3651 return tsec->sockcreate_sid ? : tsec->sid; 3651 return tsec->sockcreate_sid ? : tsec->sid;
3652} 3652}
3653 3653
3654static int socket_has_perm(struct task_struct *task, struct socket *sock, 3654static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
3655 u32 perms)
3656{ 3655{
3657 struct inode_security_struct *isec; 3656 struct sk_security_struct *sksec = sk->sk_security;
3658 struct common_audit_data ad; 3657 struct common_audit_data ad;
3659 u32 sid; 3658 u32 tsid = task_sid(task);
3660 int err = 0;
3661 3659
3662 isec = SOCK_INODE(sock)->i_security; 3660 if (sksec->sid == SECINITSID_KERNEL)
3663 3661 return 0;
3664 if (isec->sid == SECINITSID_KERNEL)
3665 goto out;
3666 sid = task_sid(task);
3667 3662
3668 COMMON_AUDIT_DATA_INIT(&ad, NET); 3663 COMMON_AUDIT_DATA_INIT(&ad, NET);
3669 ad.u.net.sk = sock->sk; 3664 ad.u.net.sk = sk;
3670 err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
3671 3665
3672out: 3666 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
3673 return err;
3674} 3667}
3675 3668
3676static int selinux_socket_create(int family, int type, 3669static int selinux_socket_create(int family, int type,
@@ -3722,10 +3715,11 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3722 3715
3723static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) 3716static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3724{ 3717{
3718 struct sock *sk = sock->sk;
3725 u16 family; 3719 u16 family;
3726 int err; 3720 int err;
3727 3721
3728 err = socket_has_perm(current, sock, SOCKET__BIND); 3722 err = sock_has_perm(current, sk, SOCKET__BIND);
3729 if (err) 3723 if (err)
3730 goto out; 3724 goto out;
3731 3725
@@ -3734,19 +3728,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3734 * Multiple address binding for SCTP is not supported yet: we just 3728 * Multiple address binding for SCTP is not supported yet: we just
3735 * check the first address now. 3729 * check the first address now.
3736 */ 3730 */
3737 family = sock->sk->sk_family; 3731 family = sk->sk_family;
3738 if (family == PF_INET || family == PF_INET6) { 3732 if (family == PF_INET || family == PF_INET6) {
3739 char *addrp; 3733 char *addrp;
3740 struct inode_security_struct *isec; 3734 struct sk_security_struct *sksec = sk->sk_security;
3741 struct common_audit_data ad; 3735 struct common_audit_data ad;
3742 struct sockaddr_in *addr4 = NULL; 3736 struct sockaddr_in *addr4 = NULL;
3743 struct sockaddr_in6 *addr6 = NULL; 3737 struct sockaddr_in6 *addr6 = NULL;
3744 unsigned short snum; 3738 unsigned short snum;
3745 struct sock *sk = sock->sk;
3746 u32 sid, node_perm; 3739 u32 sid, node_perm;
3747 3740
3748 isec = SOCK_INODE(sock)->i_security;
3749
3750 if (family == PF_INET) { 3741 if (family == PF_INET) {
3751 addr4 = (struct sockaddr_in *)address; 3742 addr4 = (struct sockaddr_in *)address;
3752 snum = ntohs(addr4->sin_port); 3743 snum = ntohs(addr4->sin_port);
@@ -3770,15 +3761,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3770 COMMON_AUDIT_DATA_INIT(&ad, NET); 3761 COMMON_AUDIT_DATA_INIT(&ad, NET);
3771 ad.u.net.sport = htons(snum); 3762 ad.u.net.sport = htons(snum);
3772 ad.u.net.family = family; 3763 ad.u.net.family = family;
3773 err = avc_has_perm(isec->sid, sid, 3764 err = avc_has_perm(sksec->sid, sid,
3774 isec->sclass, 3765 sksec->sclass,
3775 SOCKET__NAME_BIND, &ad); 3766 SOCKET__NAME_BIND, &ad);
3776 if (err) 3767 if (err)
3777 goto out; 3768 goto out;
3778 } 3769 }
3779 } 3770 }
3780 3771
3781 switch (isec->sclass) { 3772 switch (sksec->sclass) {
3782 case SECCLASS_TCP_SOCKET: 3773 case SECCLASS_TCP_SOCKET:
3783 node_perm = TCP_SOCKET__NODE_BIND; 3774 node_perm = TCP_SOCKET__NODE_BIND;
3784 break; 3775 break;
@@ -3809,8 +3800,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3809 else 3800 else
3810 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); 3801 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3811 3802
3812 err = avc_has_perm(isec->sid, sid, 3803 err = avc_has_perm(sksec->sid, sid,
3813 isec->sclass, node_perm, &ad); 3804 sksec->sclass, node_perm, &ad);
3814 if (err) 3805 if (err)
3815 goto out; 3806 goto out;
3816 } 3807 }
@@ -3821,19 +3812,18 @@ out:
3821static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 3812static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3822{ 3813{
3823 struct sock *sk = sock->sk; 3814 struct sock *sk = sock->sk;
3824 struct inode_security_struct *isec; 3815 struct sk_security_struct *sksec = sk->sk_security;
3825 int err; 3816 int err;
3826 3817
3827 err = socket_has_perm(current, sock, SOCKET__CONNECT); 3818 err = sock_has_perm(current, sk, SOCKET__CONNECT);
3828 if (err) 3819 if (err)
3829 return err; 3820 return err;
3830 3821
3831 /* 3822 /*
3832 * If a TCP or DCCP socket, check name_connect permission for the port. 3823 * If a TCP or DCCP socket, check name_connect permission for the port.
3833 */ 3824 */
3834 isec = SOCK_INODE(sock)->i_security; 3825 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3835 if (isec->sclass == SECCLASS_TCP_SOCKET || 3826 sksec->sclass == SECCLASS_DCCP_SOCKET) {
3836 isec->sclass == SECCLASS_DCCP_SOCKET) {
3837 struct common_audit_data ad; 3827 struct common_audit_data ad;
3838 struct sockaddr_in *addr4 = NULL; 3828 struct sockaddr_in *addr4 = NULL;
3839 struct sockaddr_in6 *addr6 = NULL; 3829 struct sockaddr_in6 *addr6 = NULL;
@@ -3856,13 +3846,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3856 if (err) 3846 if (err)
3857 goto out; 3847 goto out;
3858 3848
3859 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? 3849 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
3860 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; 3850 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3861 3851
3862 COMMON_AUDIT_DATA_INIT(&ad, NET); 3852 COMMON_AUDIT_DATA_INIT(&ad, NET);
3863 ad.u.net.dport = htons(snum); 3853 ad.u.net.dport = htons(snum);
3864 ad.u.net.family = sk->sk_family; 3854 ad.u.net.family = sk->sk_family;
3865 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); 3855 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
3866 if (err) 3856 if (err)
3867 goto out; 3857 goto out;
3868 } 3858 }
@@ -3875,7 +3865,7 @@ out:
3875 3865
3876static int selinux_socket_listen(struct socket *sock, int backlog) 3866static int selinux_socket_listen(struct socket *sock, int backlog)
3877{ 3867{
3878 return socket_has_perm(current, sock, SOCKET__LISTEN); 3868 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
3879} 3869}
3880 3870
3881static int selinux_socket_accept(struct socket *sock, struct socket *newsock) 3871static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
@@ -3884,7 +3874,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3884 struct inode_security_struct *isec; 3874 struct inode_security_struct *isec;
3885 struct inode_security_struct *newisec; 3875 struct inode_security_struct *newisec;
3886 3876
3887 err = socket_has_perm(current, sock, SOCKET__ACCEPT); 3877 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
3888 if (err) 3878 if (err)
3889 return err; 3879 return err;
3890 3880
@@ -3901,30 +3891,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3901static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3891static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3902 int size) 3892 int size)
3903{ 3893{
3904 return socket_has_perm(current, sock, SOCKET__WRITE); 3894 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
3905} 3895}
3906 3896
3907static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3897static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3908 int size, int flags) 3898 int size, int flags)
3909{ 3899{
3910 return socket_has_perm(current, sock, SOCKET__READ); 3900 return sock_has_perm(current, sock->sk, SOCKET__READ);
3911} 3901}
3912 3902
3913static int selinux_socket_getsockname(struct socket *sock) 3903static int selinux_socket_getsockname(struct socket *sock)
3914{ 3904{
3915 return socket_has_perm(current, sock, SOCKET__GETATTR); 3905 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
3916} 3906}
3917 3907
3918static int selinux_socket_getpeername(struct socket *sock) 3908static int selinux_socket_getpeername(struct socket *sock)
3919{ 3909{
3920 return socket_has_perm(current, sock, SOCKET__GETATTR); 3910 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
3921} 3911}
3922 3912
3923static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) 3913static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
3924{ 3914{
3925 int err; 3915 int err;
3926 3916
3927 err = socket_has_perm(current, sock, SOCKET__SETOPT); 3917 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
3928 if (err) 3918 if (err)
3929 return err; 3919 return err;
3930 3920
@@ -3934,12 +3924,12 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
3934static int selinux_socket_getsockopt(struct socket *sock, int level, 3924static int selinux_socket_getsockopt(struct socket *sock, int level,
3935 int optname) 3925 int optname)
3936{ 3926{
3937 return socket_has_perm(current, sock, SOCKET__GETOPT); 3927 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
3938} 3928}
3939 3929
3940static int selinux_socket_shutdown(struct socket *sock, int how) 3930static int selinux_socket_shutdown(struct socket *sock, int how)
3941{ 3931{
3942 return socket_has_perm(current, sock, SOCKET__SHUTDOWN); 3932 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
3943} 3933}
3944 3934
3945static int selinux_socket_unix_stream_connect(struct socket *sock, 3935static int selinux_socket_unix_stream_connect(struct socket *sock,
@@ -3977,23 +3967,15 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
3977static int selinux_socket_unix_may_send(struct socket *sock, 3967static int selinux_socket_unix_may_send(struct socket *sock,
3978 struct socket *other) 3968 struct socket *other)
3979{ 3969{
3980 struct inode_security_struct *isec; 3970 struct sk_security_struct *ssec = sock->sk->sk_security;
3981 struct inode_security_struct *other_isec; 3971 struct sk_security_struct *osec = other->sk->sk_security;
3982 struct common_audit_data ad; 3972 struct common_audit_data ad;
3983 int err;
3984
3985 isec = SOCK_INODE(sock)->i_security;
3986 other_isec = SOCK_INODE(other)->i_security;
3987 3973
3988 COMMON_AUDIT_DATA_INIT(&ad, NET); 3974 COMMON_AUDIT_DATA_INIT(&ad, NET);
3989 ad.u.net.sk = other->sk; 3975 ad.u.net.sk = other->sk;
3990 3976
3991 err = avc_has_perm(isec->sid, other_isec->sid, 3977 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
3992 isec->sclass, SOCKET__SENDTO, &ad); 3978 &ad);
3993 if (err)
3994 return err;
3995
3996 return 0;
3997} 3979}
3998 3980
3999static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, 3981static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
@@ -4132,26 +4114,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
4132 int err = 0; 4114 int err = 0;
4133 char *scontext; 4115 char *scontext;
4134 u32 scontext_len; 4116 u32 scontext_len;
4135 struct sk_security_struct *sksec; 4117 struct sk_security_struct *sksec = sock->sk->sk_security;
4136 struct inode_security_struct *isec;
4137 u32 peer_sid = SECSID_NULL; 4118 u32 peer_sid = SECSID_NULL;
4138 4119
4139 isec = SOCK_INODE(sock)->i_security; 4120 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4140 4121 sksec->sclass == SECCLASS_TCP_SOCKET)
4141 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4142 isec->sclass == SECCLASS_TCP_SOCKET) {
4143 sksec = sock->sk->sk_security;
4144 peer_sid = sksec->peer_sid; 4122 peer_sid = sksec->peer_sid;
4145 } 4123 if (peer_sid == SECSID_NULL)
4146 if (peer_sid == SECSID_NULL) { 4124 return -ENOPROTOOPT;
4147 err = -ENOPROTOOPT;
4148 goto out;
4149 }
4150 4125
4151 err = security_sid_to_context(peer_sid, &scontext, &scontext_len); 4126 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4152
4153 if (err) 4127 if (err)
4154 goto out; 4128 return err;
4155 4129
4156 if (scontext_len > len) { 4130 if (scontext_len > len) {
4157 err = -ERANGE; 4131 err = -ERANGE;
@@ -4164,9 +4138,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
4164out_len: 4138out_len:
4165 if (put_user(scontext_len, optlen)) 4139 if (put_user(scontext_len, optlen))
4166 err = -EFAULT; 4140 err = -EFAULT;
4167
4168 kfree(scontext); 4141 kfree(scontext);
4169out:
4170 return err; 4142 return err;
4171} 4143}
4172 4144
@@ -4378,8 +4350,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4378 int err = 0; 4350 int err = 0;
4379 u32 perm; 4351 u32 perm;
4380 struct nlmsghdr *nlh; 4352 struct nlmsghdr *nlh;
4381 struct socket *sock = sk->sk_socket; 4353 struct sk_security_struct *sksec = sk->sk_security;
4382 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4383 4354
4384 if (skb->len < NLMSG_SPACE(0)) { 4355 if (skb->len < NLMSG_SPACE(0)) {
4385 err = -EINVAL; 4356 err = -EINVAL;
@@ -4387,13 +4358,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4387 } 4358 }
4388 nlh = nlmsg_hdr(skb); 4359 nlh = nlmsg_hdr(skb);
4389 4360
4390 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); 4361 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
4391 if (err) { 4362 if (err) {
4392 if (err == -EINVAL) { 4363 if (err == -EINVAL) {
4393 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, 4364 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
4394 "SELinux: unrecognized netlink message" 4365 "SELinux: unrecognized netlink message"
4395 " type=%hu for sclass=%hu\n", 4366 " type=%hu for sclass=%hu\n",
4396 nlh->nlmsg_type, isec->sclass); 4367 nlh->nlmsg_type, sksec->sclass);
4397 if (!selinux_enforcing || security_get_allow_unknown()) 4368 if (!selinux_enforcing || security_get_allow_unknown())
4398 err = 0; 4369 err = 0;
4399 } 4370 }
@@ -4404,7 +4375,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4404 goto out; 4375 goto out;
4405 } 4376 }
4406 4377
4407 err = socket_has_perm(current, sock, perm); 4378 err = sock_has_perm(current, sk, perm);
4408out: 4379out:
4409 return err; 4380 return err;
4410} 4381}