We did the right thing in a few cases but there were several areas where we
determined a packet's address family based on the socket's address family which
is not the right thing to do since we can get IPv4 packets on IPv6 sockets.
This patch fixes these problems by either taking the address family directly
from the packet.
Signed-off-by: Paul Moore <paul.moore@hp.com>
Acked-by: James Morris <jmorris@namei.org>
u32 peer_secid = SECSID_NULL;
u16 family;
u32 peer_secid = SECSID_NULL;
u16 family;
+ if (skb && skb->protocol == htons(ETH_P_IP))
+ family = PF_INET;
+ else if (skb && skb->protocol == htons(ETH_P_IPV6))
+ family = PF_INET6;
+ else if (sock)
family = sock->sk->sk_family;
family = sock->sk->sk_family;
- else if (skb && skb->sk)
- family = skb->sk->sk_family;
{
struct sk_security_struct *sksec = sk->sk_security;
int err;
{
struct sk_security_struct *sksec = sk->sk_security;
int err;
+ u16 family = sk->sk_family;
- err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
+ /* handle mapped IPv4 packets arriving via IPv6 sockets */
+ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+ family = PF_INET;
+
+ err = selinux_skb_peerlbl_sid(skb, family, &peersid);
if (err)
return err;
if (peersid == SECSID_NULL) {
if (err)
return err;
if (peersid == SECSID_NULL) {
static void selinux_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
static void selinux_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
+ u16 family = sk->sk_family;
struct sk_security_struct *sksec = sk->sk_security;
struct sk_security_struct *sksec = sk->sk_security;
- selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
+ /* handle mapped IPv4 packets arriving via IPv6 sockets */
+ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+ family = PF_INET;
+
+ selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
}
static void selinux_req_classify_flow(const struct request_sock *req,
}
static void selinux_req_classify_flow(const struct request_sock *req,