Skip to content

common/wireaddr: Fix an out-of-bounds bug in the address parser #8325

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Chand-ra
Copy link

@Chand-ra Chand-ra commented Jun 6, 2025

In struct wireaddr, the addr buffer is defined with a length of DNS_ADDRLEN (255). When parsing a valid DNS name that is exactly 255 bytes long, the subsequent attempt to append a NULL terminator overruns the buffer and triggers an out-of-bounds error under UBSan.

Fix this bug and add a test to guard against it.

Checklist

Before submitting the PR, ensure the following tasks are completed. If an item is not applicable to your PR, please mark it as checked:

  • The changelog has been updated in the relevant commit(s) according to the guidelines.
  • Tests have been added or modified to reflect the changes.
  • Documentation has been reviewed and updated as needed.
  • Related issues have been listed and linked, including any that this PR closes.

CC: @morehouse

Changelog-Fixed: In `struct wireaddr`, the `addr` buffer is defined
with a length of DNS_ADDRLEN (255). When parsing a valid DNS name
that is exactly 255 bytes long, the subsequent attempt to append a
`NULL` terminator overruns the buffer and triggers an out-of-bounds
error under UBSan.

Fix this by removing the line that appends `NULL`. This change is
safe because the preceding call to:

`memset(&addr->addr, 0, sizeof(addr->addr))`

already zeroes the entire buffer.
@Chand-ra
Copy link
Author

Chand-ra commented Jun 6, 2025

This bug was discovered through the new fuzz test in #8324.

@morehouse
Copy link
Contributor

Note that this bug is triggerable from outside init or node_announcement messages, though AFAICT the worst that can happen is the port for that node gets corrupted. No crash should occur without UBSan instrumentation.

@@ -287,6 +224,31 @@ int main(int argc, char *argv[])
expect->u.unresolved.port = 1234;
assert(wireaddr_internal_eq(&addr, expect));

const char raw_input[] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a comment describing the test, and also the bug that was fixed.

Comment on lines 246 to 250
const u8 *crashing_input = tal_dup_arr(tmpctx, u8, (const u8*) raw_input, sizeof(raw_input) - 1, 0);
size_t crashing_input_len = tal_bytelen(crashing_input);

struct wireaddr_internal decoded_wa;
assert(fromwire_wireaddr_internal(&crashing_input, &crashing_input_len, &decoded_wa));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we improve the test to check the expected decoded values, as with the above tests?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, the readability could also use some improvements.

Add a test in `common/test/run-wireaddr.c` that reproduces the
out-of-bounds error when the fix is not applied.
Copy link
Contributor

@morehouse morehouse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK c8000f2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants