Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2022-01-06

1) Fix xfrm policy lookups for ipv6 gre packets by initializing
   fl6_gre_key properly. From Ghalem Boudour.

2) Fix the dflt policy check on forwarding when there is no
   policy configured. The check was done for the wrong direction.
   From Nicolas Dichtel.

3) Use the correct 'struct xfrm_user_offload' when calculating
   netlink message lenghts in xfrm_sa_len(). From Eric Dumazet.

4) Tread inserting xfrm interface id 0 as an error.
   From Antony Antony.

5) Fail if xfrm state or policy is inserted with XFRMA_IF_ID 0,
   xfrm interfaces with id 0 are not allowed.
   From Antony Antony.

6) Fix inner_ipproto setting in the sec_path for tunnel mode.
   From  Raed Salem.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 6, 2022
2 parents 502a2ce + 45a98ef commit c4251db
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 13 deletions.
2 changes: 1 addition & 1 deletion include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ 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_FWD))
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);
Expand Down
5 changes: 4 additions & 1 deletion net/ipv6/ip6_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
fl6->daddr = key->u.ipv6.dst;
fl6->flowlabel = key->label;
fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
fl6->fl6_gre_key = tunnel_id_to_key32(key->tun_id);

dsfield = key->tos;
flags = key->tun_flags &
Expand Down Expand Up @@ -990,6 +991,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
fl6.daddr = key->u.ipv6.dst;
fl6.flowlabel = key->label;
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
fl6.fl6_gre_key = tunnel_id_to_key32(key->tun_id);

dsfield = key->tos;
if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
Expand Down Expand Up @@ -1098,6 +1100,7 @@ static void ip6gre_tnl_link_config_common(struct ip6_tnl *t)
fl6->flowi6_oif = p->link;
fl6->flowlabel = 0;
fl6->flowi6_proto = IPPROTO_GRE;
fl6->fl6_gre_key = t->parms.o_key;

if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
Expand Down Expand Up @@ -1544,7 +1547,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
static struct inet6_protocol ip6gre_protocol __read_mostly = {
.handler = gre_rcv,
.err_handler = ip6gre_err,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
.flags = INET6_PROTO_FINAL,
};

static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
Expand Down
14 changes: 12 additions & 2 deletions net/xfrm/xfrm_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,16 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct net *net = dev_net(dev);
struct xfrm_if_parms p;
struct xfrm_if_parms p = {};
struct xfrm_if *xi;
int err;

xfrmi_netlink_parms(data, &p);
if (!p.if_id) {
NL_SET_ERR_MSG(extack, "if_id must be non zero");
return -EINVAL;
}

xi = xfrmi_locate(net, &p);
if (xi)
return -EEXIST;
Expand All @@ -666,7 +671,12 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
{
struct xfrm_if *xi = netdev_priv(dev);
struct net *net = xi->net;
struct xfrm_if_parms p;
struct xfrm_if_parms p = {};

if (!p.if_id) {
NL_SET_ERR_MSG(extack, "if_id must be non zero");
return -EINVAL;
}

xfrmi_netlink_parms(data, &p);
xi = xfrmi_locate(net, &p);
Expand Down
30 changes: 25 additions & 5 deletions net/xfrm/xfrm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,17 +647,38 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb
* This requires hardware to know the inner packet type to calculate
* the inner header checksum. Save inner ip protocol here to avoid
* traversing the packet in the vendor's xmit code.
* If the encap type is IPIP, just save skb->inner_ipproto. Otherwise,
* get the ip protocol from the IP header.
* For IPsec tunnel mode save the ip protocol from the IP header of the
* plain text packet. Otherwise If the encap type is IPIP, just save
* skb->inner_ipproto in any other case get the ip protocol from the IP
* header.
*/
static void xfrm_get_inner_ipproto(struct sk_buff *skb)
static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x)
{
struct xfrm_offload *xo = xfrm_offload(skb);
const struct ethhdr *eth;

if (!xo)
return;

if (x->outer_mode.encap == XFRM_MODE_TUNNEL) {
switch (x->outer_mode.family) {
case AF_INET:
xo->inner_ipproto = ip_hdr(skb)->protocol;
break;
case AF_INET6:
xo->inner_ipproto = ipv6_hdr(skb)->nexthdr;
break;
default:
break;
}

return;
}

/* non-Tunnel Mode */
if (!skb->encapsulation)
return;

if (skb->inner_protocol_type == ENCAP_TYPE_IPPROTO) {
xo->inner_ipproto = skb->inner_ipproto;
return;
Expand Down Expand Up @@ -712,8 +733,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
sp->xvec[sp->len++] = x;
xfrm_state_hold(x);

if (skb->encapsulation)
xfrm_get_inner_ipproto(skb);
xfrm_get_inner_ipproto(skb, x);
skb->encapsulation = 1;

if (skb_is_gso(skb)) {
Expand Down
21 changes: 21 additions & 0 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <net/flow.h>
#include <net/xfrm.h>
#include <net/ip.h>
#include <net/gre.h>
#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/mip6.h>
#endif
Expand Down Expand Up @@ -3422,6 +3423,26 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse)
}
fl6->flowi6_proto = nexthdr;
return;
case IPPROTO_GRE:
if (!onlyproto &&
(nh + offset + 12 < skb->data ||
pskb_may_pull(skb, nh + offset + 12 - skb->data))) {
struct gre_base_hdr *gre_hdr;
__be32 *gre_key;

nh = skb_network_header(skb);
gre_hdr = (struct gre_base_hdr *)(nh + offset);
gre_key = (__be32 *)(gre_hdr + 1);

if (gre_hdr->flags & GRE_KEY) {
if (gre_hdr->flags & GRE_CSUM)
gre_key++;
fl6->fl6_gre_key = *gre_key;
}
}
fl6->flowi6_proto = nexthdr;
return;

#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPPROTO_MH:
offset += ipv6_optlen(exthdr);
Expand Down
23 changes: 19 additions & 4 deletions net/xfrm/xfrm_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,13 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,

xfrm_smark_init(attrs, &x->props.smark);

if (attrs[XFRMA_IF_ID])
if (attrs[XFRMA_IF_ID]) {
x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
if (!x->if_id) {
err = -EINVAL;
goto error;
}
}

err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
if (err)
Expand Down Expand Up @@ -1413,8 +1418,13 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,

mark = xfrm_mark_get(attrs, &m);

if (attrs[XFRMA_IF_ID])
if (attrs[XFRMA_IF_ID]) {
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
if (!if_id) {
err = -EINVAL;
goto out_noput;
}
}

if (p->info.seq) {
x = xfrm_find_acq_byseq(net, mark, p->info.seq);
Expand Down Expand Up @@ -1727,8 +1737,13 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us

xfrm_mark_get(attrs, &xp->mark);

if (attrs[XFRMA_IF_ID])
if (attrs[XFRMA_IF_ID]) {
xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
if (!xp->if_id) {
err = -EINVAL;
goto error;
}
}

return xp;
error:
Expand Down Expand Up @@ -3058,7 +3073,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
if (x->props.extra_flags)
l += nla_total_size(sizeof(x->props.extra_flags));
if (x->xso.dev)
l += nla_total_size(sizeof(x->xso));
l += nla_total_size(sizeof(struct xfrm_user_offload));
if (x->props.smark.v | x->props.smark.m) {
l += nla_total_size(sizeof(x->props.smark.v));
l += nla_total_size(sizeof(x->props.smark.m));
Expand Down

0 comments on commit c4251db

Please sign in to comment.