Commit b145745f 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 2019-04-30

1) Fix an out-of-bound array accesses in __xfrm_policy_unlink.
   From YueHaibing.

2) Reset the secpath on failure in the ESP GRO handlers
   to avoid dereferencing an invalid pointer on error.
   From Myungho Jung.

3) Add and revert a patch that tried to add rcu annotations
   to netns_xfrm. From Su Yanjun.

4) Wait for rcu callbacks before freeing xfrm6_tunnel_spi_kmem.
   From Su Yanjun.

5) Fix forgotten vti4 ipip tunnel deregistration.
   From Jeremy Sowden:

6) Remove some duplicated log messages in vti4.
   From Jeremy Sowden.

7) Don't use IPSEC_PROTO_ANY when flushing states because
   this will flush only IPsec portocol speciffic states.
   IPPROTO_ROUTING states may remain in the lists when
   doing net exit. Fix this by replacing IPSEC_PROTO_ANY
   with zero. From Cong Wang.

8) Add length check for UDP encapsulation to fix "Oversized IP packet"
   warnings on receive side. From Sabrina Dubroca.

9) Fix xfrm interface lookup when the interface is associated to
   a vrf layer 3 master device. From Martin Willi.

10) Reload header pointers after pskb_may_pull() in _decode_session4(),
    otherwise we may read from uninitialized memory.

11) Update the documentation about xfrm[46]_gc_thresh, it
    is not used anymore after the flowcache removal.
    From Nicolas Dichtel.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6c0afef5 837f7411
