aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c667
1 files changed, 450 insertions, 217 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 64d414efb40..be6de0b8734 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -12,8 +12,8 @@
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com> 14 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 15 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
16 * Paul Moore, <paul.moore@hp.com> 16 * Paul Moore <paul.moore@hp.com>
17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. 17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
18 * Yuichi Nakamura <ynakam@hitachisoft.jp> 18 * Yuichi Nakamura <ynakam@hitachisoft.jp>
19 * 19 *
@@ -50,8 +50,11 @@
50#include <net/icmp.h> 50#include <net/icmp.h>
51#include <net/ip.h> /* for local_port_range[] */ 51#include <net/ip.h> /* for local_port_range[] */
52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
53#include <net/net_namespace.h>
54#include <net/netlabel.h>
53#include <asm/uaccess.h> 55#include <asm/uaccess.h>
54#include <asm/ioctls.h> 56#include <asm/ioctls.h>
57#include <asm/atomic.h>
55#include <linux/bitops.h> 58#include <linux/bitops.h>
56#include <linux/interrupt.h> 59#include <linux/interrupt.h>
57#include <linux/netdevice.h> /* for network interface checks */ 60#include <linux/netdevice.h> /* for network interface checks */
@@ -76,6 +79,7 @@
76#include "avc.h" 79#include "avc.h"
77#include "objsec.h" 80#include "objsec.h"
78#include "netif.h" 81#include "netif.h"
82#include "netnode.h"
79#include "xfrm.h" 83#include "xfrm.h"
80#include "netlabel.h" 84#include "netlabel.h"
81 85
@@ -89,6 +93,9 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
89extern int selinux_compat_net; 93extern int selinux_compat_net;
90extern struct security_operations *security_ops; 94extern struct security_operations *security_ops;
91 95
96/* SECMARK reference count */
97atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
98
92#ifdef CONFIG_SECURITY_SELINUX_DEVELOP 99#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
93int selinux_enforcing = 0; 100int selinux_enforcing = 0;
94 101
@@ -155,6 +162,21 @@ getsecurity_exit:
155 return len; 162 return len;
156} 163}
157 164
165/**
166 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
167 *
168 * Description:
169 * This function checks the SECMARK reference counter to see if any SECMARK
170 * targets are currently configured, if the reference counter is greater than
171 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
172 * enabled, false (0) if SECMARK is disabled.
173 *
174 */
175static int selinux_secmark_enabled(void)
176{
177 return (atomic_read(&selinux_secmark_refcount) > 0);
178}
179
158/* Allocate and free functions for each kind of security blob. */ 180/* Allocate and free functions for each kind of security blob. */
159 181
160static int task_alloc_security(struct task_struct *task) 182static int task_alloc_security(struct task_struct *task)
@@ -561,8 +583,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
561 * Allow filesystems with binary mount data to explicitly set mount point 583 * Allow filesystems with binary mount data to explicitly set mount point
562 * labeling information. 584 * labeling information.
563 */ 585 */
564int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, 586static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
565 int *flags, int num_opts) 587 int *flags, int num_opts)
566{ 588{
567 int rc = 0, i; 589 int rc = 0, i;
568 struct task_security_struct *tsec = current->security; 590 struct task_security_struct *tsec = current->security;
@@ -3395,7 +3417,7 @@ out:
3395#endif /* IPV6 */ 3417#endif /* IPV6 */
3396 3418
3397static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3419static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3398 char **addrp, int *len, int src, u8 *proto) 3420 char **addrp, int src, u8 *proto)
3399{ 3421{
3400 int ret = 0; 3422 int ret = 0;
3401 3423
@@ -3404,7 +3426,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3404 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3426 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3405 if (ret || !addrp) 3427 if (ret || !addrp)
3406 break; 3428 break;
3407 *len = 4;
3408 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3429 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3409 &ad->u.net.v4info.daddr); 3430 &ad->u.net.v4info.daddr);
3410 break; 3431 break;
@@ -3414,7 +3435,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3414 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3435 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3415 if (ret || !addrp) 3436 if (ret || !addrp)
3416 break; 3437 break;
3417 *len = 16;
3418 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3438 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3419 &ad->u.net.v6info.daddr); 3439 &ad->u.net.v6info.daddr);
3420 break; 3440 break;
@@ -3423,36 +3443,48 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3423 break; 3443 break;
3424 } 3444 }
3425 3445
3446 if (unlikely(ret))
3447 printk(KERN_WARNING
3448 "SELinux: failure in selinux_parse_skb(),"
3449 " unable to parse packet\n");
3450
3426 return ret; 3451 return ret;
3427} 3452}
3428 3453
3429/** 3454/**
3430 * selinux_skb_extlbl_sid - Determine the external label of a packet 3455 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
3431 * @skb: the packet 3456 * @skb: the packet
3432 * @sid: the packet's SID 3457 * @family: protocol family
3458 * @sid: the packet's peer label SID
3433 * 3459 *
3434 * Description: 3460 * Description:
3435 * Check the various different forms of external packet labeling and determine 3461 * Check the various different forms of network peer labeling and determine
3436 * the external SID for the packet. If only one form of external labeling is 3462 * the peer label/SID for the packet; most of the magic actually occurs in
3437 * present then it is used, if both labeled IPsec and NetLabel labels are 3463 * the security server function security_net_peersid_cmp(). The function
3438 * present then the SELinux type information is taken from the labeled IPsec 3464 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3439 * SA and the MLS sensitivity label information is taken from the NetLabel 3465 * or -EACCES if @sid is invalid due to inconsistencies with the different
3440 * security attributes. This bit of "magic" is done in the call to 3466 * peer labels.
3441 * selinux_netlbl_skbuff_getsid().
3442 * 3467 *
3443 */ 3468 */
3444static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) 3469static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3445{ 3470{
3471 int err;
3446 u32 xfrm_sid; 3472 u32 xfrm_sid;
3447 u32 nlbl_sid; 3473 u32 nlbl_sid;
3474 u32 nlbl_type;
3448 3475
3449 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3476 selinux_skb_xfrm_sid(skb, &xfrm_sid);
3450 if (selinux_netlbl_skbuff_getsid(skb, 3477 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3451 (xfrm_sid == SECSID_NULL ? 3478
3452 SECINITSID_NETMSG : xfrm_sid), 3479 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3453 &nlbl_sid) != 0) 3480 if (unlikely(err)) {
3454 nlbl_sid = SECSID_NULL; 3481 printk(KERN_WARNING
3455 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); 3482 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3483 " unable to determine packet's peer label\n");
3484 return -EACCES;
3485 }
3486
3487 return 0;
3456} 3488}
3457 3489
3458/* socket security operations */ 3490/* socket security operations */
@@ -3518,6 +3550,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3518 if (sock->sk) { 3550 if (sock->sk) {
3519 sksec = sock->sk->sk_security; 3551 sksec = sock->sk->sk_security;
3520 sksec->sid = isec->sid; 3552 sksec->sid = isec->sid;
3553 sksec->sclass = isec->sclass;
3521 err = selinux_netlbl_socket_post_create(sock); 3554 err = selinux_netlbl_socket_post_create(sock);
3522 } 3555 }
3523 3556
@@ -3610,7 +3643,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3610 break; 3643 break;
3611 } 3644 }
3612 3645
3613 err = security_node_sid(family, addrp, addrlen, &sid); 3646 err = sel_netnode_sid(addrp, family, &sid);
3614 if (err) 3647 if (err)
3615 goto out; 3648 goto out;
3616 3649
@@ -3821,131 +3854,182 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3821 return 0; 3854 return 0;
3822} 3855}
3823 3856
3824static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 3857static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3825 struct avc_audit_data *ad, u16 family, char *addrp, int len) 3858 u32 peer_sid,
3859 struct avc_audit_data *ad)
3826{ 3860{
3827 int err = 0; 3861 int err;
3828 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; 3862 u32 if_sid;
3829 struct socket *sock; 3863 u32 node_sid;
3830 u16 sock_class = 0;
3831 u32 sock_sid = 0;
3832
3833 read_lock_bh(&sk->sk_callback_lock);
3834 sock = sk->sk_socket;
3835 if (sock) {
3836 struct inode *inode;
3837 inode = SOCK_INODE(sock);
3838 if (inode) {
3839 struct inode_security_struct *isec;
3840 isec = inode->i_security;
3841 sock_sid = isec->sid;
3842 sock_class = isec->sclass;
3843 }
3844 }
3845 read_unlock_bh(&sk->sk_callback_lock);
3846 if (!sock_sid)
3847 goto out;
3848 3864
3849 if (!skb->dev) 3865 err = sel_netif_sid(ifindex, &if_sid);
3850 goto out; 3866 if (err)
3867 return err;
3868 err = avc_has_perm(peer_sid, if_sid,
3869 SECCLASS_NETIF, NETIF__INGRESS, ad);
3870 if (err)
3871 return err;
3851 3872
3852 err = sel_netif_sids(skb->dev, &if_sid, NULL); 3873 err = sel_netnode_sid(addrp, family, &node_sid);
3853 if (err) 3874 if (err)
3854 goto out; 3875 return err;
3876 return avc_has_perm(peer_sid, node_sid,
3877 SECCLASS_NODE, NODE__RECVFROM, ad);
3878}
3879
3880static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3881 struct sk_buff *skb,
3882 struct avc_audit_data *ad,
3883 u16 family,
3884 char *addrp)
3885{
3886 int err;
3887 struct sk_security_struct *sksec = sk->sk_security;
3888 u16 sk_class;
3889 u32 netif_perm, node_perm, recv_perm;
3890 u32 port_sid, node_sid, if_sid, sk_sid;
3855 3891
3856 switch (sock_class) { 3892 sk_sid = sksec->sid;
3893 sk_class = sksec->sclass;
3894
3895 switch (sk_class) {
3857 case SECCLASS_UDP_SOCKET: 3896 case SECCLASS_UDP_SOCKET:
3858 netif_perm = NETIF__UDP_RECV; 3897 netif_perm = NETIF__UDP_RECV;
3859 node_perm = NODE__UDP_RECV; 3898 node_perm = NODE__UDP_RECV;
3860 recv_perm = UDP_SOCKET__RECV_MSG; 3899 recv_perm = UDP_SOCKET__RECV_MSG;
3861 break; 3900 break;
3862
3863 case SECCLASS_TCP_SOCKET: 3901 case SECCLASS_TCP_SOCKET:
3864 netif_perm = NETIF__TCP_RECV; 3902 netif_perm = NETIF__TCP_RECV;
3865 node_perm = NODE__TCP_RECV; 3903 node_perm = NODE__TCP_RECV;
3866 recv_perm = TCP_SOCKET__RECV_MSG; 3904 recv_perm = TCP_SOCKET__RECV_MSG;
3867 break; 3905 break;
3868
3869 case SECCLASS_DCCP_SOCKET: 3906 case SECCLASS_DCCP_SOCKET:
3870 netif_perm = NETIF__DCCP_RECV; 3907 netif_perm = NETIF__DCCP_RECV;
3871 node_perm = NODE__DCCP_RECV; 3908 node_perm = NODE__DCCP_RECV;
3872 recv_perm = DCCP_SOCKET__RECV_MSG; 3909 recv_perm = DCCP_SOCKET__RECV_MSG;
3873 break; 3910 break;
3874
3875 default: 3911 default:
3876 netif_perm = NETIF__RAWIP_RECV; 3912 netif_perm = NETIF__RAWIP_RECV;
3877 node_perm = NODE__RAWIP_RECV; 3913 node_perm = NODE__RAWIP_RECV;
3914 recv_perm = 0;
3878 break; 3915 break;
3879 } 3916 }
3880 3917
3881 err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad); 3918 err = sel_netif_sid(skb->iif, &if_sid);
3882 if (err) 3919 if (err)
3883 goto out; 3920 return err;
3884 3921 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3885 err = security_node_sid(family, addrp, len, &node_sid);
3886 if (err) 3922 if (err)
3887 goto out; 3923 return err;
3888 3924
3889 err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad); 3925 err = sel_netnode_sid(addrp, family, &node_sid);
3890 if (err) 3926 if (err)
3891 goto out; 3927 return err;
3928 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
3929 if (err)
3930 return err;
3892 3931
3893 if (recv_perm) { 3932 if (!recv_perm)
3894 u32 port_sid; 3933 return 0;
3934 err = security_port_sid(sk->sk_family, sk->sk_type,
3935 sk->sk_protocol, ntohs(ad->u.net.sport),
3936 &port_sid);
3937 if (unlikely(err)) {
3938 printk(KERN_WARNING
3939 "SELinux: failure in"
3940 " selinux_sock_rcv_skb_iptables_compat(),"
3941 " network port label not found\n");
3942 return err;
3943 }
3944 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3945}
3895 3946
3896 err = security_port_sid(sk->sk_family, sk->sk_type, 3947static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3897 sk->sk_protocol, ntohs(ad->u.net.sport), 3948 struct avc_audit_data *ad,
3898 &port_sid); 3949 u16 family, char *addrp)
3899 if (err) 3950{
3900 goto out; 3951 int err;
3952 struct sk_security_struct *sksec = sk->sk_security;
3953 u32 peer_sid;
3954 u32 sk_sid = sksec->sid;
3901 3955
3902 err = avc_has_perm(sock_sid, port_sid, 3956 if (selinux_compat_net)
3903 sock_class, recv_perm, ad); 3957 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3958 family, addrp);
3959 else
3960 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3961 PACKET__RECV, ad);
3962 if (err)
3963 return err;
3964
3965 if (selinux_policycap_netpeer) {
3966 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
3967 if (err)
3968 return err;
3969 err = avc_has_perm(sk_sid, peer_sid,
3970 SECCLASS_PEER, PEER__RECV, ad);
3971 } else {
3972 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3973 if (err)
3974 return err;
3975 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
3904 } 3976 }
3905 3977
3906out:
3907 return err; 3978 return err;
3908} 3979}
3909 3980
3910static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 3981static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3911{ 3982{
3912 u16 family; 3983 int err;
3913 char *addrp;
3914 int len, err = 0;
3915 struct avc_audit_data ad;
3916 struct sk_security_struct *sksec = sk->sk_security; 3984 struct sk_security_struct *sksec = sk->sk_security;
3985 u16 family = sk->sk_family;
3986 u32 sk_sid = sksec->sid;
3987 struct avc_audit_data ad;
3988 char *addrp;
3917 3989
3918 family = sk->sk_family;
3919 if (family != PF_INET && family != PF_INET6) 3990 if (family != PF_INET && family != PF_INET6)
3920 goto out; 3991 return 0;
3921 3992
3922 /* Handle mapped IPv4 packets arriving via IPv6 sockets */ 3993 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
3923 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) 3994 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
3924 family = PF_INET; 3995 family = PF_INET;
3925 3996
3926 AVC_AUDIT_DATA_INIT(&ad, NET); 3997 AVC_AUDIT_DATA_INIT(&ad, NET);
3927 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3998 ad.u.net.netif = skb->iif;
3928 ad.u.net.family = family; 3999 ad.u.net.family = family;
3929 4000 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
3930 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
3931 if (err) 4001 if (err)
3932 goto out; 4002 return err;
3933 4003
3934 if (selinux_compat_net) 4004 /* If any sort of compatibility mode is enabled then handoff processing
3935 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, 4005 * to the selinux_sock_rcv_skb_compat() function to deal with the
3936 addrp, len); 4006 * special handling. We do this in an attempt to keep this function
3937 else 4007 * as fast and as clean as possible. */
3938 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, 4008 if (selinux_compat_net || !selinux_policycap_netpeer)
3939 PACKET__RECV, &ad); 4009 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3940 if (err) 4010 family, addrp);
3941 goto out;
3942 4011
3943 err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); 4012 if (netlbl_enabled() || selinux_xfrm_enabled()) {
3944 if (err) 4013 u32 peer_sid;
3945 goto out; 4014
4015 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4016 if (err)
4017 return err;
4018 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4019 peer_sid, &ad);
4020 if (err)
4021 return err;
4022 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4023 PEER__RECV, &ad);
4024 }
4025
4026 if (selinux_secmark_enabled()) {
4027 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4028 PACKET__RECV, &ad);
4029 if (err)
4030 return err;
4031 }
3946 4032
3947 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
3948out:
3949 return err; 4033 return err;
3950} 4034}
3951 4035
@@ -3996,18 +4080,25 @@ out:
3996static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) 4080static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
3997{ 4081{
3998 u32 peer_secid = SECSID_NULL; 4082 u32 peer_secid = SECSID_NULL;
3999 int err = 0; 4083 u16 family;
4084
4085 if (sock)
4086 family = sock->sk->sk_family;
4087 else if (skb && skb->sk)
4088 family = skb->sk->sk_family;
4089 else
4090 goto out;
4000 4091
4001 if (sock && sock->sk->sk_family == PF_UNIX) 4092 if (sock && family == PF_UNIX)
4002 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 4093 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
4003 else if (skb) 4094 else if (skb)
4004 selinux_skb_extlbl_sid(skb, &peer_secid); 4095 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
4005 4096
4006 if (peer_secid == SECSID_NULL) 4097out:
4007 err = -EINVAL;
4008 *secid = peer_secid; 4098 *secid = peer_secid;
4009 4099 if (peer_secid == SECSID_NULL)
4010 return err; 4100 return -EINVAL;
4101 return 0;
4011} 4102}
4012 4103
4013static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 4104static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
@@ -4027,6 +4118,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4027 4118
4028 newssec->sid = ssec->sid; 4119 newssec->sid = ssec->sid;
4029 newssec->peer_sid = ssec->peer_sid; 4120 newssec->peer_sid = ssec->peer_sid;
4121 newssec->sclass = ssec->sclass;
4030 4122
4031 selinux_netlbl_sk_security_clone(ssec, newssec); 4123 selinux_netlbl_sk_security_clone(ssec, newssec);
4032} 4124}
@@ -4050,6 +4142,7 @@ static void selinux_sock_graft(struct sock* sk, struct socket *parent)
4050 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || 4142 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4051 sk->sk_family == PF_UNIX) 4143 sk->sk_family == PF_UNIX)
4052 isec->sid = sksec->sid; 4144 isec->sid = sksec->sid;
4145 sksec->sclass = isec->sclass;
4053 4146
4054 selinux_netlbl_sock_graft(sk, parent); 4147 selinux_netlbl_sock_graft(sk, parent);
4055} 4148}
@@ -4062,7 +4155,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4062 u32 newsid; 4155 u32 newsid;
4063 u32 peersid; 4156 u32 peersid;
4064 4157
4065 selinux_skb_extlbl_sid(skb, &peersid); 4158 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4159 if (err)
4160 return err;
4066 if (peersid == SECSID_NULL) { 4161 if (peersid == SECSID_NULL) {
4067 req->secid = sksec->sid; 4162 req->secid = sksec->sid;
4068 req->peer_secid = SECSID_NULL; 4163 req->peer_secid = SECSID_NULL;
@@ -4100,7 +4195,7 @@ static void selinux_inet_conn_established(struct sock *sk,
4100{ 4195{
4101 struct sk_security_struct *sksec = sk->sk_security; 4196 struct sk_security_struct *sksec = sk->sk_security;
4102 4197
4103 selinux_skb_extlbl_sid(skb, &sksec->peer_sid); 4198 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
4104} 4199}
4105 4200
4106static void selinux_req_classify_flow(const struct request_sock *req, 4201static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4147,149 +4242,260 @@ out:
4147 4242
4148#ifdef CONFIG_NETFILTER 4243#ifdef CONFIG_NETFILTER
4149 4244
4150static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, 4245static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4151 struct avc_audit_data *ad, 4246 u16 family)
4152 u16 family, char *addrp, int len)
4153{ 4247{
4154 int err = 0; 4248 char *addrp;
4155 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 4249 u32 peer_sid;
4156 struct socket *sock; 4250 struct avc_audit_data ad;
4157 struct inode *inode; 4251 u8 secmark_active;
4158 struct inode_security_struct *isec; 4252 u8 peerlbl_active;
4159 4253
4160 sock = sk->sk_socket; 4254 if (!selinux_policycap_netpeer)
4161 if (!sock) 4255 return NF_ACCEPT;
4162 goto out;
4163 4256
4164 inode = SOCK_INODE(sock); 4257 secmark_active = selinux_secmark_enabled();
4165 if (!inode) 4258 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4166 goto out; 4259 if (!secmark_active && !peerlbl_active)
4260 return NF_ACCEPT;
4167 4261
4168 isec = inode->i_security; 4262 AVC_AUDIT_DATA_INIT(&ad, NET);
4169 4263 ad.u.net.netif = ifindex;
4170 err = sel_netif_sids(dev, &if_sid, NULL); 4264 ad.u.net.family = family;
4171 if (err) 4265 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4172 goto out; 4266 return NF_DROP;
4267
4268 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4269 return NF_DROP;
4270
4271 if (peerlbl_active)
4272 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4273 peer_sid, &ad) != 0)
4274 return NF_DROP;
4275
4276 if (secmark_active)
4277 if (avc_has_perm(peer_sid, skb->secmark,
4278 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4279 return NF_DROP;
4280
4281 return NF_ACCEPT;
4282}
4283
4284static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4285 struct sk_buff *skb,
4286 const struct net_device *in,
4287 const struct net_device *out,
4288 int (*okfn)(struct sk_buff *))
4289{
4290 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4291}
4173 4292
4174 switch (isec->sclass) { 4293#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4294static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4295 struct sk_buff *skb,
4296 const struct net_device *in,
4297 const struct net_device *out,
4298 int (*okfn)(struct sk_buff *))
4299{
4300 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4301}
4302#endif /* IPV6 */
4303
4304static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4305 int ifindex,
4306 struct avc_audit_data *ad,
4307 u16 family, char *addrp)
4308{
4309 int err;
4310 struct sk_security_struct *sksec = sk->sk_security;
4311 u16 sk_class;
4312 u32 netif_perm, node_perm, send_perm;
4313 u32 port_sid, node_sid, if_sid, sk_sid;
4314
4315 sk_sid = sksec->sid;
4316 sk_class = sksec->sclass;
4317
4318 switch (sk_class) {
4175 case SECCLASS_UDP_SOCKET: 4319 case SECCLASS_UDP_SOCKET:
4176 netif_perm = NETIF__UDP_SEND; 4320 netif_perm = NETIF__UDP_SEND;
4177 node_perm = NODE__UDP_SEND; 4321 node_perm = NODE__UDP_SEND;
4178 send_perm = UDP_SOCKET__SEND_MSG; 4322 send_perm = UDP_SOCKET__SEND_MSG;
4179 break; 4323 break;
4180
4181 case SECCLASS_TCP_SOCKET: 4324 case SECCLASS_TCP_SOCKET:
4182 netif_perm = NETIF__TCP_SEND; 4325 netif_perm = NETIF__TCP_SEND;
4183 node_perm = NODE__TCP_SEND; 4326 node_perm = NODE__TCP_SEND;
4184 send_perm = TCP_SOCKET__SEND_MSG; 4327 send_perm = TCP_SOCKET__SEND_MSG;
4185 break; 4328 break;
4186
4187 case SECCLASS_DCCP_SOCKET: 4329 case SECCLASS_DCCP_SOCKET:
4188 netif_perm = NETIF__DCCP_SEND; 4330 netif_perm = NETIF__DCCP_SEND;
4189 node_perm = NODE__DCCP_SEND; 4331 node_perm = NODE__DCCP_SEND;
4190 send_perm = DCCP_SOCKET__SEND_MSG; 4332 send_perm = DCCP_SOCKET__SEND_MSG;
4191 break; 4333 break;
4192
4193 default: 4334 default:
4194 netif_perm = NETIF__RAWIP_SEND; 4335 netif_perm = NETIF__RAWIP_SEND;
4195 node_perm = NODE__RAWIP_SEND; 4336 node_perm = NODE__RAWIP_SEND;
4337 send_perm = 0;
4196 break; 4338 break;
4197 } 4339 }
4198 4340
4199 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad); 4341 err = sel_netif_sid(ifindex, &if_sid);
4200 if (err) 4342 if (err)
4201 goto out; 4343 return err;
4344 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4345 return err;
4202 4346
4203 err = security_node_sid(family, addrp, len, &node_sid); 4347 err = sel_netnode_sid(addrp, family, &node_sid);
4204 if (err) 4348 if (err)
4205 goto out; 4349 return err;
4206 4350 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4207 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
4208 if (err) 4351 if (err)
4209 goto out; 4352 return err;
4210 4353
4211 if (send_perm) { 4354 if (send_perm != 0)
4212 u32 port_sid; 4355 return 0;
4213
4214 err = security_port_sid(sk->sk_family,
4215 sk->sk_type,
4216 sk->sk_protocol,
4217 ntohs(ad->u.net.dport),
4218 &port_sid);
4219 if (err)
4220 goto out;
4221 4356
4222 err = avc_has_perm(isec->sid, port_sid, isec->sclass, 4357 err = security_port_sid(sk->sk_family, sk->sk_type,
4223 send_perm, ad); 4358 sk->sk_protocol, ntohs(ad->u.net.dport),
4359 &port_sid);
4360 if (unlikely(err)) {
4361 printk(KERN_WARNING
4362 "SELinux: failure in"
4363 " selinux_ip_postroute_iptables_compat(),"
4364 " network port label not found\n");
4365 return err;
4224 } 4366 }
4225out: 4367 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
4226 return err;
4227} 4368}
4228 4369
4229static unsigned int selinux_ip_postroute_last(unsigned int hooknum, 4370static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4230 struct sk_buff *skb, 4371 int ifindex,
4231 const struct net_device *in, 4372 struct avc_audit_data *ad,
4232 const struct net_device *out, 4373 u16 family,
4233 int (*okfn)(struct sk_buff *), 4374 char *addrp,
4234 u16 family) 4375 u8 proto)
4235{ 4376{
4236 char *addrp; 4377 struct sock *sk = skb->sk;
4237 int len, err = 0;
4238 struct sock *sk;
4239 struct avc_audit_data ad;
4240 struct net_device *dev = (struct net_device *)out;
4241 struct sk_security_struct *sksec; 4378 struct sk_security_struct *sksec;
4242 u8 proto;
4243
4244 sk = skb->sk;
4245 if (!sk)
4246 goto out;
4247 4379
4380 if (sk == NULL)
4381 return NF_ACCEPT;
4248 sksec = sk->sk_security; 4382 sksec = sk->sk_security;
4249 4383
4250 AVC_AUDIT_DATA_INIT(&ad, NET); 4384 if (selinux_compat_net) {
4251 ad.u.net.netif = dev->name; 4385 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4252 ad.u.net.family = family; 4386 ad, family, addrp))
4387 return NF_DROP;
4388 } else {
4389 if (avc_has_perm(sksec->sid, skb->secmark,
4390 SECCLASS_PACKET, PACKET__SEND, ad))
4391 return NF_DROP;
4392 }
4253 4393
4254 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); 4394 if (selinux_policycap_netpeer)
4255 if (err) 4395 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4256 goto out; 4396 return NF_DROP;
4257 4397
4258 if (selinux_compat_net) 4398 return NF_ACCEPT;
4259 err = selinux_ip_postroute_last_compat(sk, dev, &ad, 4399}
4260 family, addrp, len);
4261 else
4262 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
4263 PACKET__SEND, &ad);
4264 4400
4265 if (err) 4401static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4266 goto out; 4402 u16 family)
4403{
4404 u32 secmark_perm;
4405 u32 peer_sid;
4406 struct sock *sk;
4407 struct avc_audit_data ad;
4408 char *addrp;
4409 u8 proto;
4410 u8 secmark_active;
4411 u8 peerlbl_active;
4267 4412
4268 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto); 4413 AVC_AUDIT_DATA_INIT(&ad, NET);
4269out: 4414 ad.u.net.netif = ifindex;
4270 return err ? NF_DROP : NF_ACCEPT; 4415 ad.u.net.family = family;
4416 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4417 return NF_DROP;
4418
4419 /* If any sort of compatibility mode is enabled then handoff processing
4420 * to the selinux_ip_postroute_compat() function to deal with the
4421 * special handling. We do this in an attempt to keep this function
4422 * as fast and as clean as possible. */
4423 if (selinux_compat_net || !selinux_policycap_netpeer)
4424 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4425 family, addrp, proto);
4426
4427 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4428 * packet transformation so allow the packet to pass without any checks
4429 * since we'll have another chance to perform access control checks
4430 * when the packet is on it's final way out.
4431 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4432 * is NULL, in this case go ahead and apply access control. */
4433 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4434 return NF_ACCEPT;
4435
4436 secmark_active = selinux_secmark_enabled();
4437 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4438 if (!secmark_active && !peerlbl_active)
4439 return NF_ACCEPT;
4440
4441 /* if the packet is locally generated (skb->sk != NULL) then use the
4442 * socket's label as the peer label, otherwise the packet is being
4443 * forwarded through this system and we need to fetch the peer label
4444 * directly from the packet */
4445 sk = skb->sk;
4446 if (sk) {
4447 struct sk_security_struct *sksec = sk->sk_security;
4448 peer_sid = sksec->sid;
4449 secmark_perm = PACKET__SEND;
4450 } else {
4451 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4452 return NF_DROP;
4453 secmark_perm = PACKET__FORWARD_OUT;
4454 }
4455
4456 if (secmark_active)
4457 if (avc_has_perm(peer_sid, skb->secmark,
4458 SECCLASS_PACKET, secmark_perm, &ad))
4459 return NF_DROP;
4460
4461 if (peerlbl_active) {
4462 u32 if_sid;
4463 u32 node_sid;
4464
4465 if (sel_netif_sid(ifindex, &if_sid))
4466 return NF_DROP;
4467 if (avc_has_perm(peer_sid, if_sid,
4468 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4469 return NF_DROP;
4470
4471 if (sel_netnode_sid(addrp, family, &node_sid))
4472 return NF_DROP;
4473 if (avc_has_perm(peer_sid, node_sid,
4474 SECCLASS_NODE, NODE__SENDTO, &ad))
4475 return NF_DROP;
4476 }
4477
4478 return NF_ACCEPT;
4271} 4479}
4272 4480
4273static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, 4481static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4274 struct sk_buff *skb, 4482 struct sk_buff *skb,
4275 const struct net_device *in, 4483 const struct net_device *in,
4276 const struct net_device *out, 4484 const struct net_device *out,
4277 int (*okfn)(struct sk_buff *)) 4485 int (*okfn)(struct sk_buff *))
4278{ 4486{
4279 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET); 4487 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
4280} 4488}
4281 4489
4282#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 4490#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4283 4491static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4284static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, 4492 struct sk_buff *skb,
4285 struct sk_buff *skb, 4493 const struct net_device *in,
4286 const struct net_device *in, 4494 const struct net_device *out,
4287 const struct net_device *out, 4495 int (*okfn)(struct sk_buff *))
4288 int (*okfn)(struct sk_buff *))
4289{ 4496{
4290 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6); 4497 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
4291} 4498}
4292
4293#endif /* IPV6 */ 4499#endif /* IPV6 */
4294 4500
4295#endif /* CONFIG_NETFILTER */ 4501#endif /* CONFIG_NETFILTER */
@@ -5277,22 +5483,40 @@ security_initcall(selinux_init);
5277 5483
5278#if defined(CONFIG_NETFILTER) 5484#if defined(CONFIG_NETFILTER)
5279 5485
5280static struct nf_hook_ops selinux_ipv4_op = { 5486static struct nf_hook_ops selinux_ipv4_ops[] = {
5281 .hook = selinux_ipv4_postroute_last, 5487 {
5282 .owner = THIS_MODULE, 5488 .hook = selinux_ipv4_postroute,
5283 .pf = PF_INET, 5489 .owner = THIS_MODULE,
5284 .hooknum = NF_INET_POST_ROUTING, 5490 .pf = PF_INET,
5285 .priority = NF_IP_PRI_SELINUX_LAST, 5491 .hooknum = NF_INET_POST_ROUTING,
5492 .priority = NF_IP_PRI_SELINUX_LAST,
5493 },
5494 {
5495 .hook = selinux_ipv4_forward,
5496 .owner = THIS_MODULE,
5497 .pf = PF_INET,
5498 .hooknum = NF_INET_FORWARD,
5499 .priority = NF_IP_PRI_SELINUX_FIRST,
5500 }
5286}; 5501};
5287 5502
5288#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5503#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5289 5504
5290static struct nf_hook_ops selinux_ipv6_op = { 5505static struct nf_hook_ops selinux_ipv6_ops[] = {
5291 .hook = selinux_ipv6_postroute_last, 5506 {
5292 .owner = THIS_MODULE, 5507 .hook = selinux_ipv6_postroute,
5293 .pf = PF_INET6, 5508 .owner = THIS_MODULE,
5294 .hooknum = NF_INET_POST_ROUTING, 5509 .pf = PF_INET6,
5295 .priority = NF_IP6_PRI_SELINUX_LAST, 5510 .hooknum = NF_INET_POST_ROUTING,
5511 .priority = NF_IP6_PRI_SELINUX_LAST,
5512 },
5513 {
5514 .hook = selinux_ipv6_forward,
5515 .owner = THIS_MODULE,
5516 .pf = PF_INET6,
5517 .hooknum = NF_INET_FORWARD,
5518 .priority = NF_IP6_PRI_SELINUX_FIRST,
5519 }
5296}; 5520};
5297 5521
5298#endif /* IPV6 */ 5522#endif /* IPV6 */
@@ -5300,22 +5524,27 @@ static struct nf_hook_ops selinux_ipv6_op = {
5300static int __init selinux_nf_ip_init(void) 5524static int __init selinux_nf_ip_init(void)
5301{ 5525{
5302 int err = 0; 5526 int err = 0;
5527 u32 iter;
5303 5528
5304 if (!selinux_enabled) 5529 if (!selinux_enabled)
5305 goto out; 5530 goto out;
5306 5531
5307 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 5532 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5308 5533
5309 err = nf_register_hook(&selinux_ipv4_op); 5534 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5310 if (err) 5535 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5311 panic("SELinux: nf_register_hook for IPv4: error %d\n", err); 5536 if (err)
5537 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5538 err);
5539 }
5312 5540
5313#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5541#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5314 5542 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5315 err = nf_register_hook(&selinux_ipv6_op); 5543 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5316 if (err) 5544 if (err)
5317 panic("SELinux: nf_register_hook for IPv6: error %d\n", err); 5545 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5318 5546 err);
5547 }
5319#endif /* IPV6 */ 5548#endif /* IPV6 */
5320 5549
5321out: 5550out:
@@ -5327,11 +5556,15 @@ __initcall(selinux_nf_ip_init);
5327#ifdef CONFIG_SECURITY_SELINUX_DISABLE 5556#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5328static void selinux_nf_ip_exit(void) 5557static void selinux_nf_ip_exit(void)
5329{ 5558{
5559 u32 iter;
5560
5330 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 5561 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
5331 5562
5332 nf_unregister_hook(&selinux_ipv4_op); 5563 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5564 nf_unregister_hook(&selinux_ipv4_ops[iter]);
5333#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5565#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5334 nf_unregister_hook(&selinux_ipv6_op); 5566 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5567 nf_unregister_hook(&selinux_ipv6_ops[iter]);
5335#endif /* IPV6 */ 5568#endif /* IPV6 */
5336} 5569}
5337#endif 5570#endif