Commit 2be4d74f authored by Chris PeBenito's avatar Chris PeBenito Committed by Eric Paris

Add SELinux policy capability for always checking packet and peer classes.

Currently the packet class in SELinux is not checked if there are no
SECMARK rules in the security or mangle netfilter tables.  Some systems
prefer that packets are always checked, for example, to protect the system
should the netfilter rules fail to load or if the nefilter rules
were maliciously flushed.

Add the always_check_network policy capability which, when enabled, treats
SECMARK as enabled, even if there are no netfilter SECMARK rules and
treats peer labeling as enabled, even if there is no Netlabel or
labeled IPSEC configuration.

Includes definition of "redhat1" SELinux policy capability, which
exists in the SELinux userpace library, to keep ordering correct.

The SELinux userpace portion of this was merged last year, but this kernel
change fell on the floor.
Signed-off-by: default avatarChris PeBenito <cpebenito@tresys.com>
Signed-off-by: default avatarEric Paris <eparis@redhat.com>
parent b04eea88
...@@ -136,12 +136,28 @@ static struct kmem_cache *sel_inode_cache; ...@@ -136,12 +136,28 @@ static struct kmem_cache *sel_inode_cache;
* This function checks the SECMARK reference counter to see if any SECMARK * This function checks the SECMARK reference counter to see if any SECMARK
* targets are currently configured, if the reference counter is greater than * targets are currently configured, if the reference counter is greater than
* zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
* enabled, false (0) if SECMARK is disabled. * enabled, false (0) if SECMARK is disabled. If the always_check_network
* policy capability is enabled, SECMARK is always considered enabled.
* *
*/ */
static int selinux_secmark_enabled(void) static int selinux_secmark_enabled(void)
{ {
return (atomic_read(&selinux_secmark_refcount) > 0); return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
}
/**
* selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
*
* Description:
* This function checks if NetLabel or labeled IPSEC is enabled. Returns true
* (1) if any are enabled or false (0) if neither are enabled. If the
* always_check_network policy capability is enabled, peer labeling
* is always considered enabled.
*
*/
static int selinux_peerlbl_enabled(void)
{
return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
} }
/* /*
...@@ -4197,7 +4213,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -4197,7 +4213,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return selinux_sock_rcv_skb_compat(sk, skb, family); return selinux_sock_rcv_skb_compat(sk, skb, family);
secmark_active = selinux_secmark_enabled(); secmark_active = selinux_secmark_enabled();
peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active) if (!secmark_active && !peerlbl_active)
return 0; return 0;
...@@ -4579,7 +4595,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, ...@@ -4579,7 +4595,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
secmark_active = selinux_secmark_enabled(); secmark_active = selinux_secmark_enabled();
netlbl_active = netlbl_enabled(); netlbl_active = netlbl_enabled();
peerlbl_active = netlbl_active || selinux_xfrm_enabled(); peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active) if (!secmark_active && !peerlbl_active)
return NF_ACCEPT; return NF_ACCEPT;
...@@ -4731,7 +4747,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ...@@ -4731,7 +4747,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
return NF_ACCEPT; return NF_ACCEPT;
#endif #endif
secmark_active = selinux_secmark_enabled(); secmark_active = selinux_secmark_enabled();
peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active) if (!secmark_active && !peerlbl_active)
return NF_ACCEPT; return NF_ACCEPT;
......
...@@ -69,12 +69,15 @@ extern int selinux_enabled; ...@@ -69,12 +69,15 @@ extern int selinux_enabled;
enum { enum {
POLICYDB_CAPABILITY_NETPEER, POLICYDB_CAPABILITY_NETPEER,
POLICYDB_CAPABILITY_OPENPERM, POLICYDB_CAPABILITY_OPENPERM,
POLICYDB_CAPABILITY_REDHAT1,
POLICYDB_CAPABILITY_ALWAYSNETWORK,
__POLICYDB_CAPABILITY_MAX __POLICYDB_CAPABILITY_MAX
}; };
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern int selinux_policycap_netpeer; extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm; extern int selinux_policycap_openperm;
extern int selinux_policycap_alwaysnetwork;
/* /*
* type_datum properties * type_datum properties
......
...@@ -44,7 +44,9 @@ ...@@ -44,7 +44,9 @@
/* Policy capability filenames */ /* Policy capability filenames */
static char *policycap_names[] = { static char *policycap_names[] = {
"network_peer_controls", "network_peer_controls",
"open_perms" "open_perms",
"redhat1",
"always_check_network"
}; };
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
int selinux_policycap_netpeer; int selinux_policycap_netpeer;
int selinux_policycap_openperm; int selinux_policycap_openperm;
int selinux_policycap_alwaysnetwork;
static DEFINE_RWLOCK(policy_rwlock); static DEFINE_RWLOCK(policy_rwlock);
...@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void) ...@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void)
POLICYDB_CAPABILITY_NETPEER); POLICYDB_CAPABILITY_NETPEER);
selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_OPENPERM); POLICYDB_CAPABILITY_OPENPERM);
selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_ALWAYSNETWORK);
} }
static int security_preserve_bools(struct policydb *p); static int security_preserve_bools(struct policydb *p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment