selinux: make better use of the nf_hook_state passed to the NF hooks
authorPaul Moore <paul@paul-moore.com>
Mon, 11 Oct 2021 21:50:48 +0000 (17:50 -0400)
committerPaul Moore <paul@paul-moore.com>
Wed, 13 Oct 2021 20:31:18 +0000 (16:31 -0400)
This patch builds on a previous SELinux/netfilter patch by Florian
Westphal and makes better use of the nf_hook_state variable passed
into the SELinux/netfilter hooks as well as a number of other small
cleanups in the related code.

Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/hooks.c

index 4210831d5adeb96bdff502dc4c97693ca634717f..49d52d7a7714c9664d307ea639b24ee89c65cba9 100644 (file)
@@ -5692,38 +5692,38 @@ static int selinux_tun_dev_open(void *security)
 static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
                                       const struct nf_hook_state *state)
 {
-       const struct net_device *indev = state->in;
-       u16 family = state->pf;
-       int err;
+       int ifindex;
+       u16 family;
        char *addrp;
        u32 peer_sid;
        struct common_audit_data ad;
        struct lsm_network_audit net = {0,};
-       u8 secmark_active;
-       u8 netlbl_active;
-       u8 peerlbl_active;
+       int secmark_active, peerlbl_active;
 
        if (!selinux_policycap_netpeer())
                return NF_ACCEPT;
 
        secmark_active = selinux_secmark_enabled();
-       netlbl_active = netlbl_enabled();
        peerlbl_active = selinux_peerlbl_enabled();
        if (!secmark_active && !peerlbl_active)
                return NF_ACCEPT;
 
+       family = state->pf;
        if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
                return NF_DROP;
 
+       ifindex = state->in->ifindex;
        ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
-       ad.u.net->netif = indev->ifindex;
+       ad.u.net->netif = ifindex;
        ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
                return NF_DROP;
 
        if (peerlbl_active) {
-               err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
+               int err;
+
+               err = selinux_inet_sys_rcv_skb(state->net, ifindex,
                                               addrp, family, peer_sid, &ad);
                if (err) {
                        selinux_netlbl_err(skb, family, err, 1);
@@ -5737,7 +5737,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
                                 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
                        return NF_DROP;
 
-       if (netlbl_active)
+       if (netlbl_enabled())
                /* we do this in the FORWARD path and not the POST_ROUTING
                 * path because we want to make sure we apply the necessary
                 * labeling before IPsec is applied so we can leverage AH
@@ -5751,7 +5751,6 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
 static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb,
                                      const struct nf_hook_state *state)
 {
-       u16 family = state->pf;
        struct sock *sk;
        u32 sid;
 
@@ -5785,7 +5784,7 @@ static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb,
                sid = sksec->sid;
        } else
                sid = SECINITSID_KERNEL;
-       if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
+       if (selinux_netlbl_skbuff_setsid(skb, state->pf, sid) != 0)
                return NF_DROP;
 
        return NF_ACCEPT;
@@ -5793,25 +5792,24 @@ static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb,
 
 
 static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
-                                               int ifindex,
-                                               u16 family)
+                                       const struct nf_hook_state *state)
 {
-       struct sock *sk = skb_to_full_sk(skb);
+       struct sock *sk;
        struct sk_security_struct *sksec;
        struct common_audit_data ad;
        struct lsm_network_audit net = {0,};
-       char *addrp;
        u8 proto;
 
-       if (sk == NULL)
+       if (state->sk == NULL)
                return NF_ACCEPT;
+       sk = skb_to_full_sk(skb);
        sksec = sk->sk_security;
 
        ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
-       ad.u.net->netif = ifindex;
-       ad.u.net->family = family;
-       if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
+       ad.u.net->netif = state->out->ifindex;
+       ad.u.net->family = state->pf;
+       if (selinux_parse_skb(skb, &ad, NULL, 0, &proto))
                return NF_DROP;
 
        if (selinux_secmark_enabled())
@@ -5830,24 +5828,22 @@ static unsigned int selinux_ip_postroute(void *priv,
                                         struct sk_buff *skb,
                                         const struct nf_hook_state *state)
 {
-       const struct net_device *outdev = state->out;
-       u16 family = state->pf;
+       u16 family;
        u32 secmark_perm;
        u32 peer_sid;
-       int ifindex = outdev->ifindex;
+       int ifindex;
        struct sock *sk;
        struct common_audit_data ad;
        struct lsm_network_audit net = {0,};
        char *addrp;
-       u8 secmark_active;
-       u8 peerlbl_active;
+       int secmark_active, peerlbl_active;
 
        /* If any sort of compatibility mode is enabled then handoff processing
         * to the selinux_ip_postroute_compat() function to deal with the
         * special handling.  We do this in an attempt to keep this function
         * as fast and as clean as possible. */
        if (!selinux_policycap_netpeer())
-               return selinux_ip_postroute_compat(skb, ifindex, family);
+               return selinux_ip_postroute_compat(skb, state);
 
        secmark_active = selinux_secmark_enabled();
        peerlbl_active = selinux_peerlbl_enabled();
@@ -5873,6 +5869,7 @@ static unsigned int selinux_ip_postroute(void *priv,
                return NF_ACCEPT;
 #endif
 
+       family = state->pf;
        if (sk == NULL) {
                /* Without an associated socket the packet is either coming
                 * from the kernel or it is being forwarded; check the packet
@@ -5933,6 +5930,7 @@ static unsigned int selinux_ip_postroute(void *priv,
                secmark_perm = PACKET__SEND;
        }
 
+       ifindex = state->out->ifindex;
        ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->netif = ifindex;
@@ -5950,7 +5948,7 @@ static unsigned int selinux_ip_postroute(void *priv,
                u32 if_sid;
                u32 node_sid;
 
-               if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
+               if (sel_netif_sid(state->net, ifindex, &if_sid))
                        return NF_DROP;
                if (avc_has_perm(&selinux_state,
                                 peer_sid, if_sid,