From: Namjae Jeon linkinjeon@kernel.org
mainline inclusion from mainline-5.17-rc1 commit b589f5db6d4af8f14d70e31e1276b4c017668a26 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I60T7G CVE: NA
Reference: https://git.kernel.org/torvalds/linux/c/b589f5db6d4a
-------------------------------
If the client ignores the CreditResponse received from the server and continues to send the request, ksmbd limits the requests if it exceeds smb2 max credits.
Signed-off-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com --- fs/ksmbd/connection.c | 1 + fs/ksmbd/connection.h | 3 ++- fs/ksmbd/smb2misc.c | 9 +++++++++ fs/ksmbd/smb2pdu.c | 1 + 4 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c index cdb029e4fae5..8e15ec9e8f43 100644 --- a/fs/ksmbd/connection.c +++ b/fs/ksmbd/connection.c @@ -63,6 +63,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) atomic_set(&conn->req_running, 0); atomic_set(&conn->r_count, 0); conn->total_credits = 1; + conn->outstanding_credits = 1;
init_waitqueue_head(&conn->req_running_q); init_waitqueue_head(&conn->r_count_q); diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h index b50c33bd1315..f803e3e60d34 100644 --- a/fs/ksmbd/connection.h +++ b/fs/ksmbd/connection.h @@ -54,7 +54,8 @@ struct ksmbd_conn { atomic_t req_running; /* References which are made for this Server object*/ atomic_t r_count; - unsigned short total_credits; + unsigned int total_credits; + unsigned int outstanding_credits; spinlock_t credits_lock; wait_queue_head_t req_running_q; wait_queue_head_t r_count_q; diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c index 5dd91879e3d9..81b227034865 100644 --- a/fs/ksmbd/smb2misc.c +++ b/fs/ksmbd/smb2misc.c @@ -333,7 +333,16 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn, credit_charge, conn->total_credits); ret = 1; } + + if ((u64)conn->outstanding_credits + credit_charge > conn->vals->max_credits) { + ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n", + credit_charge, conn->outstanding_credits); + ret = 1; + } else + conn->outstanding_credits += credit_charge; + spin_unlock(&conn->credits_lock); + return ret; }
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 1370fc6f1f0b..5a7eab3991db 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -323,6 +323,7 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) }
conn->total_credits -= credit_charge; + conn->outstanding_credits -= credit_charge; credits_requested = max_t(unsigned short, le16_to_cpu(req_hdr->CreditRequest), 1);