Skip to content

Commit 4390008

Browse files
Erez Shitritjgunthorpe
authored andcommitted
IB/ipoib: Avoid memory leak if the SA returns a different DGID
The ipoib path database is organized around DGIDs from the LLADDR, but the SA is free to return a different GID when asked for path. This causes a bug because the SA's modified DGID is copied into the database key, even though it is no longer the correct lookup key, causing a memory leak and other malfunctions. Ensure the database key does not change after the SA query completes. Demonstration of the bug is as follows ipoib wants to send to GID fe80:0000:0000:0000:0002:c903:00ef:5ee2, it creates new record in the DB with that gid as a key, and issues a new request to the SM. Now, the SM from some reason returns path-record with other SGID (for example, 2001:0000:0000:0000:0002:c903:00ef:5ee2 that contains the local subnet prefix) now ipoib will overwrite the current entry with the new one, and if new request to the original GID arrives ipoib will not find it in the DB (was overwritten) and will create new record that in its turn will also be overwritten by the response from the SM, and so on till the driver eats all the device memory. Signed-off-by: Erez Shitrit <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent d7c0557 commit 4390008

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

drivers/infiniband/ulp/ipoib/ipoib_main.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,22 @@ static void path_rec_completion(int status,
775775
spin_lock_irqsave(&priv->lock, flags);
776776

777777
if (!IS_ERR_OR_NULL(ah)) {
778+
/*
779+
* pathrec.dgid is used as the database key from the LLADDR,
780+
* it must remain unchanged even if the SA returns a different
781+
* GID to use in the AH.
782+
*/
783+
if (memcmp(pathrec->dgid.raw, path->pathrec.dgid.raw,
784+
sizeof(union ib_gid))) {
785+
ipoib_dbg(
786+
priv,
787+
"%s got PathRec for gid %pI6 while asked for %pI6\n",
788+
dev->name, pathrec->dgid.raw,
789+
path->pathrec.dgid.raw);
790+
memcpy(pathrec->dgid.raw, path->pathrec.dgid.raw,
791+
sizeof(union ib_gid));
792+
}
793+
778794
path->pathrec = *pathrec;
779795

780796
old_ah = path->ah;

0 commit comments

Comments
 (0)