Skip to content

Fix crashing induced by Zonemaster::LDNS::RR::NSEC3::salt() method#177

Merged
marc-vanderwal merged 2 commits into
zonemaster:developfrom
marc-vanderwal:bugfix/nsec3-salt-method
Nov 21, 2023
Merged

Fix crashing induced by Zonemaster::LDNS::RR::NSEC3::salt() method#177
marc-vanderwal merged 2 commits into
zonemaster:developfrom
marc-vanderwal:bugfix/nsec3-salt-method

Conversation

@marc-vanderwal

@marc-vanderwal marc-vanderwal commented Nov 20, 2023

Copy link
Copy Markdown
Contributor

Purpose

The salt() method in the Zonemaster::LDNS::RR::NSEC3 module never worked and often caused the Perl interpreter to crash. This PR fixes many long-standing issues with the affected code.

Firstly, the root cause of the crash is a double free resulting from the inappropriate use of ldns_rdf_deep_free() in the code. The ldns_nsec3_salt() function returns a pointer to a ldns_rdf structure which is just a window into the salt field, not a copy of the data. So calling ldns_rdf_deep_free() on that ldns_rdf object causes a part of the original resource record structure to be freed instead. This then results in a double free when the memory for the resource record object is deallocated. Removing the call to that function fixes the crashing.

Secondly, the method doesn’t quite return the salt: it actually returns a string containing the salt preceded by its length byte. This is surprising, not as documented and unlikely to be useful. This problem is fixed by rewriting the entire function so as to return the salt, all the salt and nothing but the salt.

Thirdly, the method was also insufficiently covered by unit tests. Tests were added, first to help reproduce the crashes, but also to cover the case of an NSEC3 with non-empty salt.

Finally, the method returns undef if the salt is empty. Not only is that documented nowhere, but the choice of doing so is questionable. This PR changes the behavior somewhat in this case: if the salt is empty, an empty string is returned instead; the method only returns undef if there was a problem accessing the salt field.

Context

Found by @tgreenx while updating the implementation of DNSSEC03 (see PR zonemaster/zonemaster-engine#1304).

Changes

  • Rewrite the salt() method in Zonemaster::LDNS::RR::NSEC3 completely
  • Add unit tests and update documentation

Note: because the function’s behavior is changed in the case of a resource record with an empty salt, this change should be considered breaking.

How to test this PR

Unit tests should pass.

The salt() method in the Zonemaster::LDNS::RR::NSEC3 module never worked
and often caused the Perl interpreter to crash. This commit fixes many
long-standing issues with the affected code.

Firstly, the root cause of the crash is a double free resulting from the
inappropriate use of ldns_rdf_deep_free() in the code. The
ldns_nsec3_salt() function returns a pointer to a ldns_rdf structure
which is just a window into the salt field, not a copy of the data. So
calling ldns_rdf_deep_free() on that ldns_rdf object causes a part of
the original resource record structure to be freed instead. This then
results in a double free when the memory for the resource record object
is deallocated. Calling ldns_rdf_free() instead fixes the crashing.

Secondly, the method doesn’t quite return the salt: it actually returns
a string containing the salt preceded by its length byte. This is
surprising, not as documented and unlikely to be useful. This problem is
fixed by rewriting the entire function so as to return the salt, all the
salt and nothing but the salt.

Thirdly, the method was also insufficiently covered by unit tests. Tests
were added, first to help reproduce the crashes, but also to cover the
case of an NSEC3 with non-empty salt.

Finally, the method returns undef if the salt is empty. Not only is that
documented nowhere, but the choice of doing so is questionable. This
commit changes the behavior somewhat in this case: if the salt is empty,
an empty string is returned instead; the method only returns undef if
there was a problem accessing the salt field.
@marc-vanderwal marc-vanderwal added T-Bug Type: Bug in software or error in test case description V-Major Versioning: The change gives an update of major in version. labels Nov 20, 2023
@marc-vanderwal marc-vanderwal marked this pull request as ready for review November 20, 2023 10:50
matsduf
matsduf previously approved these changes Nov 20, 2023

@matsduf matsduf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks fine. Are there calls in Engine that have to be updated to match this change?

Comment thread t/rr.t Outdated
@marc-vanderwal

Copy link
Copy Markdown
Contributor Author

This looks fine. Are there calls in Engine that have to be updated to match this change?

I did a git grep on Zonemaster::Engine (with the develop branch checked out) and this method isn’t used anywhere yet.

@marc-vanderwal marc-vanderwal merged commit d079e46 into zonemaster:develop Nov 21, 2023
@marc-vanderwal marc-vanderwal deleted the bugfix/nsec3-salt-method branch August 29, 2024 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-Bug Type: Bug in software or error in test case description V-Major Versioning: The change gives an update of major in version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants