Skip to content

Commit c4251db

Browse files
committed
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/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 <[email protected]>
2 parents 502a2ce + 45a98ef commit c4251db

File tree

6 files changed

+82
-13
lines changed

6 files changed

+82
-13
lines changed

include/net/xfrm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
11621162
{
11631163
struct net *net = dev_net(skb->dev);
11641164

1165-
if (xfrm_default_allow(net, XFRM_POLICY_FWD))
1165+
if (xfrm_default_allow(net, XFRM_POLICY_OUT))
11661166
return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
11671167
(skb_dst(skb)->flags & DST_NOXFRM) ||
11681168
__xfrm_route_forward(skb, family);

net/ipv6/ip6_gre.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
755755
fl6->daddr = key->u.ipv6.dst;
756756
fl6->flowlabel = key->label;
757757
fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
758+
fl6->fl6_gre_key = tunnel_id_to_key32(key->tun_id);
758759

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

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

11021105
if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
11031106
fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
@@ -1544,7 +1547,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
15441547
static struct inet6_protocol ip6gre_protocol __read_mostly = {
15451548
.handler = gre_rcv,
15461549
.err_handler = ip6gre_err,
1547-
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1550+
.flags = INET6_PROTO_FINAL,
15481551
};
15491552

15501553
static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)

net/xfrm/xfrm_interface.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,11 +637,16 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
637637
struct netlink_ext_ack *extack)
638638
{
639639
struct net *net = dev_net(dev);
640-
struct xfrm_if_parms p;
640+
struct xfrm_if_parms p = {};
641641
struct xfrm_if *xi;
642642
int err;
643643

644644
xfrmi_netlink_parms(data, &p);
645+
if (!p.if_id) {
646+
NL_SET_ERR_MSG(extack, "if_id must be non zero");
647+
return -EINVAL;
648+
}
649+
645650
xi = xfrmi_locate(net, &p);
646651
if (xi)
647652
return -EEXIST;
@@ -666,7 +671,12 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
666671
{
667672
struct xfrm_if *xi = netdev_priv(dev);
668673
struct net *net = xi->net;
669-
struct xfrm_if_parms p;
674+
struct xfrm_if_parms p = {};
675+
676+
if (!p.if_id) {
677+
NL_SET_ERR_MSG(extack, "if_id must be non zero");
678+
return -EINVAL;
679+
}
670680

671681
xfrmi_netlink_parms(data, &p);
672682
xi = xfrmi_locate(net, &p);

net/xfrm/xfrm_output.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -647,17 +647,38 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb
647647
* This requires hardware to know the inner packet type to calculate
648648
* the inner header checksum. Save inner ip protocol here to avoid
649649
* traversing the packet in the vendor's xmit code.
650-
* If the encap type is IPIP, just save skb->inner_ipproto. Otherwise,
651-
* get the ip protocol from the IP header.
650+
* For IPsec tunnel mode save the ip protocol from the IP header of the
651+
* plain text packet. Otherwise If the encap type is IPIP, just save
652+
* skb->inner_ipproto in any other case get the ip protocol from the IP
653+
* header.
652654
*/
653-
static void xfrm_get_inner_ipproto(struct sk_buff *skb)
655+
static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x)
654656
{
655657
struct xfrm_offload *xo = xfrm_offload(skb);
656658
const struct ethhdr *eth;
657659

658660
if (!xo)
659661
return;
660662

663+
if (x->outer_mode.encap == XFRM_MODE_TUNNEL) {
664+
switch (x->outer_mode.family) {
665+
case AF_INET:
666+
xo->inner_ipproto = ip_hdr(skb)->protocol;
667+
break;
668+
case AF_INET6:
669+
xo->inner_ipproto = ipv6_hdr(skb)->nexthdr;
670+
break;
671+
default:
672+
break;
673+
}
674+
675+
return;
676+
}
677+
678+
/* non-Tunnel Mode */
679+
if (!skb->encapsulation)
680+
return;
681+
661682
if (skb->inner_protocol_type == ENCAP_TYPE_IPPROTO) {
662683
xo->inner_ipproto = skb->inner_ipproto;
663684
return;
@@ -712,8 +733,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
712733
sp->xvec[sp->len++] = x;
713734
xfrm_state_hold(x);
714735

715-
if (skb->encapsulation)
716-
xfrm_get_inner_ipproto(skb);
736+
xfrm_get_inner_ipproto(skb, x);
717737
skb->encapsulation = 1;
718738

719739
if (skb_is_gso(skb)) {

net/xfrm/xfrm_policy.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <net/flow.h>
3434
#include <net/xfrm.h>
3535
#include <net/ip.h>
36+
#include <net/gre.h>
3637
#if IS_ENABLED(CONFIG_IPV6_MIP6)
3738
#include <net/mip6.h>
3839
#endif
@@ -3422,6 +3423,26 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse)
34223423
}
34233424
fl6->flowi6_proto = nexthdr;
34243425
return;
3426+
case IPPROTO_GRE:
3427+
if (!onlyproto &&
3428+
(nh + offset + 12 < skb->data ||
3429+
pskb_may_pull(skb, nh + offset + 12 - skb->data))) {
3430+
struct gre_base_hdr *gre_hdr;
3431+
__be32 *gre_key;
3432+
3433+
nh = skb_network_header(skb);
3434+
gre_hdr = (struct gre_base_hdr *)(nh + offset);
3435+
gre_key = (__be32 *)(gre_hdr + 1);
3436+
3437+
if (gre_hdr->flags & GRE_KEY) {
3438+
if (gre_hdr->flags & GRE_CSUM)
3439+
gre_key++;
3440+
fl6->fl6_gre_key = *gre_key;
3441+
}
3442+
}
3443+
fl6->flowi6_proto = nexthdr;
3444+
return;
3445+
34253446
#if IS_ENABLED(CONFIG_IPV6_MIP6)
34263447
case IPPROTO_MH:
34273448
offset += ipv6_optlen(exthdr);

net/xfrm/xfrm_user.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,13 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
621621

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

624-
if (attrs[XFRMA_IF_ID])
624+
if (attrs[XFRMA_IF_ID]) {
625625
x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
626+
if (!x->if_id) {
627+
err = -EINVAL;
628+
goto error;
629+
}
630+
}
626631

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

14141419
mark = xfrm_mark_get(attrs, &m);
14151420

1416-
if (attrs[XFRMA_IF_ID])
1421+
if (attrs[XFRMA_IF_ID]) {
14171422
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
1423+
if (!if_id) {
1424+
err = -EINVAL;
1425+
goto out_noput;
1426+
}
1427+
}
14181428

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

17281738
xfrm_mark_get(attrs, &xp->mark);
17291739

1730-
if (attrs[XFRMA_IF_ID])
1740+
if (attrs[XFRMA_IF_ID]) {
17311741
xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
1742+
if (!xp->if_id) {
1743+
err = -EINVAL;
1744+
goto error;
1745+
}
1746+
}
17321747

17331748
return xp;
17341749
error:
@@ -3058,7 +3073,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
30583073
if (x->props.extra_flags)
30593074
l += nla_total_size(sizeof(x->props.extra_flags));
30603075
if (x->xso.dev)
3061-
l += nla_total_size(sizeof(x->xso));
3076+
l += nla_total_size(sizeof(struct xfrm_user_offload));
30623077
if (x->props.smark.v | x->props.smark.m) {
30633078
l += nla_total_size(sizeof(x->props.smark.v));
30643079
l += nla_total_size(sizeof(x->props.smark.m));

0 commit comments

Comments
 (0)