diff options
-rw-r--r-- | net/core/flow_dissector.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index e0ea17d1c7fc..0a977373d003 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -396,6 +396,18 @@ __skb_flow_dissect_ipv6(const struct sk_buff *skb, key_ip->ttl = iph->hop_limit; } +/* Maximum number of protocol headers that can be parsed in + * __skb_flow_dissect + */ +#define MAX_FLOW_DISSECT_HDRS 15 + +static bool skb_flow_dissect_allowed(int *num_hdrs) +{ + ++*num_hdrs; + + return (*num_hdrs <= MAX_FLOW_DISSECT_HDRS); +} + /** * __skb_flow_dissect - extract the flow_keys struct and return it * @skb: sk_buff to extract the flow from, can be NULL if the rest are specified @@ -427,6 +439,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_dissector_key_vlan *key_vlan; enum flow_dissect_ret fdret; bool skip_vlan = false; + int num_hdrs = 0; u8 ip_proto = 0; bool ret; @@ -714,7 +727,9 @@ proto_again: case FLOW_DISSECT_RET_OUT_GOOD: goto out_good; case FLOW_DISSECT_RET_PROTO_AGAIN: - goto proto_again; + if (skb_flow_dissect_allowed(&num_hdrs)) + goto proto_again; + goto out_good; case FLOW_DISSECT_RET_CONTINUE: case FLOW_DISSECT_RET_IPPROTO_AGAIN: break; @@ -843,9 +858,13 @@ ip_proto_again: /* Process result of IP proto processing */ switch (fdret) { case FLOW_DISSECT_RET_PROTO_AGAIN: - goto proto_again; + if (skb_flow_dissect_allowed(&num_hdrs)) + goto proto_again; + break; case FLOW_DISSECT_RET_IPPROTO_AGAIN: - goto ip_proto_again; + if (skb_flow_dissect_allowed(&num_hdrs)) + goto ip_proto_again; + break; case FLOW_DISSECT_RET_OUT_GOOD: case FLOW_DISSECT_RET_CONTINUE: break; |