Skip to content

channels_sv2: client rejected_shares map grows unboundedly #2262

Description

@plebhash

ShareAccounting::on_share_rejection is fed error_code values straight from upstream SubmitSharesError messages:

pub fn on_share_rejection(&mut self, error_code: String) {
self.rejected_shares
.entry(error_code)
.and_modify(|v| *v += 1)
.or_insert(1);
}

The wire type is Str0255, so a malicious or compromised pool controls up to 255 bytes of arbitrary content per message.

Every distinct value becomes a permanent key in rejected_shares: HashMap<String, u32> — no length cap, no eviction, no allowlist, and (unlike seen_shares) no flush on chain-tip updates.

Over a sustained connection this is a slow but real memory-exhaustion DoS against the mining client (CWE-400), mirroring the upstream-trust threat model already accepted for the same struct's counter-overflow fixes.

In-repo usage treats this set as a small fixed enumeration (the ERROR_CODE_SUBMIT_SHARES_* constants in mining_sv2), so bounding it matches intent.

fix

count only the known ERROR_CODE_SUBMIT_SHARES_* codes

fold anything else into an "unknown" bucket.

regression test

Feed 10,000 unique error codes into on_share_rejection, assert the stored map stays bounded.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions