xfrm: rework default policy structure
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Mon, 14 Mar 2022 10:38:22 +0000 (11:38 +0100)
committerSteffen Klassert <steffen.klassert@secunet.com>
Fri, 18 Mar 2022 06:23:12 +0000 (07:23 +0100)
This is a follow up of commit f8d858e607b2 ("xfrm: make user policy API
complete"). The goal is to align userland API to the internal structures.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
include/net/netns/xfrm.h
include/net/xfrm.h
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c

index 947733a..bd7c3be 100644 (file)
@@ -66,11 +66,7 @@ struct netns_xfrm {
        int                     sysctl_larval_drop;
        u32                     sysctl_acq_expires;
 
-       u8                      policy_default;
-#define XFRM_POL_DEFAULT_IN    1
-#define XFRM_POL_DEFAULT_OUT   2
-#define XFRM_POL_DEFAULT_FWD   4
-#define XFRM_POL_DEFAULT_MASK  7
+       u8                      policy_default[XFRM_POLICY_MAX];
 
 #ifdef CONFIG_SYSCTL
        struct ctl_table_header *sysctl_hdr;
index fdb41e8..1541ca0 100644 (file)
@@ -1081,25 +1081,18 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un
 }
 
 #ifdef CONFIG_XFRM
-static inline bool
-xfrm_default_allow(struct net *net, int dir)
-{
-       u8 def = net->xfrm.policy_default;
-
-       switch (dir) {
-       case XFRM_POLICY_IN:
-               return def & XFRM_POL_DEFAULT_IN ? false : true;
-       case XFRM_POLICY_OUT:
-               return def & XFRM_POL_DEFAULT_OUT ? false : true;
-       case XFRM_POLICY_FWD:
-               return def & XFRM_POL_DEFAULT_FWD ? false : true;
-       }
-       return false;
-}
-
 int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
                        unsigned short family);
 
+static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb,
+                                        int dir)
+{
+       if (!net->xfrm.policy_count[dir] && !secpath_exists(skb))
+               return net->xfrm.policy_default[dir] == XFRM_USERPOLICY_ACCEPT;
+
+       return false;
+}
+
 static inline int __xfrm_policy_check2(struct sock *sk, int dir,
                                       struct sk_buff *skb,
                                       unsigned int family, int reverse)
@@ -1110,13 +1103,9 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
        if (sk && sk->sk_policy[XFRM_POLICY_IN])
                return __xfrm_policy_check(sk, ndir, skb, family);
 
-       if (xfrm_default_allow(net, dir))
-               return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) ||
-                      (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
-                      __xfrm_policy_check(sk, ndir, skb, family);
-       else
-               return (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
-                      __xfrm_policy_check(sk, ndir, skb, family);
+       return __xfrm_check_nopolicy(net, skb, dir) ||
+              (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
+              __xfrm_policy_check(sk, ndir, skb, family);
 }
 
 static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
@@ -1168,13 +1157,12 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 {
        struct net *net = dev_net(skb->dev);
 
-       if (xfrm_default_allow(net, XFRM_POLICY_OUT))
-               return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
-                       (skb_dst(skb)->flags & DST_NOXFRM) ||
-                       __xfrm_route_forward(skb, family);
-       else
-               return (skb_dst(skb)->flags & DST_NOXFRM) ||
-                       __xfrm_route_forward(skb, family);
+       if (!net->xfrm.policy_count[XFRM_POLICY_OUT] &&
+           net->xfrm.policy_default[XFRM_POLICY_OUT] == XFRM_USERPOLICY_ACCEPT)
+               return true;
+
+       return (skb_dst(skb)->flags & DST_NOXFRM) ||
+              __xfrm_route_forward(skb, family);
 }
 
 static inline int xfrm4_route_forward(struct sk_buff *skb)
index 04d1ce9..01fe1e9 100644 (file)
@@ -3158,7 +3158,7 @@ ok:
 
 nopol:
        if (!(dst_orig->dev->flags & IFF_LOOPBACK) &&
-           !xfrm_default_allow(net, dir)) {
+           net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
                err = -EPERM;
                goto error;
        }
@@ -3569,7 +3569,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
        }
 
        if (!pol) {
-               if (!xfrm_default_allow(net, dir)) {
+               if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
                        return 0;
                }
@@ -3629,7 +3629,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                }
                xfrm_nr = ti;
 
-               if (!xfrm_default_allow(net, dir) && !xfrm_nr) {
+               if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK &&
+                   !xfrm_nr) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
                        goto reject;
                }
