summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamjae Jeon <linkinjeon@kernel.org>2021-12-31 03:26:25 +0300
committerSteve French <stfrench@microsoft.com>2022-01-10 21:44:19 +0300
commitb589f5db6d4af8f14d70e31e1276b4c017668a26 (patch)
treed5d2850a5a54c553245e40435576b89da8d19008
parent914d7e5709ac59ded70bea7956d408fe2acd7c3c (diff)
downloadlinux-b589f5db6d4af8f14d70e31e1276b4c017668a26.tar.xz
ksmbd: limits exceeding the maximum allowable outstanding requests
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>
-rw-r--r--fs/ksmbd/connection.c1
-rw-r--r--fs/ksmbd/connection.h3
-rw-r--r--fs/ksmbd/smb2misc.c9
-rw-r--r--fs/ksmbd/smb2pdu.c1
4 files changed, 13 insertions, 1 deletions
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 83a94d0bb480..d1d0105be5b1 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -62,6 +62,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_LIST_HEAD(&conn->conns_list);
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index 42ffb6d9c5d8..7e0730a262da 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -61,7 +61,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;
/* Lock to protect requests list*/
diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c
index fedcb753c7af..4a9460153b59 100644
--- a/fs/ksmbd/smb2misc.c
+++ b/fs/ksmbd/smb2misc.c
@@ -337,7 +337,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 706191f5e475..867ed982f729 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -322,6 +322,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);