Skip to contentSkip to conversation

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

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-next 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 also be merged in the next major kernel release during the merge window.

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