@@ -4118,6 +4119,9 @@ static int __net_init xfrm_net_init(struct net *net)
        spin_lock_init(&net->xfrm.xfrm_policy_lock);
        seqcount_spinlock_init(&net->xfrm.xfrm_policy_hash_generation, &net->xfrm.xfrm_policy_lock);
        mutex_init(&net->xfrm.xfrm_cfg_mutex);
+       net->xfrm.policy_default[XFRM_POLICY_IN] = XFRM_USERPOLICY_ACCEPT;
+       net->xfrm.policy_default[XFRM_POLICY_FWD] = XFRM_USERPOLICY_ACCEPT;
+       net->xfrm.policy_default[XFRM_POLICY_OUT] = XFRM_USERPOLICY_ACCEPT;
 
        rv = xfrm_statistics_init(net);
        if (rv < 0)
index 8cd6c81..2f6b64c 100644 (file)
@@ -2009,12 +2009,9 @@ static int xfrm_notify_userpolicy(struct net *net)
        }
 
        up = nlmsg_data(nlh);
-       up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
-                       XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
-       up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
-                       XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
-       up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
-                       XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
+       up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
+       up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD];
+       up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
 
        nlmsg_end(skb, nlh);
 
@@ -2025,26 +2022,26 @@ static int xfrm_notify_userpolicy(struct net *net)
        return err;
 }
 
+static bool xfrm_userpolicy_is_valid(__u8 policy)
+{
+       return policy == XFRM_USERPOLICY_BLOCK ||
+              policy == XFRM_USERPOLICY_ACCEPT;
+}
+
 static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
                            struct nlattr **attrs)
 {
        struct net *net = sock_net(skb->sk);
        struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
 
-       if (up->in == XFRM_USERPOLICY_BLOCK)
-               net->xfrm.policy_default |= XFRM_POL_DEFAULT_IN;
-       else if (up->in == XFRM_USERPOLICY_ACCEPT)
-               net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_IN;
+       if (xfrm_userpolicy_is_valid(up->in))
+               net->xfrm.policy_default[XFRM_POLICY_IN] = up->in;
 
-       if (up->fwd == XFRM_USERPOLICY_BLOCK)
-               net->xfrm.policy_default |= XFRM_POL_DEFAULT_FWD;
-       else if (up->fwd == XFRM_USERPOLICY_ACCEPT)
-               net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_FWD;
+       if (xfrm_userpolicy_is_valid(up->fwd))
+               net->xfrm.policy_default[XFRM_POLICY_FWD] = up->fwd;
 
-       if (up->out == XFRM_USERPOLICY_BLOCK)
-               net->xfrm.policy_default |= XFRM_POL_DEFAULT_OUT;
-       else if (up->out == XFRM_USERPOLICY_ACCEPT)
-               net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_OUT;
+       if (xfrm_userpolicy_is_valid(up->out))
+               net->xfrm.policy_default[XFRM_POLICY_OUT] = up->out;
 
        rt_genid_bump_all(net);
 
@@ -2074,13 +2071,9 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
        }
 
        r_up = nlmsg_data(r_nlh);
-
-       r_up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
-                       XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
-       r_up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
-                       XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
-       r_up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
-                       XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
+       r_up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
+       r_up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD];
+       r_up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
        nlmsg_end(r_skb, r_nlh);
 
        return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid);