|
@@ -223,6 +223,7 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
|
|
|
unsigned int nhoff;
|
|
|
int nexthdr;
|
|
|
bool raw;
|
|
|
+ bool have_final = false;
|
|
|
|
|
|
/*
|
|
|
* Parse extension headers
|
|
@@ -242,9 +243,21 @@ resubmit_final:
|
|
|
if (ipprot) {
|
|
|
int ret;
|
|
|
|
|
|
- if (ipprot->flags & INET6_PROTO_FINAL) {
|
|
|
+ if (have_final) {
|
|
|
+ if (!(ipprot->flags & INET6_PROTO_FINAL)) {
|
|
|
+ /* Once we've seen a final protocol don't
|
|
|
+ * allow encapsulation on any non-final
|
|
|
+ * ones. This allows foo in UDP encapsulation
|
|
|
+ * to work.
|
|
|
+ */
|
|
|
+ goto discard;
|
|
|
+ }
|
|
|
+ } else if (ipprot->flags & INET6_PROTO_FINAL) {
|
|
|
const struct ipv6hdr *hdr;
|
|
|
|
|
|
+ /* Only do this once for first final protocol */
|
|
|
+ have_final = true;
|
|
|
+
|
|
|
/* Free reference early: we don't need it any more,
|
|
|
and it may hold ip_conntrack module loaded
|
|
|
indefinitely. */
|