-
Notifications
You must be signed in to change notification settings - Fork 376
Fix data corruption in delayed mini-conn packets #594
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
base: master
Are you sure you want to change the base?
Fix data corruption in delayed mini-conn packets #594
Conversation
dtikhonov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the bug report and the patch, @sabitov-kirill! It is surprising that this bug has lingered for so long.
Because memory allocation can fail, this logic should be changed:
Try allocating and copying. If that fails, throw the packet out. If successful, proceed as before.
| { | ||
| ++conn->imc_delayed_packets_count; | ||
| lsquic_packet_in_upref(packet_in); | ||
| lsquic_conn_copy_and_release_pi_data(&conn->imc_conn, conn->imc_enpub, packet_in); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function call can fail, need to check return value and take appropriate action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, my bad. Fixed in e41fc86. However, am I correct that we do not need to bother about free as long as PI_OWN_DATA is raised and reference count is set correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, freeing happens when the reference count goes to zero. In lsquic_engine.c, the reference count is decremented after the "packet in" call:
conn->cn_if->ci_packet_in(conn, packet_in);
#if LSQUIC_CONN_STATS
engine->busy.pin_conn = conn;
#endif
QLOG_PACKET_RX(lsquic_conn_log_cid(conn), packet_in, packet_in_data, packet_in_size);
lsquic_packet_in_put(&engine->pub.enp_mm, packet_in); // <---------- this decrements refcnt If the count goes to zero, this is called:
void
lsquic_mm_put_packet_in (struct lsquic_mm *mm,
struct lsquic_packet_in *packet_in)
{
assert(0 == packet_in->pi_refcnt);
if (packet_in->pi_flags & PI_OWN_DATA)
{
lsquic_mm_put_packet_in_buf(mm, packet_in->pi_data, packet_in->pi_data_sz);
}
#if LSQUIC_USE_POOLS
TAILQ_INSERT_HEAD(&mm->free_packets_in, packet_in, pi_next);
#else
lsquic_malo_put(packet_in);
#endif
} |
I just looked at the original mini-conn code ("original" as in "Google QUIC") and it does the right thing! else if ((packet_in->pi_flags & PI_OWN_DATA) ||
0 == lsquic_conn_copy_and_release_pi_data(&mc->mc_conn,
mc->mc_enpub, packet_in))
{
assert(packet_in->pi_flags & PI_OWN_DATA);
LSQ_INFO("could not decrypt packet: defer");
mc->mc_deferred_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno);
MCHIST_APPEND(mc, MCHE_UNDECR_DEFER);
return PRP_DEFER;
} Furthermore, it appears that @sabitov-kirill, I am going to ask you to do one more modification to your PR: Check whether |
c2c23ff to
6ccda12
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a critical data corruption bug in the IETF mini-connection implementation where delayed packets retained pointers to volatile caller-provided memory buffers. The fix ensures packet data is copied to persistent storage before queuing, preventing corruption when the original buffer is reused or freed.
Key Changes:
- Modified
imico_maybe_delay_processingto copy packet data before delaying packets, matching the pattern used in the GQUIC mini-connection implementation - Added a new unit test to verify the fix by simulating decryption delays and validating data integrity
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/liblsquic/lsquic_mini_conn_ietf.c | Added data copying logic to prevent corruption when delaying packets that lack the PI_OWN_DATA flag |
| tests/test_mini_conn_delay.c | New test that reproduces the bug by mocking decryption delays and verifying packet data integrity after buffer modification |
| tests/CMakeLists.txt | Added mini_conn_delay to the list of tests to build |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| // Check delayed packet data is not corrupted | ||
| assert(delayed->pi_data[0] == 0x42 && "Delayed data is corrupted!"); | ||
|
|
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory leak: The test creates a mini connection but never destroys it. The conn object and its associated resources (including the delayed packet with copied data) are not cleaned up before the test exits. Consider calling conn->cn_if->ci_destroy(conn) before lsquic_mm_cleanup.
| conn->cn_if->ci_destroy(conn); |
| @@ -0,0 +1,110 @@ | |||
| /* Test for mini connection delayed packet data corruption bug */ | |||
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing copyright header. Other test files in this repository include a copyright notice at the top (e.g., /* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */). Consider adding the appropriate copyright header to maintain consistency with the codebase.
This PR fixes a bug (see #593) where packets delayed by a mini-connection (due to missing keys) retained pointers to volatile memory provided by the caller of
lsquic_engine_packet_in. This resulted in data corruption when the caller reused or freed the buffer before the packet was processed by the full connection.Fix
imico_maybe_delay_processingnow callslsquic_conn_copy_and_release_pi_data. This allocates a persistent buffer for the packet data and sets thePI_OWN_DATAflag, ensuring the data remains valid until the packet is processed or destroyed.Testing
tests/test_mini_conn_delay.cthat reproduces the corruption by mocking the decryption delay and verifying the data integrity.lsquic_packet_in_putcorrectly frees the allocated memory when the packet is eventually processed inlsquic_ietf_full_conn_server_new.