aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2010-04-22 14:46:19 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:34:39 -0400
commit253bfae6e0ad97554799affa0266052968a45808 (patch)
treec3599a18f06664160a55a20b30428ba4faf6e2c0 /security/selinux/hooks.c
parent84914b7ed1c5e0f3199a5a6997022758a70fcaff (diff)
selinux: Convert socket related access controls to use socket labels
At present, the socket related access controls use a mix of inode and socket labels; while there should be no practical difference (they _should_ always be the same), it makes the code more confusing. This patch attempts to convert all of the socket related access control points (with the exception of some of the inode/fd based controls) to use the socket's own label. In the process, I also converted the socket_has_perm() function to take a 'sock' argument instead of a 'socket' since that was adding a bit more overhead in some cases. Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/hooks.c')
-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}