Commit 089403a3 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2022-05-18

1) Fix "disable_policy" flag use when arriving from different devices.
   From Eyal Birger.

2) Fix error handling of pfkey_broadcast in function pfkey_process.
   From Jiasheng Jiang.

3) Check the encryption module availability consistency in pfkey.
   From Thomas Bartschies.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 765d1216 015c44d7
...@@ -56,6 +56,7 @@ struct inet_skb_parm { ...@@ -56,6 +56,7 @@ struct inet_skb_parm {
#define IPSKB_DOREDIRECT BIT(5) #define IPSKB_DOREDIRECT BIT(5)
#define IPSKB_FRAG_PMTU BIT(6) #define IPSKB_FRAG_PMTU BIT(6)
#define IPSKB_L3SLAVE BIT(7) #define IPSKB_L3SLAVE BIT(7)
#define IPSKB_NOPOLICY BIT(8)
u16 frag_max_size; u16 frag_max_size;
}; };
......
...@@ -1093,6 +1093,18 @@ static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb, ...@@ -1093,6 +1093,18 @@ static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb,
return false; return false;
} }
static inline bool __xfrm_check_dev_nopolicy(struct sk_buff *skb,
int dir, unsigned short family)
{
if (dir != XFRM_POLICY_OUT && family == AF_INET) {
/* same dst may be used for traffic originating from
* devices with different policy settings.
*/
return IPCB(skb)->flags & IPSKB_NOPOLICY;
}
return skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY);
}
static inline int __xfrm_policy_check2(struct sock *sk, int dir, static inline int __xfrm_policy_check2(struct sock *sk, int dir,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int family, int reverse) unsigned int family, int reverse)
...@@ -1104,7 +1116,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir, ...@@ -1104,7 +1116,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
return __xfrm_policy_check(sk, ndir, skb, family); return __xfrm_policy_check(sk, ndir, skb, family);
return __xfrm_check_nopolicy(net, skb, dir) || return __xfrm_check_nopolicy(net, skb, dir) ||
(skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || __xfrm_check_dev_nopolicy(skb, dir, family) ||
__xfrm_policy_check(sk, ndir, skb, family); __xfrm_policy_check(sk, ndir, skb, family);
} }
......
...@@ -1726,6 +1726,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -1726,6 +1726,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
struct in_device *in_dev = __in_dev_get_rcu(dev); struct in_device *in_dev = __in_dev_get_rcu(dev);
unsigned int flags = RTCF_MULTICAST; unsigned int flags = RTCF_MULTICAST;
struct rtable *rth; struct rtable *rth;
bool no_policy;
u32 itag = 0; u32 itag = 0;
int err; int err;
...@@ -1736,8 +1737,12 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -1736,8 +1737,12 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (our) if (our)
flags |= RTCF_LOCAL; flags |= RTCF_LOCAL;
no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
if (no_policy)
IPCB(skb)->flags |= IPSKB_NOPOLICY;
rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST, rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
IN_DEV_ORCONF(in_dev, NOPOLICY), false); no_policy, false);
if (!rth) if (!rth)
return -ENOBUFS; return -ENOBUFS;
...@@ -1796,7 +1801,7 @@ static int __mkroute_input(struct sk_buff *skb, ...@@ -1796,7 +1801,7 @@ static int __mkroute_input(struct sk_buff *skb,
struct rtable *rth; struct rtable *rth;
int err; int err;
struct in_device *out_dev; struct in_device *out_dev;
bool do_cache; bool do_cache, no_policy;
u32 itag = 0; u32 itag = 0;
/* get a working reference to the output device */ /* get a working reference to the output device */
...@@ -1841,6 +1846,10 @@ static int __mkroute_input(struct sk_buff *skb, ...@@ -1841,6 +1846,10 @@ static int __mkroute_input(struct sk_buff *skb,
} }
} }
no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
if (no_policy)
IPCB(skb)->flags |= IPSKB_NOPOLICY;
fnhe = find_exception(nhc, daddr); fnhe = find_exception(nhc, daddr);
if (do_cache) { if (do_cache) {
if (fnhe) if (fnhe)
...@@ -1853,8 +1862,7 @@ static int __mkroute_input(struct sk_buff *skb, ...@@ -1853,8 +1862,7 @@ static int __mkroute_input(struct sk_buff *skb,
} }
} }
rth = rt_dst_alloc(out_dev->dev, 0, res->type, rth = rt_dst_alloc(out_dev->dev, 0, res->type, no_policy,
IN_DEV_ORCONF(in_dev, NOPOLICY),
IN_DEV_ORCONF(out_dev, NOXFRM)); IN_DEV_ORCONF(out_dev, NOXFRM));
if (!rth) { if (!rth) {
err = -ENOBUFS; err = -ENOBUFS;
...@@ -2229,6 +2237,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -2229,6 +2237,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
struct rtable *rth; struct rtable *rth;
struct flowi4 fl4; struct flowi4 fl4;
bool do_cache = true; bool do_cache = true;
bool no_policy;
/* IP on this device is disabled. */ /* IP on this device is disabled. */
...@@ -2347,6 +2356,10 @@ out: return err; ...@@ -2347,6 +2356,10 @@ out: return err;
RT_CACHE_STAT_INC(in_brd); RT_CACHE_STAT_INC(in_brd);
local_input: local_input:
no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
if (no_policy)
IPCB(skb)->flags |= IPSKB_NOPOLICY;
do_cache &= res->fi && !itag; do_cache &= res->fi && !itag;
if (do_cache) { if (do_cache) {
struct fib_nh_common *nhc = FIB_RES_NHC(*res); struct fib_nh_common *nhc = FIB_RES_NHC(*res);
...@@ -2361,7 +2374,7 @@ out: return err; ...@@ -2361,7 +2374,7 @@ out: return err;
rth = rt_dst_alloc(ip_rt_get_dev(net, res), rth = rt_dst_alloc(ip_rt_get_dev(net, res),
flags | RTCF_LOCAL, res->type, flags | RTCF_LOCAL, res->type,
IN_DEV_ORCONF(in_dev, NOPOLICY), false); no_policy, false);
if (!rth) if (!rth)
goto e_nobufs; goto e_nobufs;
......
...@@ -2826,8 +2826,10 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb ...@@ -2826,8 +2826,10 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
void *ext_hdrs[SADB_EXT_MAX]; void *ext_hdrs[SADB_EXT_MAX];
int err; int err;
pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, err = pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
BROADCAST_PROMISC_ONLY, NULL, sock_net(sk)); BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
if (err)
return err;
memset(ext_hdrs, 0, sizeof(ext_hdrs)); memset(ext_hdrs, 0, sizeof(ext_hdrs));
err = parse_exthdrs(skb, hdr, ext_hdrs); err = parse_exthdrs(skb, hdr, ext_hdrs);
...@@ -2898,7 +2900,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t) ...@@ -2898,7 +2900,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t)
break; break;
if (!aalg->pfkey_supported) if (!aalg->pfkey_supported)
continue; continue;
if (aalg_tmpl_set(t, aalg)) if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
return sz + sizeof(struct sadb_prop); return sz + sizeof(struct sadb_prop);
...@@ -2916,7 +2918,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) ...@@ -2916,7 +2918,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
if (!ealg->pfkey_supported) if (!ealg->pfkey_supported)
continue; continue;
if (!(ealg_tmpl_set(t, ealg))) if (!(ealg_tmpl_set(t, ealg) && ealg->available))
continue; continue;
for (k = 1; ; k++) { for (k = 1; ; k++) {
...@@ -2927,7 +2929,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) ...@@ -2927,7 +2929,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
if (!aalg->pfkey_supported) if (!aalg->pfkey_supported)
continue; continue;
if (aalg_tmpl_set(t, aalg)) if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
} }
......
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