Skip to content
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

Fixes #1698: prevent use-after-free of qd_link_t on session close #1699

Merged
merged 3 commits into from
Dec 16, 2024

Conversation

kgiusti
Copy link
Contributor

@kgiusti kgiusti commented Dec 13, 2024

Previously the detach handler might free the qd_link_t but it was not consistent. This patch moves the qd_link_t cleanup to the container.

@kgiusti kgiusti marked this pull request as draft December 13, 2024 19:50
@kgiusti kgiusti marked this pull request as ready for review December 13, 2024 20:29
@@ -645,6 +627,7 @@ void qd_container_handle_event(qd_container_t *container, pn_event_t *event,
pn_link = pn_event_link(event);
if (pn_link_state(pn_link) == (PN_LOCAL_CLOSED | PN_REMOTE_CLOSED)) {
add_link_to_free_list(&qd_conn->free_link_list, pn_link);
qd_link_free((qd_link_t *) pn_link_get_context(pn_link));
Copy link
Contributor

@ganeshmurthy ganeshmurthy Dec 16, 2024

Choose a reason for hiding this comment

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

Instead of calling qd_link_free() once in the handler to PN_LINK_REMOTE_CLOSE and once in PN_LINK_LOCAL_CLOSE, can we call it just once in the qd_conn_event_batch_complete() function where we loop thru the qd_conn->free_link_list ?

In fact, I was wondering if we could have the qd_conn_event_batch_complete() function as the only place we call qd_link_free() and pn_link_free()

Copy link
Contributor

@ganeshmurthy ganeshmurthy Dec 16, 2024

Choose a reason for hiding this comment

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

In fact, I was wondering if we could have the qd_conn_event_batch_complete() function as the only place we call qd_link_free() and pn_link_free()

I realized that the qd_conn_event_batch_complete() function is called only on connection close, so it cannot be the only place where the qd_link_free() and pn_link_free() functions are called. So, please disregard that comment. I assumed that qd_conn_event_batch_complete() is called after every event batch. My bad.

pn_session_close(ssn);
}
else if (pn_session_state(ssn) == (PN_LOCAL_CLOSED | PN_REMOTE_CLOSED)) {
qd_session_t *qd_ssn = qd_session_from_pn(ssn);
if (qd_ssn) {
if (qd_ssn->policy_counted) {
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 please move this policy_counted related code to a new commit so this commit only contains the code that fixes the router crash ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to add that hacky policy flag because otherwise this patch would break the policy code. The problem is that not all sessions or links are counted by policy: only those that are 1) remotely initiated and 2) policy is in use.

That means the code cannot unconditionally decrement the relevant policy counters since the counters may not have been incremented for that particular session/link (for reasons 1 and 2 above). So I have to add that ugly "hey I'm counted by policy so remember to decrement when I'm done" hack.

Unconditionally incrementing/decrementing the counters will break the policy logic: there's even asserts in the (existing) code to guard against underflow:

assert(qd_conn->n_receivers >= 0);

Copy link
Contributor

Choose a reason for hiding this comment

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

That means the code cannot unconditionally decrement the relevant policy counters since the counters may not have been incremented for that particular session/link

Makes sense to me.

…sion close

Previously the detach handler might free the qd_link_t but it was not
consistent. This patch moves the qd_link_t cleanup to the container.
@kgiusti kgiusti merged commit f2b8092 into skupperproject:main Dec 16, 2024
37 of 41 checks passed
@kgiusti kgiusti deleted the ISSUE-1698 branch December 16, 2024 19:55
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.

Teardown of an AMQP session with active links and deliveries causes a router crash
2 participants