diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bfe9a05db3a2..6156241c8770 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -51,8 +51,10 @@ | |||
| 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> | 53 | #include <net/net_namespace.h> |
| 54 | #include <net/netlabel.h> | ||
| 54 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
| 55 | #include <asm/ioctls.h> | 56 | #include <asm/ioctls.h> |
| 57 | #include <asm/atomic.h> | ||
| 56 | #include <linux/bitops.h> | 58 | #include <linux/bitops.h> |
| 57 | #include <linux/interrupt.h> | 59 | #include <linux/interrupt.h> |
| 58 | #include <linux/netdevice.h> /* for network interface checks */ | 60 | #include <linux/netdevice.h> /* for network interface checks */ |
| @@ -91,6 +93,9 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | |||
| 91 | extern int selinux_compat_net; | 93 | extern int selinux_compat_net; |
| 92 | extern struct security_operations *security_ops; | 94 | extern struct security_operations *security_ops; |
| 93 | 95 | ||
| 96 | /* SECMARK reference count */ | ||
| 97 | atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); | ||
| 98 | |||
| 94 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | 99 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP |
| 95 | int selinux_enforcing = 0; | 100 | int selinux_enforcing = 0; |
| 96 | 101 | ||
| @@ -157,6 +162,21 @@ getsecurity_exit: | |||
| 157 | return len; | 162 | return len; |
| 158 | } | 163 | } |
| 159 | 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 | */ | ||
| 175 | static int selinux_secmark_enabled(void) | ||
| 176 | { | ||
| 177 | return (atomic_read(&selinux_secmark_refcount) > 0); | ||
| 178 | } | ||
| 179 | |||
| 160 | /* Allocate and free functions for each kind of security blob. */ | 180 | /* Allocate and free functions for each kind of security blob. */ |
| 161 | 181 | ||
| 162 | static int task_alloc_security(struct task_struct *task) | 182 | static int task_alloc_security(struct task_struct *task) |
| @@ -3931,7 +3951,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 3931 | struct sk_security_struct *sksec = sk->sk_security; | 3951 | struct sk_security_struct *sksec = sk->sk_security; |
| 3932 | u16 family = sk->sk_family; | 3952 | u16 family = sk->sk_family; |
| 3933 | u32 sk_sid = sksec->sid; | 3953 | u32 sk_sid = sksec->sid; |
| 3934 | u32 peer_sid; | ||
| 3935 | struct avc_audit_data ad; | 3954 | struct avc_audit_data ad; |
| 3936 | char *addrp; | 3955 | char *addrp; |
| 3937 | 3956 | ||
| @@ -3957,15 +3976,24 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 3957 | return selinux_sock_rcv_skb_compat(sk, skb, &ad, | 3976 | return selinux_sock_rcv_skb_compat(sk, skb, &ad, |
| 3958 | family, addrp); | 3977 | family, addrp); |
| 3959 | 3978 | ||
| 3960 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 3979 | if (selinux_secmark_enabled()) { |
| 3961 | PACKET__RECV, &ad); | 3980 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, |
| 3962 | if (err) | 3981 | PACKET__RECV, &ad); |
| 3963 | return err; | 3982 | if (err) |
| 3983 | return err; | ||
| 3984 | } | ||
| 3964 | 3985 | ||
| 3965 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 3986 | if (netlbl_enabled() || selinux_xfrm_enabled()) { |
| 3966 | if (err) | 3987 | u32 peer_sid; |
| 3967 | return err; | 3988 | |
| 3968 | return avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); | 3989 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
| 3990 | if (err) | ||
| 3991 | return err; | ||
| 3992 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, | ||
| 3993 | PEER__RECV, &ad); | ||
| 3994 | } | ||
| 3995 | |||
| 3996 | return err; | ||
| 3969 | } | 3997 | } |
| 3970 | 3998 | ||
| 3971 | static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, | 3999 | static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, |
