-
Notifications
You must be signed in to change notification settings - Fork 433
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
Ethernet denial of service #281
Comments
You can't really do this as the TCP state machine currently assumes ingress first.
The imbalance is an attempt at fairness between several sockets. Admittedly not a very good one, but sending all available packets from the first socket in the set generally has worse results. |
Imbalance between several sockets still sounds better than imbalance between incoming, malicious traffic and outgoing packets. But I think this has the same root case: The interface offers of Here's another idea: Send single packets from all socket in round-robin fashion until none has any more packets to emit or some number of packets have been sent in total (fixed, configurable, ..). Thus, This is however not quite sufficient alone, as really there must be a way not to error out with |
What about changing the |
To me this looks like this is 2 problems that could be tackled separately:
My proposal to solve 2 is to:
For 1, I'm not sure what'd be the solution.
@whitequark could you expand on this? To me it seems that handling egress first then ingress would just look to the TCP socket like the ingressed packet arrived "a little bit later", ie it could've happened anyway. I can't see how it can break things. If the socket wants to send something, it'll return PollAt::Now and get polled again. |
Malformed/unexpected packets are logged and ignored. See #281 on rationale for why this is better.
Malformed/unexpected packets are logged and ignored. See smoltcp-rs#281 on rationale for why this is better.
Bug report
A malicious sender over an ethernet interface can cause a denial of service by making every call to
poll
return an error beforeprocess_egress
could have been called. This will cause the interface to never send any packets that are pending on any socket.The same happens inwittingly when the ingress call can constantly keep the buffer of a socket filled, for example by saturating line rate of a fast enough nic with a packet generator.
Reproduction steps
phy::Device
that has an infinite stream of packets and somehow signals when a packet would have been sent (for example by panicking).loop
infinitely withiface.poll(&mut socketset)
3.1 Each loop, you can dequeue packets received, or not, doesn't matter
Instead of having an infinite stream of packets read each time poll is called, you can alternatively implement the
phy
such that exactly one malformed packet is ready each time. This has the same effect on the poll-loop.I have code ready for this, should I link it or not?
Fixes
There are several possible ways to fix this:
ingress
andegress
, for example by removing the?
from the their initial call point and insteadEthernetInterface
that determines whether to ingress or egress first. Flip it everytimepoll
is invoked.Both of the above are still unsatisfying, as each
poll
call will at most egress a single packet before evaluating theErr
from the nextsocket_ingress
call and returning. Note thatprocess_ingress
will loop while there areRxToken
returned from thephy
whileproces_egress
will try to send a single packet from each socket within the set. This imbalance is quite confusing.Workarounds
Nothing quick and fast here, you'd need to poll without receiving packets so that it can not error. That possible leaves a wrapping
phy
implementation that allows you to turn offreceive
. Something like this. Then you can disablerx
for thephy
, callpoll
once without transmit being potentially interrupted by receive, and reenablerx
.The text was updated successfully, but these errors were encountered: