[PATCH] IB: Fix race in sa_query

Use a copy of the id we'll return to the consumer so that we don't
dereference query->sa_query after calling send_mad(). A completion may
occur very quickly and end up freeing the query before we get to do
anything after send_mad().

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Roland Dreier and committed by
Linus Torvalds
dae4c1d2 cae54bdf

+13 -5
+13 -5
drivers/infiniband/core/sa_query.c
··· 507 spin_unlock_irqrestore(&idr_lock, flags); 508 } 509 510 - return ret; 511 } 512 513 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, ··· 604 rec, query->sa_query.mad->data); 605 606 *sa_query = &query->sa_query; 607 ret = send_mad(&query->sa_query, timeout_ms); 608 - if (ret) { 609 *sa_query = NULL; 610 kfree(query->sa_query.mad); 611 kfree(query); 612 } 613 614 - return ret ? ret : query->sa_query.id; 615 } 616 EXPORT_SYMBOL(ib_sa_path_rec_get); 617 ··· 681 rec, query->sa_query.mad->data); 682 683 *sa_query = &query->sa_query; 684 ret = send_mad(&query->sa_query, timeout_ms); 685 - if (ret) { 686 *sa_query = NULL; 687 kfree(query->sa_query.mad); 688 kfree(query); 689 } 690 691 - return ret ? ret : query->sa_query.id; 692 } 693 EXPORT_SYMBOL(ib_sa_mcmember_rec_query); 694
··· 507 spin_unlock_irqrestore(&idr_lock, flags); 508 } 509 510 + /* 511 + * It's not safe to dereference query any more, because the 512 + * send may already have completed and freed the query in 513 + * another context. So use wr.wr_id, which has a copy of the 514 + * query's id. 515 + */ 516 + return ret ? ret : wr.wr_id; 517 } 518 519 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, ··· 598 rec, query->sa_query.mad->data); 599 600 *sa_query = &query->sa_query; 601 + 602 ret = send_mad(&query->sa_query, timeout_ms); 603 + if (ret < 0) { 604 *sa_query = NULL; 605 kfree(query->sa_query.mad); 606 kfree(query); 607 } 608 609 + return ret; 610 } 611 EXPORT_SYMBOL(ib_sa_path_rec_get); 612 ··· 674 rec, query->sa_query.mad->data); 675 676 *sa_query = &query->sa_query; 677 + 678 ret = send_mad(&query->sa_query, timeout_ms); 679 + if (ret < 0) { 680 *sa_query = NULL; 681 kfree(query->sa_query.mad); 682 kfree(query); 683 } 684 685 + return ret; 686 } 687 EXPORT_SYMBOL(ib_sa_mcmember_rec_query); 688