Skip to contentSkip to conversation

patch "staging: lustre: separate a connection destroy from free struct" added to staging-testing

PATCH [email protected] 1 participant 1 message Jan 26, 2018

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

staging: lustre: separate a connection destroy from free struct

to my staging git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
in the staging-testing branch.

The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)

The patch will be merged to the staging-next branch sometime soon, after it passes testing, and the merge window is open.

If you have any questions about this process, please let me know.

Quoted 1 line

From 9b046013e5837f8a58453d1e9f8e01d03adb7fe7 Mon Sep 17 00:00:00 2001

From: Dmitry Eremin <[email protected]>
Date: Thu, 25 Jan 2018 16:51:04 +0300
Subject: staging: lustre: separate a connection destroy from free struct
kib_conn

The logic of the original commit 4d99b2581eff ("staging: lustre: avoid intensive reconnecting for ko2iblnd") was assumed conditional free of struct kib_conn if the second argument free_conn in function kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn) is true. But this hunk of code was dropped from original commit. As result the logic works wrong and current code use struct kib_conn after free.

Quoted 17 lines

drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
3317 kiblnd_destroy_conn(conn, !peer);
^^^^ Freed always (but should be conditionally)
3318
3319 spin_lock_irqsave(lock, flags);
3320 if (!peer)
3321 continue;
3322

3323  conn->ibc_peer = peer;
      ^^^^^^^^^^^^^^ Use after free
3324  if (peer->ibp_reconnected < KIB_RECONN_HIGH_RACE)
3325      list_add_tail(&conn->ibc_list,
                         ^^^^^^^^^^^^^^ Use after free
3326                    &kiblnd_data.kib_reconn_list);
3327  else
3328      list_add_tail(&conn->ibc_list,
                         ^^^^^^^^^^^^^^ Use after free
Quoted 1 line

3329 &kiblnd_data.kib_reconn_wait);

To avoid confusion this fix moved the freeing a struct kib_conn outside of the function kiblnd_destroy_conn() and free as it was intended in original commit.

Cc <[email protected]> # v4.6
Fixes 4d99b2581eff ("staging: lustre: avoid intensive reconnecting for ko2iblnd")
---
 drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c    | 7 +++----
 drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h    | 2 +-
 drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 6 ++++--
 3 files changed, 8 insertions(+), 7 deletions(-)
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +3 -4
index 2ebc484385b3..ec84edfda271 100644
@@ -824,14 +824,15 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cm
 	return conn;
 
  failed_2:
-	kiblnd_destroy_conn(conn, true);
+	kiblnd_destroy_conn(conn);
+	kfree(conn);
  failed_1:
 	kfree(init_qp_attr);
  failed_0:
 	return NULL;
 }
 
-void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn)
+void kiblnd_destroy_conn(struct kib_conn *conn)
 {
 	struct rdma_cm_id *cmid = conn->ibc_cmid;
 	struct kib_peer *peer = conn->ibc_peer;
@@ -889,8 +890,6 @@ void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn)
 		rdma_destroy_id(cmid);
 		atomic_dec(&net->ibn_nconns);
 	}
-
-	kfree(conn);
 }
 
 int kiblnd_close_peer_conns_locked(struct kib_peer *peer, int why)
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +1 -1
index 171eced213f8..b18911d09e9a 100644
@@ -1016,7 +1016,7 @@ int  kiblnd_close_peer_conns_locked(struct kib_peer *peer, int why);
 struct kib_conn *kiblnd_create_conn(struct kib_peer *peer,
 				    struct rdma_cm_id *cmid,
 				    int state, int version);
-void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn);
+void kiblnd_destroy_conn(struct kib_conn *conn);
 void kiblnd_close_conn(struct kib_conn *conn, int error);
 void kiblnd_close_conn_locked(struct kib_conn *conn, int error);
 
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +4 -2
index 9b3328c5d1e7..b3e7f28eb978 100644
@@ -3314,11 +3314,13 @@ kiblnd_connd(void *arg)
 			spin_unlock_irqrestore(lock, flags);
 			dropped_lock = 1;
 
-			kiblnd_destroy_conn(conn, !peer);
+			kiblnd_destroy_conn(conn);
 
 			spin_lock_irqsave(lock, flags);
-			if (!peer)
+			if (!peer) {
+				kfree(conn);
 				continue;
+			}
 
 			conn->ibc_peer = peer;
 			if (peer->ibp_reconnected < KIB_RECONN_HIGH_RACE)
Signature · 1 line
2.16.1