Details
-
Bug
-
Resolution: Fixed
-
Critical
-
None
-
None
-
3
-
9223372036854775807
Description
There is a use after free in the LNet response tracking code.
If an MD is unlinked with a non-zero refcount the lnet_libhandle is invalidated so that future lookups of the MD are failed.
/* must be called with lnet_res_lock held */
void
lnet_md_unlink(struct lnet_libmd *md)
{
if ((md->md_flags & LNET_MD_FLAG_ZOMBIE) == 0) {
/* first unlink attempt... */
struct lnet_me *me = md->md_me;
md->md_flags |= LNET_MD_FLAG_ZOMBIE;
/* Disassociate from ME (if any), and unlink it if it was created
* with LNET_UNLINK */
if (me != NULL) {
/* detach MD from portal */
lnet_ptl_detach_md(me, md);
if (me->me_unlink == LNET_UNLINK)
lnet_me_unlink(me);
}
/* ensure all future handle lookups fail */
lnet_res_lh_invalidate(&md->md_lh);
}
if (md->md_refcount != 0) {
CDEBUG(D_NET, "Queueing unlink of md %p\n", md);
return;
}
If a response tracker is attached to such an MD then it is possible for the lnet_finalize_expired_responses loop to free the rspt before it has been detached from the MD.
static void
lnet_finalize_expired_responses(bool force)
{
<snip>
if (ktime_compare(ktime_get(), rspt->rspt_deadline) >= 0 ||
force) {
struct lnet_peer_ni *lpni;
lnet_nid_t nid;
md = lnet_handle2md(&rspt->rspt_mdh);
if (!md) {
LNetInvalidateMDHandle(&rspt->rspt_mdh);
lnet_res_unlock(i);
list_del_init(&rspt->rspt_on_list);
lnet_rspt_free(rspt, i);
continue;
}
When the final operation on the MD completes the MD is detached from the lnet_msg, the response tracker is detached from the MD, and the assert can be tripped:
lnet_finalize()->lnet_msg_detach_md()->lnet_detach_rsp_tracker()
void
lnet_detach_rsp_tracker(struct lnet_libmd *md, int cpt)
{
struct lnet_rsp_tracker *rspt;
/*
* msg has a refcount on the MD so the MD is not going away.
* The rspt queue for the cpt is protected by
* the lnet_net_lock(cpt). cpt is the cpt of the MD cookie.
*/
if (!md->md_rspt_ptr)
return;
rspt = md->md_rspt_ptr;
md->md_rspt_ptr = NULL;
/* debug code */
LASSERT(rspt->rspt_cpt == cpt);
Attachments
Issue Links
- is related to
-
LU-12906 LBUG ASSERTION( rspt->rspt_cpt == cpt ) failed
-
- Resolved
-
-
LU-12907 LNet routers: LNetError: 14141:0:(lib-msg.c:894:lnet_finalize()) ASSERTION( !(((current_thread_info()->preempt_count) & ((((1UL << (10))-1) << ((0 + 8) + 8)) | (((1UL << (8))-1) << (0 + 8)) | (((1UL << (1))-1) << (((0 + 8) + 8) + 10)))))
-
- Resolved
-
- is related to
-
LU-12441 Response tracker is not detached on router ping reply
-
- Resolved
-