...@@ -1337,6 +1337,7 @@ tag - INTEGER ...@@ -1337,6 +1337,7 @@ tag - INTEGER
Default value is 0. Default value is 0.
xfrm4_gc_thresh - INTEGER xfrm4_gc_thresh - INTEGER
(Obsolete since linux-4.14)
The threshold at which we will start garbage collecting for IPv4 The threshold at which we will start garbage collecting for IPv4
destination cache entries. At twice this value the system will destination cache entries. At twice this value the system will
refuse new allocations. refuse new allocations.
...@@ -1920,6 +1921,7 @@ echo_ignore_all - BOOLEAN ...@@ -1920,6 +1921,7 @@ echo_ignore_all - BOOLEAN
Default: 0 Default: 0
xfrm6_gc_thresh - INTEGER xfrm6_gc_thresh - INTEGER
(Obsolete since linux-4.14)
The threshold at which we will start garbage collecting for IPv6 The threshold at which we will start garbage collecting for IPv6
destination cache entries. At twice this value the system will destination cache entries. At twice this value the system will
refuse new allocations. refuse new allocations.
......
...@@ -295,7 +295,8 @@ struct xfrm_replay { ...@@ -295,7 +295,8 @@ struct xfrm_replay {
}; };
struct xfrm_if_cb { struct xfrm_if_cb {
struct xfrm_if *(*decode_session)(struct sk_buff *skb); struct xfrm_if *(*decode_session)(struct sk_buff *skb,
unsigned short family);
}; };
void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb); void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
...@@ -1404,6 +1405,23 @@ static inline int xfrm_state_kern(const struct xfrm_state *x) ...@@ -1404,6 +1405,23 @@ static inline int xfrm_state_kern(const struct xfrm_state *x)
return atomic_read(&x->tunnel_users); return atomic_read(&x->tunnel_users);
} }
static inline bool xfrm_id_proto_valid(u8 proto)
{
switch (proto) {
case IPPROTO_AH:
case IPPROTO_ESP:
case IPPROTO_COMP:
#if IS_ENABLED(CONFIG_IPV6)
case IPPROTO_ROUTING:
case IPPROTO_DSTOPTS:
#endif
return true;
default:
return false;
}
}
/* IPSEC_PROTO_ANY only matches 3 IPsec protocols, 0 could match all. */
static inline int xfrm_id_proto_match(u8 proto, u8 userproto) static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
{ {
return (!userproto || proto == userproto || return (!userproto || proto == userproto ||
......
...@@ -226,7 +226,7 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto) ...@@ -226,7 +226,7 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
tail[plen - 1] = proto; tail[plen - 1] = proto;
} }
static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) static int esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
{ {
int encap_type; int encap_type;
struct udphdr *uh; struct udphdr *uh;
...@@ -234,6 +234,7 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru ...@@ -234,6 +234,7 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
__be16 sport, dport; __be16 sport, dport;
struct xfrm_encap_tmpl *encap = x->encap; struct xfrm_encap_tmpl *encap = x->encap;
struct ip_esp_hdr *esph = esp->esph; struct ip_esp_hdr *esph = esp->esph;
unsigned int len;
spin_lock_bh(&x->lock); spin_lock_bh(&x->lock);
sport = encap->encap_sport; sport = encap->encap_sport;
...@@ -241,11 +242,14 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru ...@@ -241,11 +242,14 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
encap_type = encap->encap_type; encap_type = encap->encap_type;
spin_unlock_bh(&x->lock); spin_unlock_bh(&x->lock);
len = skb->len + esp->tailen - skb_transport_offset(skb);
if (len + sizeof(struct iphdr) >= IP_MAX_MTU)
return -EMSGSIZE;
uh = (struct udphdr *)esph; uh = (struct udphdr *)esph;
uh->source = sport; uh->source = sport;
uh->dest = dport; uh->dest = dport;
uh->len = htons(skb->len + esp->tailen uh->len = htons(len);
- skb_transport_offset(skb));
uh->check = 0; uh->check = 0;
switch (encap_type) { switch (encap_type) {
...@@ -262,6 +266,8 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru ...@@ -262,6 +266,8 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
*skb_mac_header(skb) = IPPROTO_UDP; *skb_mac_header(skb) = IPPROTO_UDP;
esp->esph = esph; esp->esph = esph;
return 0;
} }
int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
...@@ -275,8 +281,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * ...@@ -275,8 +281,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
int tailen = esp->tailen; int tailen = esp->tailen;
/* this is non-NULL only with UDP Encapsulation */ /* this is non-NULL only with UDP Encapsulation */
if (x->encap) if (x->encap) {
esp_output_udp_encap(x, skb, esp); int err = esp_output_udp_encap(x, skb, esp);
if (err < 0)
return err;
}
if (!skb_cloned(skb)) { if (!skb_cloned(skb)) {
if (tailen <= skb_tailroom(skb)) { if (tailen <= skb_tailroom(skb)) {
......
...@@ -52,13 +52,13 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head, ...@@ -52,13 +52,13 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head,
goto out; goto out;
if (sp->len == XFRM_MAX_DEPTH) if (sp->len == XFRM_MAX_DEPTH)
goto out; goto out_reset;
x = xfrm_state_lookup(dev_net(skb->dev), skb->mark, x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
(xfrm_address_t *)&ip_hdr(skb)->daddr, (xfrm_address_t *)&ip_hdr(skb)->daddr,
spi, IPPROTO_ESP, AF_INET); spi, IPPROTO_ESP, AF_INET);
if (!x) if (!x)
goto out; goto out_reset;
sp->xvec[sp->len++] = x; sp->xvec[sp->len++] = x;
sp->olen++; sp->olen++;
...@@ -66,7 +66,7 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head, ...@@ -66,7 +66,7 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head,
xo = xfrm_offload(skb); xo = xfrm_offload(skb);
if (!xo) { if (!xo) {
xfrm_state_put(x); xfrm_state_put(x);
goto out; goto out_reset;
} }
} }
...@@ -82,6 +82,8 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head, ...@@ -82,6 +82,8 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head,
xfrm_input(skb, IPPROTO_ESP, spi, -2); xfrm_input(skb, IPPROTO_ESP, spi, -2);
return ERR_PTR(-EINPROGRESS); return ERR_PTR(-EINPROGRESS);
out_reset:
secpath_reset(skb);
out: out:
skb_push(skb, offset); skb_push(skb, offset);
NAPI_GRO_CB(skb)->same_flow = 0; NAPI_GRO_CB(skb)->same_flow = 0;
......
...@@ -646,10 +646,8 @@ static int __init vti_init(void) ...@@ -646,10 +646,8 @@ static int __init vti_init(void)
msg = "ipip tunnel"; msg = "ipip tunnel";
err = xfrm4_tunnel_register(&ipip_handler, AF_INET); err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
if (err < 0) { if (err < 0)
pr_info("%s: cant't register tunnel\n",__func__);
goto xfrm_tunnel_failed; goto xfrm_tunnel_failed;
}
msg = "netlink interface"; msg = "netlink interface";
err = rtnl_link_register(&vti_link_ops); err = rtnl_link_register(&vti_link_ops);
...@@ -659,9 +657,9 @@ static int __init vti_init(void) ...@@ -659,9 +657,9 @@ static int __init vti_init(void)
return err; return err;
rtnl_link_failed: rtnl_link_failed:
xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
xfrm_tunnel_failed:
xfrm4_tunnel_deregister(&ipip_handler, AF_INET); xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
xfrm_tunnel_failed:
xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
xfrm_proto_comp_failed: xfrm_proto_comp_failed:
xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
xfrm_proto_ah_failed: xfrm_proto_ah_failed:
...@@ -676,6 +674,7 @@ static int __init vti_init(void) ...@@ -676,6 +674,7 @@ static int __init vti_init(void)
static void __exit vti_fini(void) static void __exit vti_fini(void)
{ {
rtnl_link_unregister(&vti_link_ops); rtnl_link_unregister(&vti_link_ops);
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
......
...@@ -111,7 +111,8 @@ static void ...@@ -111,7 +111,8 @@ static void
_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
{ {
const struct iphdr *iph = ip_hdr(skb); const struct iphdr *iph = ip_hdr(skb);
u8 *xprth = skb_network_header(skb) + iph->ihl * 4; int ihl = iph->ihl;
u8 *xprth = skb_network_header(skb) + ihl * 4;
struct flowi4 *fl4 = &fl->u.ip4; struct flowi4 *fl4 = &fl->u.ip4;
int oif = 0; int oif = 0;
...@@ -122,6 +123,11 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -122,6 +123,11 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
fl4->flowi4_mark = skb->mark; fl4->flowi4_mark = skb->mark;
fl4->flowi4_oif = reverse ? skb->skb_iif : oif; fl4->flowi4_oif = reverse ? skb->skb_iif : oif;
fl4->flowi4_proto = iph->protocol;
fl4->daddr = reverse ? iph->saddr : iph->daddr;
fl4->saddr = reverse ? iph->daddr : iph->saddr;
fl4->flowi4_tos = iph->tos;
if (!ip_is_fragment(iph)) { if (!ip_is_fragment(iph)) {
switch (iph->protocol) { switch (iph->protocol) {
case IPPROTO_UDP: case IPPROTO_UDP:
...@@ -133,7 +139,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -133,7 +139,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 4 - skb->data)) { pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be16 *ports; __be16 *ports;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ports = (__be16 *)xprth; ports = (__be16 *)xprth;
fl4->fl4_sport = ports[!!reverse]; fl4->fl4_sport = ports[!!reverse];
...@@ -146,7 +152,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -146,7 +152,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 2 - skb->data)) { pskb_may_pull(skb, xprth + 2 - skb->data)) {
u8 *icmp; u8 *icmp;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
icmp = xprth; icmp = xprth;
fl4->fl4_icmp_type = icmp[0]; fl4->fl4_icmp_type = icmp[0];
...@@ -159,7 +165,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -159,7 +165,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 4 - skb->data)) { pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be32 *ehdr; __be32 *ehdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ehdr = (__be32 *)xprth; ehdr = (__be32 *)xprth;
fl4->fl4_ipsec_spi = ehdr[0]; fl4->fl4_ipsec_spi = ehdr[0];
...@@ -171,7 +177,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -171,7 +177,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 8 - skb->data)) { pskb_may_pull(skb, xprth + 8 - skb->data)) {
__be32 *ah_hdr; __be32 *ah_hdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ah_hdr = (__be32 *)xprth; ah_hdr = (__be32 *)xprth;
fl4->fl4_ipsec_spi = ah_hdr[1]; fl4->fl4_ipsec_spi = ah_hdr[1];
...@@ -183,7 +189,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -183,7 +189,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 4 - skb->data)) { pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be16 *ipcomp_hdr; __be16 *ipcomp_hdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ipcomp_hdr = (__be16 *)xprth; ipcomp_hdr = (__be16 *)xprth;
fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
...@@ -196,7 +202,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -196,7 +202,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
__be16 *greflags; __be16 *greflags;
__be32 *gre_hdr; __be32 *gre_hdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
greflags = (__be16 *)xprth; greflags = (__be16 *)xprth;
gre_hdr = (__be32 *)xprth; gre_hdr = (__be32 *)xprth;
...@@ -213,10 +219,6 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -213,10 +219,6 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
break; break;
} }
} }
fl4->flowi4_proto = iph->protocol;
fl4->daddr = reverse ? iph->saddr : iph->daddr;
fl4->saddr = reverse ? iph->daddr : iph->saddr;
fl4->flowi4_tos = iph->tos;
} }
static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk,
......
...@@ -74,13 +74,13 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head, ...@@ -74,13 +74,13 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
goto out; goto out;
if (sp->len == XFRM_MAX_DEPTH) if (sp->len == XFRM_MAX_DEPTH)
goto out; goto out_reset;
x = xfrm_state_lookup(dev_net(skb->dev), skb->mark, x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
(xfrm_address_t *)&ipv6_hdr(skb)->daddr, (xfrm_address_t *)&ipv6_hdr(skb)->daddr,
spi, IPPROTO_ESP, AF_INET6); spi, IPPROTO_ESP, AF_INET6);
if (!x) if (!x)
goto out; goto out_reset;
sp->xvec[sp->len++] = x; sp->xvec[sp->len++] = x;
sp->olen++; sp->olen++;
...@@ -88,7 +88,7 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head, ...@@ -88,7 +88,7 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
xo = xfrm_offload(skb); xo = xfrm_offload(skb);
if (!xo) { if (!xo) {
xfrm_state_put(x); xfrm_state_put(x);
goto out; goto out_reset;
} }
} }
...@@ -109,6 +109,8 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head, ...@@ -109,6 +109,8 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
xfrm_input(skb, IPPROTO_ESP, spi, -2); xfrm_input(skb, IPPROTO_ESP, spi, -2);
return ERR_PTR(-EINPROGRESS); return ERR_PTR(-EINPROGRESS);
out_reset:
secpath_reset(skb);
out: out:
skb_push(skb, offset); skb_push(skb, offset);
NAPI_GRO_CB(skb)->same_flow = 0; NAPI_GRO_CB(skb)->same_flow = 0;
......
...@@ -345,7 +345,7 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net) ...@@ -345,7 +345,7 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
unsigned int i; unsigned int i;
xfrm_flush_gc(); xfrm_flush_gc();
xfrm_state_flush(net, IPSEC_PROTO_ANY, false, true); xfrm_state_flush(net, 0, false, true);
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i])); WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));
...@@ -402,6 +402,10 @@ static void __exit xfrm6_tunnel_fini(void) ...@@ -402,6 +402,10 @@ static void __exit xfrm6_tunnel_fini(void)
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
unregister_pernet_subsys(&xfrm6_tunnel_net_ops); unregister_pernet_subsys(&xfrm6_tunnel_net_ops);
/* Someone maybe has gotten the xfrm6_tunnel_spi.
* So need to wait it.
*/
rcu_barrier();
kmem_cache_destroy(xfrm6_tunnel_spi_kmem); kmem_cache_destroy(xfrm6_tunnel_spi_kmem);
} }
......
...@@ -1951,8 +1951,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) ...@@ -1951,8 +1951,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
if (rq->sadb_x_ipsecrequest_mode == 0) if (rq->sadb_x_ipsecrequest_mode == 0)
return -EINVAL; return -EINVAL;
if (!xfrm_id_proto_valid(rq->sadb_x_ipsecrequest_proto))
return -EINVAL;
t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */ t->id.proto = rq->sadb_x_ipsecrequest_proto;
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0) if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL; return -EINVAL;
t->mode = mode; t->mode = mode;
......
...@@ -70,17 +70,28 @@ static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x) ...@@ -70,17 +70,28 @@ static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
return NULL; return NULL;
} }
static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb) static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
unsigned short family)
{ {
struct xfrmi_net *xfrmn; struct xfrmi_net *xfrmn;
int ifindex;
struct xfrm_if *xi; struct xfrm_if *xi;
int ifindex = 0;
if (!secpath_exists(skb) || !skb->dev) if (!secpath_exists(skb) || !skb->dev)
return NULL; return NULL;
switch (family) {
case AF_INET6:
ifindex = inet6_sdif(skb);
break;
case AF_INET:
ifindex = inet_sdif(skb);
break;
}
if (!ifindex)
ifindex = skb->dev->ifindex;
xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id); xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id);
ifindex = skb->dev->ifindex;
for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) { for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
if (ifindex == xi->dev->ifindex && if (ifindex == xi->dev->ifindex &&
......
...@@ -3313,7 +3313,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -3313,7 +3313,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
ifcb = xfrm_if_get_cb(); ifcb = xfrm_if_get_cb();
if (ifcb) { if (ifcb) {
xi = ifcb->decode_session(skb); xi = ifcb->decode_session(skb, family);
if (xi) { if (xi) {
if_id = xi->p.if_id; if_id = xi->p.if_id;
net = xi->net; net = xi->net;
......
...@@ -2384,7 +2384,7 @@ void xfrm_state_fini(struct net *net) ...@@ -2384,7 +2384,7 @@ void xfrm_state_fini(struct net *net)
flush_work(&net->xfrm.state_hash_work); flush_work(&net->xfrm.state_hash_work);
flush_work(&xfrm_state_gc_work); flush_work(&xfrm_state_gc_work);
xfrm_state_flush(net, IPSEC_PROTO_ANY, false, true); xfrm_state_flush(net, 0, false, true);
WARN_ON(!list_empty(&net->xfrm.state_all)); WARN_ON(!list_empty(&net->xfrm.state_all));
......
...@@ -1424,7 +1424,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) ...@@ -1424,7 +1424,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
ret = verify_policy_dir(p->dir); ret = verify_policy_dir(p->dir);
if (ret) if (ret)
return ret; return ret;
if (p->index && ((p->index & XFRM_POLICY_MAX) != p->dir)) if (p->index && (xfrm_policy_id2dir(p->index) != p->dir))
return -EINVAL; return -EINVAL;
return 0; return 0;
...@@ -1513,20 +1513,8 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) ...@@ -1513,20 +1513,8 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
return -EINVAL; return -EINVAL;
} }
switch (ut[i].id.proto) { if (!xfrm_id_proto_valid(ut[i].id.proto))
case IPPROTO_AH:
case IPPROTO_ESP:
case IPPROTO_COMP:
#if IS_ENABLED(CONFIG_IPV6)
case IPPROTO_ROUTING:
case IPPROTO_DSTOPTS:
#endif
case IPSEC_PROTO_ANY:
break;
default:
return -EINVAL; return -EINVAL;
}
} }
return 0; return 0;
......
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