patch "staging: lustre: separate a connection destroy from free struct" added to staging-next
Subsystems (2)
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
9b046013e5837f8a58453d1e9f8e01d03adb7fe7Mon 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
3317kiblnd_destroy_conn(conn, !peer);
^^^^ Freed always (but should be conditionally)
3318
3319spin_lock_irqsave(lock, flags);
3320 if (!peer)
3321 continue;
33223323 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.
--- 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
@@ -824,14 +824,15 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cmreturn 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
@@ -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
@@ -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