Skip to content

Commit 6f84b50

Browse files
committed
ksmbd: prevent connection free while sending oplock brean notification
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent fe575dd commit 6f84b50

File tree

4 files changed

+30
-12
lines changed

4 files changed

+30
-12
lines changed

connection.c

+20
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,26 @@ void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)
485485
default_conn_ops.terminate_fn = ops->terminate_fn;
486486
}
487487

488+
void ksmbd_conn_r_count_inc(struct ksmbd_conn *conn)
489+
{
490+
atomic_inc(&conn->r_count);
491+
}
492+
493+
void ksmbd_conn_r_count_dec(struct ksmbd_conn *conn)
494+
{
495+
/*
496+
* Checking waitqueue to dropping pending requests on
497+
* disconnection. waitqueue_active is safe because it
498+
* uses atomic operation for condition.
499+
*/
500+
atomic_inc(&conn->refcnt);
501+
if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
502+
wake_up(&conn->r_count_q);
503+
504+
if (atomic_dec_and_test(&conn->refcnt))
505+
kfree(conn);
506+
}
507+
488508
int ksmbd_conn_transport_init(void)
489509
{
490510
int ret;

connection.h

+2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ int ksmbd_conn_transport_init(void);
168168
void ksmbd_conn_transport_destroy(void);
169169
void ksmbd_conn_lock(struct ksmbd_conn *conn);
170170
void ksmbd_conn_unlock(struct ksmbd_conn *conn);
171+
void ksmbd_conn_r_count_inc(struct ksmbd_conn *conn);
172+
void ksmbd_conn_r_count_dec(struct ksmbd_conn *conn);
171173

172174
/*
173175
* WARNING

oplock.c

+6
Original file line numberDiff line numberDiff line change
@@ -809,10 +809,12 @@ static int smb1_oplock_break_noti(struct oplock_info *opinfo)
809809
work->conn = conn;
810810

811811
if (opinfo->op_state == OPLOCK_ACK_WAIT) {
812+
ksmbd_conn_r_count_inc(conn);
812813
INIT_WORK(&work->work, __smb1_oplock_break_noti);
813814
ksmbd_queue_work(work);
814815

815816
wait_for_break_ack(opinfo);
817+
ksmbd_conn_r_count_dec(conn);
816818
} else {
817819
__smb1_oplock_break_noti(&work->work);
818820
if (opinfo->level == OPLOCK_READ)
@@ -925,10 +927,12 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
925927
work->sess = opinfo->sess;
926928

927929
if (opinfo->op_state == OPLOCK_ACK_WAIT) {
930+
ksmbd_conn_r_count_inc(conn);
928931
INIT_WORK(&work->work, __smb2_oplock_break_noti);
929932
ksmbd_queue_work(work);
930933

931934
wait_for_break_ack(opinfo);
935+
ksmbd_conn_r_count_dec(conn);
932936
} else {
933937
__smb2_oplock_break_noti(&work->work);
934938
if (opinfo->level == SMB2_OPLOCK_LEVEL_II)
@@ -1031,9 +1035,11 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
10311035
work->sess = opinfo->sess;
10321036

10331037
if (opinfo->op_state == OPLOCK_ACK_WAIT) {
1038+
ksmbd_conn_r_count_inc(conn);
10341039
INIT_WORK(&work->work, __smb2_lease_break_noti);
10351040
ksmbd_queue_work(work);
10361041
wait_for_break_ack(opinfo);
1042+
ksmbd_conn_r_count_dec(conn);
10371043
} else {
10381044
__smb2_lease_break_noti(&work->work);
10391045
if (opinfo->o_lease->new_state == SMB2_LEASE_NONE_LE) {

server.c

+2-12
Original file line numberDiff line numberDiff line change
@@ -270,17 +270,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
270270

271271
ksmbd_conn_try_dequeue_request(work);
272272
ksmbd_free_work_struct(work);
273-
/*
274-
* Checking waitqueue to dropping pending requests on
275-
* disconnection. waitqueue_active is safe because it
276-
* uses atomic operation for condition.
277-
*/
278-
atomic_inc(&conn->refcnt);
279-
if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
280-
wake_up(&conn->r_count_q);
281-
282-
if (atomic_dec_and_test(&conn->refcnt))
283-
kfree(conn);
273+
ksmbd_conn_r_count_dec(conn);
284274
}
285275

286276
/**
@@ -310,7 +300,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
310300
conn->request_buf = NULL;
311301

312302
ksmbd_conn_enqueue_request(work);
313-
atomic_inc(&conn->r_count);
303+
ksmbd_conn_r_count_inc(conn);
314304
/* update activity on connection */
315305
conn->last_active = jiffies;
316306
INIT_WORK(&work->work, handle_ksmbd_work);

0 commit comments

Comments
 (0)