Add checks to require shrink-only decap, reject conflicting decap flag combinations, and verify removed length is sufficient for claimed header decapsulation. Co-developed-by: Max Tottenham Signed-off-by: Max Tottenham Co-developed-by: Anna Glasgall Signed-off-by: Anna Glasgall Signed-off-by: Nick Hudson --- net/core/filter.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index 4e860da4381d..7f8d43420afb 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -3490,6 +3491,12 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb) #define BPF_F_ADJ_ROOM_DECAP_L3_MASK (BPF_F_ADJ_ROOM_DECAP_L3_IPV4 | \ BPF_F_ADJ_ROOM_DECAP_L3_IPV6) +#define BPF_F_ADJ_ROOM_DECAP_L4_MASK (BPF_F_ADJ_ROOM_DECAP_L4_UDP | \ + BPF_F_ADJ_ROOM_DECAP_L4_GRE) + +#define BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK (BPF_F_ADJ_ROOM_DECAP_IPXIP4 | \ + BPF_F_ADJ_ROOM_DECAP_IPXIP6) + #define BPF_F_ADJ_ROOM_ENCAP_MASK (BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \ BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \ BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \ @@ -3497,7 +3504,9 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb) BPF_F_ADJ_ROOM_ENCAP_L2( \ BPF_ADJ_ROOM_ENCAP_L2_MASK)) -#define BPF_F_ADJ_ROOM_DECAP_MASK (BPF_F_ADJ_ROOM_DECAP_L3_MASK) +#define BPF_F_ADJ_ROOM_DECAP_MASK (BPF_F_ADJ_ROOM_DECAP_L3_MASK | \ + BPF_F_ADJ_ROOM_DECAP_L4_MASK | \ + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) #define BPF_F_ADJ_ROOM_MASK (BPF_F_ADJ_ROOM_FIXED_GSO | \ BPF_F_ADJ_ROOM_ENCAP_MASK | \ @@ -3740,6 +3749,8 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff, } if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) { + u32 len_decap_min = 0; + if (!shrink) return -EINVAL; @@ -3748,6 +3759,37 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff, BPF_F_ADJ_ROOM_DECAP_L3_MASK) return -EINVAL; + if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) == + BPF_F_ADJ_ROOM_DECAP_L4_MASK) + return -EINVAL; + + if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) == + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) + return -EINVAL; + + /* Reject mutually exclusive decap tunnel type flags. */ + if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) && + (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) + return -EINVAL; + + if (flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) + len_decap_min += bpf_skb_net_base_len(skb); + + if (flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) + len_decap_min += sizeof(struct udphdr); + + if (flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE) + len_decap_min += sizeof(struct gre_base_hdr); + + if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4) + len_decap_min += sizeof(struct iphdr); + + if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6) + len_decap_min += sizeof(struct ipv6hdr); + + if (len_diff_abs < len_decap_min) + return -EINVAL; + if (flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4) len_min = sizeof(struct iphdr); -- 2.34.1