-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gnrc_ipv6: don't recurse into receive for encapsulated IPv6 #10246
gnrc_ipv6: don't recurse into receive for encapsulated IPv6 #10246
Conversation
@kaspar030 @bergzand this is a really low hanging fruit. |
And here I was thinking that I Acked all the low hanging fruit in this project already :) Give me a minute to wrap up something else, I'll give it some attention next |
pkt); | ||
/* something went horribly wrong if that's not the case because we | ||
* are currently in a thread that is subscribing to the parameters above */ | ||
assert(res > 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ask the one million dollar question, is there any way that this assert could cause a ping-of-death-like scenario? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Say, something like a message box that is full.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iff everything is in order no. If for some weird reason (e.g. a stack overflow), the registry entry for the gnrc_ipv6
thread isn't found in the dispatch above, it will. But than we are in a critical state already, so it is safer to abort the program ;-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to be on the very safe side, I can revert 66ea05b.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Say, something like a message box that is full.
Nope, that has no effect on gnrc_netapi_dispatch_receive()
. Only the number of (potentially able to receive) subscribers is returned. The case if they are able to receive is handled separately:
RIOT/sys/net/gnrc/netapi/gnrc_netapi.c
Lines 132 to 139 in 64afc74
if (release) { | |
gnrc_pktbuf_release(pkt); | |
} | |
#else | |
if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { | |
/* unable to dispatch packet */ | |
gnrc_pktbuf_release(pkt); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was already diving into that code. I agree that the assert should only trigger if the whole network stack is already broken. Never mind this then, thanks for clarifying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to revert 66ea05b after all. In case we want to make the stack more dynamic in the future (e.g. switch out modules) this might lead to problems.
I can cause a native instance to cease network operations with a bit of scapy and a relative large number of IPv6 in IPv6 in IPv6... headers. You get the idea. Attached it a pcap as demonstration. At frame 34, I transmit a frame with 8 IPv6 headers. After this arrived at the node, it stops responding to the periodic stream of ping requests. zipped tcpdump capture: pod.zip Scapy: lladdr = "fe80::9435:fdff:fe5a:e9cc" # probably different :)
ip6p = IPv6(dst=lladdr)
sendp(Ether() / ip6p / ip6p / ip6p / ip6p / ip6p / ip6p / ip6p / ICMPv6EchoRequest(), iface="tapbr0") # node keeps working.
sendp(Ether() / ip6p / ip6p / ip6p / ip6p / ip6p / ip6p / ip6p / ip6p / ICMPv6EchoRequest(), iface="tapbr0") # node stops working. |
Is this only happening with this PR or also in master? |
(I'll have a look regardless, but I think this is already the case (or due to the recursion even worse) in master. |
I can reproduce the same thing in master |
For some reason |
Ok, I now found out what happens. The encapsulated IPv6 header actually gets to be handled twice. Once (actually its the second handling) in the method I rework in this PR, and once here since Now how to proceed? Crashing a node by sending a ping of death is obviously a serious flaw that should be fixed ASAP. But requiring #10233 to be merged into the release is unrealistic. So I would propose as a "fix" to remove the whole |
Ah I think I found an alterntative "bugfix". That would fix both cases! |
It's an ugly one, but for now this should be enough. |
(the uglyness can be later reverted in #10233) |
@bergzand for testing: use your scapy commands, but also set the tap bridge's link-local address as source (this way you will the that without the latest fix you will get n (= number of IPv6 headers) replies; with the fix you only get one). |
@miri64 you mean, it fixes the PoD and we would still have IPv6 encapsulation? I think such a bugfix (regardless on what happen to IPv6 encapsulation) is worth to be included in the Release. It's a serious bug IMO. So, I'm +1 in backporting this. |
Yes. There ist still some issue, if extension headers appear between the encapsulated headers, but a) they don't cause a ping of death (they are just dropped) and b) this is also a problem in the current master. With the simplifications in #10233 this is fixed, but that change is too complicated to be used as a simple release fix. |
Tested, issues seem to be resolved. Ack! please squash! |
`_decapsulate()` is called by callees of `_receive()` so the call to the latter function within the first creates a recursion we don't want. Using `gnrc_netapi` instead removes that and provides the added benefit that other subscribers to IPv6 are also informed.
Otherwise, an encapsulated IPv6 packet is handled twice. Once in the central function, once in the specialized decapsulation.
Squashed. |
0d450d6
to
d54ac38
Compare
Murdock error is that unrelated false positive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All green!
Do we want to wait for Codacy before merging? |
Last time I checked it was green and it shouldn't change. But I leave it to you to hit the merge button ;-) |
Merged! |
Thanks! :-) |
Backport provided in #10348 |
Contribution description
_decapsulate()
is called by callees of_receive()
so the call tothe latter function within the first creates a recursion we don't want.
Using
gnrc_netapi
instead removes that and provides the added benefitthat other subscribers to IPv6 are also informed.
Testing procedure
Send an encapsulated IPv6 packet to a node. It should still be parsed properly.
Issues/PRs references
None, but related to the IPv6 refactoring project