Harden RLP limits on allocations#9465
Conversation
| @@ -0,0 +1,2 @@ | |||
| <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | |||
There was a problem hiding this comment.
Dictionary for custom english words
For Rider spellchecker
There was a problem hiding this comment.
Pull Request Overview
This PR implements RLP (Recursive Length Prefix) allocation limits to harden against malicious peers sending oversized data structures. The changes introduce a new RlpLimit struct that provides type-safe allocation limits with descriptive error messages, replacing the previous unchecked RLP decoding that could allocate arbitrary amounts of memory.
Key changes:
- Added
RlpLimitandRlpLimitExceptionclasses for limit enforcement - Enhanced all RLP decode methods to accept optional limit parameters
- Applied specific limits throughout networking and serialization layers
- Improved error handling for RLP limit violations with automatic disconnection
Reviewed Changes
Copilot reviewed 120 out of 120 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs |
New limit struct with type-safe limit definitions and error message generation |
src/Nethermind/Nethermind.Serialization.Rlp/RlpLimitException.cs |
New exception type for limit violations |
src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs |
Enhanced decode methods with limit parameters and guard checks |
src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs |
Added RLP limit exception handling with automatic session disconnection |
src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs |
Enhanced exception handling for different RLP exception types |
src/Nethermind/Nethermind.Network.Stats/SyncLimits/NethermindSyncLimits.cs
Outdated
Show resolved
Hide resolved
src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…yncLimits.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…lHandlerBase.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
emlautarom1
left a comment
There was a problem hiding this comment.
Not sure if this approach covers use cases like recursive data structures (ex. Tree = Leaf | Node(i64, Tree) where the encoding could look like [1, [2, [...]]]), though this might not be actually needed.
Also, why do we check the limits at the element level rather than at the beggining of decoding? We could set a limit for the maximum amount of bytes to decode (AFAIK we don't do async RLP decoding so we know ahead of time the number of bytes we're working with).
I would add tests that trigger this kind of limits to check that it's behaving as expected.
Lastly, there are a couple of files with unused imports that could be cleaned up.
This is a patch for current solution and I want to keep it as small as possible. I would love to move to comprehensive redesign like yours in #7975. There are some tests already (for receipts for example). Recursives would be handled well and are not a problem here. We could decode element by element and potentially grow the buffers, but it would be slower. |
Good, that was my major concern.
I see, I've probably missed it ( |
I could add tests for all/most of the limits... but not sure if worth it. They are very actively tested in real world scenarios in hive tests for example. |
Marchhill
left a comment
There was a problem hiding this comment.
Looks good, just a bit worried some of these limits won't be high enough
src/Nethermind/Nethermind.Consensus.AuRa/Validators/ValidatorInfoDecoder.cs
Show resolved
Hide resolved
* Harden RLP limits on allocations * fix * fix build * fix * fix * FIx tests, refactors, adjust limits * Move RlpLimit to own file * fix * fix pyspec tests * Improve exception message * Update src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.Network.Stats/SyncLimits/NethermindSyncLimits.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Increase Transaction.Data limit to 30MB to handle 300MGas of calldata * Remove unused * fix Benchmark solution --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Changes
Types of changes
What types of changes does your code introduce?
Testing
Requires testing
If yes, did you write tests?
Documentation
Requires documentation update
Requires explanation in Release Notes
Remarks
Before if someone said he sent us XXX amount in some collection we could try to allocate that big array in RLP decoding. Now we have more sensible limits.
Where I couldn't easily pass a limit we are now defaulting to max 256K size - maybe still needs a bit more hardening? Should be enough, the longest field I can think of is
Transaction.Dataand there are Pyspec tests that require 400KB limit there:Collection count of 404000 is over limit 262144, so I went with 1M limit for it.