diff options
author | Gordon Ross <gwr@racktopsystems.com> | 2021-09-14 22:42:59 -0400 |
---|---|---|
committer | Gordon Ross <gwr@racktopsystems.com> | 2022-07-11 13:25:29 -0400 |
commit | 174513368dec739adb93c76e5d47aed84797d1ad (patch) | |
tree | 68f9c3a89dde8e7b1f420f8f83fee136ea41354c | |
parent | 2126a14a5539b804448c27ae4eee033b7aacfa50 (diff) | |
download | illumos-joyent-174513368dec739adb93c76e5d47aed84797d1ad.tar.gz |
14739 smbtorture disconnect after bad credit grant
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Jerry Jelinek <gjelinek@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb2_dispatch.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c index 9aafb6e4d7..164b54e685 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c @@ -326,33 +326,35 @@ smb2_credit_decrease(smb_request_t *sr) smb_session_t *session = sr->session; uint16_t cur, d; + ASSERT3U(sr->smb2_credit_request, <, sr->smb2_credit_charge); + mutex_enter(&session->s_credits_mutex); cur = session->s_cur_credits; + ASSERT(cur > 0); /* Handle credit decrease. */ d = sr->smb2_credit_charge - sr->smb2_credit_request; - cur -= d; - if (cur & 0x8000) { - /* - * underflow (bad credit charge or request) - * leave credits unchanged (response=charge) - */ - cur = session->s_cur_credits; - sr->smb2_credit_response = sr->smb2_credit_charge; - DTRACE_PROBE1(smb2__credit__neg, smb_request_t *, sr); - } /* - * The server MUST ensure that the number of credits - * held by the client is never reduced to zero. + * Prevent underflow of current credits, and + * enforce a minimum of one credit, per: * [MS-SMB2] 3.3.1.2 */ - if (cur == 0) { + if (d >= cur) { + /* + * Tried to give up more credits than we should. + * Reduce the decrement. + */ + d = cur - 1; cur = 1; - sr->smb2_credit_response += 1; - DTRACE_PROBE1(smb2__credit__min, smb_request_t *, sr); + DTRACE_PROBE1(smb2__credit__neg, smb_request_t *, sr); + } else { + cur -= d; } + ASSERT3U(d, <=, sr->smb2_credit_charge); + sr->smb2_credit_response = sr->smb2_credit_charge - d; + DTRACE_PROBE3(smb2__credit__decrease, smb_request_t *, sr, int, (int)cur, int, (int)session->s_cur_credits); @@ -370,23 +372,26 @@ smb2_credit_increase(smb_request_t *sr) smb_session_t *session = sr->session; uint16_t cur, d; + ASSERT3U(sr->smb2_credit_request, >, sr->smb2_credit_charge); + mutex_enter(&session->s_credits_mutex); cur = session->s_cur_credits; /* Handle credit increase. */ d = sr->smb2_credit_request - sr->smb2_credit_charge; - cur += d; /* * If new credits would be above max, * reduce the credit grant. */ - if (cur > session->s_max_credits) { - d = cur - session->s_max_credits; + if (d > (session->s_max_credits - cur)) { + d = session->s_max_credits - cur; cur = session->s_max_credits; - sr->smb2_credit_response -= d; - DTRACE_PROBE1(smb2__credit__max, smb_request_t, sr); + DTRACE_PROBE1(smb2__credit__max, smb_request_t *, sr); + } else { + cur += d; } + sr->smb2_credit_response = sr->smb2_credit_charge + d; DTRACE_PROBE3(smb2__credit__increase, smb_request_t *, sr, int, (int)cur, @@ -859,7 +864,6 @@ cmd_start: * when we sent the interim reply. */ if (!sr->smb2_async) { - sr->smb2_credit_response = sr->smb2_credit_request; if (sr->smb2_credit_request < sr->smb2_credit_charge) { smb2_credit_decrease(sr); } @@ -1205,7 +1209,6 @@ cmd_start: * credit decrease was done by the caller. */ if (sr->smb2_cmd_hdr != saved_cmd_hdr) { - sr->smb2_credit_response = sr->smb2_credit_request; if (sr->smb2_credit_request < sr->smb2_credit_charge) { smb2_credit_decrease(sr); } |