Commit 64e3d455 authored by Erez Shitrit's avatar Erez Shitrit Committed by Greg Kroah-Hartman

IB/ipoib: Avoid memory leak if the SA returns a different DGID


[ Upstream commit 43900089 ]

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: default avatarErez Shitrit <erezsh@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarSasha Levin <alexander.levin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3ed000cd
...@@ -724,6 +724,22 @@ static void path_rec_completion(int status, ...@@ -724,6 +724,22 @@ static void path_rec_completion(int status,
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (!IS_ERR_OR_NULL(ah)) { if (!IS_ERR_OR_NULL(ah)) {
/*
* pathrec.dgid is used as the database key from the LLADDR,
* it must remain unchanged even if the SA returns a different
* GID to use in the AH.
*/
if (memcmp(pathrec->dgid.raw, path->pathrec.dgid.raw,
sizeof(union ib_gid))) {
ipoib_dbg(
priv,
"%s got PathRec for gid %pI6 while asked for %pI6\n",
dev->name, pathrec->dgid.raw,
path->pathrec.dgid.raw);
memcpy(pathrec->dgid.raw, path->pathrec.dgid.raw,
sizeof(union ib_gid));
}
path->pathrec = *pathrec; path->pathrec = *pathrec;
old_ah = path->ah; old_ah = path->ah;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment