Rename the existing selinux_skb_extlbl_sid() function to
selinux_skb_peerlbl_sid() and modify it's behavior such that it now reconciles
multiple peer/external labels and if reconciliation is not possible it returns
an error to the caller.
---
security/selinux/hooks.c| 94 ++-
security/selinux/include/netlabel.h |3 +
security/selinux/include/security.h |4 +
security/selinux/netlabel.c |3 +
security/selinux/ss/services.c | 85
5 files changed, 154 insertions(+), 35 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2188b9c..4d13a80 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3190,36 +3190,39 @@ static int selinux_parse_skb(struct sk_buff *skb,
struct avc_audit_data *ad,
}
/**
- * selinux_skb_extlbl_sid - Determine the external label of a packet
+ * selinux_skb_peerlbl_sid - Determine the peer label of a packet
* @skb: the packet
* @family: protocol family
- * @sid: the packet's SID
+ * @sid: the packet's peer label SID
*
* Description:
- * Check the various different forms of external packet labeling and determine
- * the external SID for the packet. If only one form of external labeling is
- * present then it is used, if both labeled IPsec and NetLabel labels are
- * present then the SELinux type information is taken from the labeled IPsec
- * SA and the MLS sensitivity label information is taken from the NetLabel
- * security attributes. This bit of "magic" is done in the call to
- * selinux_netlbl_skbuff_getsid().
+ * Check the various different forms of network peer labeling and determine
+ * the peer label/SID for the packet; most of the magic actually occurs in
+ * the security server function security_net_peersid_cmp(). The function
+ * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
+ * or -EACCES if @sid is invalid due to inconsistencies with the different
+ * peer labels.
*
*/
-static void selinux_skb_extlbl_sid(struct sk_buff *skb,
- u16 family,
- u32 *sid)
+static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
{
u32 xfrm_sid;
u32 nlbl_sid;
+ u32 nlbl_type;
selinux_skb_xfrm_sid(skb, &xfrm_sid);
- if (selinux_netlbl_skbuff_getsid(skb,
-family,
-(xfrm_sid == SECSID_NULL ?
- SECINITSID_NETMSG : xfrm_sid),
-&nlbl_sid) != 0)
- nlbl_sid = SECSID_NULL;
- *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
+ selinux_netlbl_skbuff_getsid(skb,
+family,
+SECINITSID_NETMSG,
+&nlbl_type,
+&nlbl_sid);
+
+ if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
+xfrm_sid,
+sid) != 0)
+ return -EACCES;
+
+ return 0;
}
/* socket security operations */
@@ -3674,17 +3677,32 @@ out:
return err;
}
+static int selinux_sock_recv_peer_compat(struct sk_security_struct *sksec,
+struct sk_buff *skb,
+u16 family,
+struct avc_audit_data ad)
+{
+ int err;
+
+ err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
+ if (err)
+ return err;
+
+ return selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
+}
+
static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
- u16 family;
+ u16 family = sk->sk_family;
char *addrp;
- int len, err = 0;
+ int len;
+ int err;
struct avc_audit_data ad;
struct sk_security_struct *sksec = sk->sk_security;
+ int peer_sid;
- family = sk->sk_family;
if (family != PF_INET && family != PF_INET6)
- goto out;
+ return 0;
/* Handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
@@ -3693,10 +3711,14 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk,
struct sk_buff *skb)
AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
ad.u.net.family = family;
-
err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
if (err)
- goto out;
+ return err;
+
+ /* Between selinux_compat_net and selinux_policycap_netpeer this is
+* starting to get a bit messy - we need to setup a timetable for
+* deprecating some of this old/obsolete functiona