diff mbox

[01/15] cifs: update smb2_check_message to handle PDUs without a 4 byte length header

Message ID CAH2r5mtOZR=x3sf=83FTCS8ibEpLcppitC2i-eY5cLGpz8e06A@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Steve French May 30, 2018, 5:53 p.m. UTC
to get it to build I had to fix a couple lines (get_neg_ctxt_len) and
merged in with your patch 1- see attached



On Tue, May 29, 2018 at 7:47 PM, Ronnie Sahlberg <lsahlber@redhat.com> wrote:
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/smb2misc.c | 43 ++++++++++++++++---------------------------
>  1 file changed, 16 insertions(+), 27 deletions(-)
>
> diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
> index f7f3ad760401..0a12c2133770 100644
> --- a/fs/cifs/smb2misc.c
> +++ b/fs/cifs/smb2misc.c
> @@ -131,25 +131,20 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
>  #endif /* CIFS_SMB311 */
>
>  int
> -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
> +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
>  {
> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
> -       struct smb2_hdr *hdr = &pdu->hdr;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)(buf + srvr->vals->header_preamble_size);
> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
>         __u64 mid;
> -       __u32 len = get_rfc1002_length(buf);
>         __u32 clc_len;  /* calculated length */
>         int command;
> -
> -       /* BB disable following printk later */
> -       cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
> -                __func__, length, len);
> +       int pdu_size = sizeof(struct smb2_sync_pdu);
> +       int hdr_size = sizeof(struct smb2_sync_hdr);
>
>         /*
>          * Add function to do table lookup of StructureSize by command
>          * ie Validate the wct via smb2_struct_sizes table above
>          */
> -
>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
>                 struct smb2_transform_hdr *thdr =
>                         (struct smb2_transform_hdr *)buf;
> @@ -173,8 +168,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>         }
>
>         mid = le64_to_cpu(shdr->MessageId);
> -       if (length < sizeof(struct smb2_pdu)) {
> -               if ((length >= sizeof(struct smb2_hdr))
> +       if (len < pdu_size) {
> +               if ((len >= hdr_size)
>                     && (shdr->Status != 0)) {
>                         pdu->StructureSize2 = 0;
>                         /*
> @@ -227,31 +222,25 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                 }
>         }
>
> -       if (srvr->vals->header_preamble_size + len != length) {
> -               cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n",
> -                        length, srvr->vals->header_preamble_size + len, mid);
> -               return 1;
> -       }
> -
> -       clc_len = smb2_calc_size(hdr, srvr);
> +       clc_len = smb2_calc_size(buf, srvr);
>
>  #ifdef CONFIG_CIFS_SMB311
>         if (shdr->Command == SMB2_NEGOTIATE)
>                 clc_len += get_neg_ctxt_len(hdr, len, clc_len,
>                                         srvr->vals->header_preamble_size);
>  #endif /* SMB311 */
> -       if (srvr->vals->header_preamble_size + len != clc_len) {
> -               cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n",
> -                        clc_len, srvr->vals->header_preamble_size + len, mid);
> +       if (len != clc_len) {
> +               cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
> +                        clc_len, len, mid);
>                 /* create failed on symlink */
>                 if (command == SMB2_CREATE_HE &&
>                     shdr->Status == STATUS_STOPPED_ON_SYMLINK)
>                         return 0;
>                 /* Windows 7 server returns 24 bytes more */
> -               if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE)
> +               if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
>                         return 0;
>                 /* server can return one byte more due to implied bcc[0] */
> -               if (clc_len == srvr->vals->header_preamble_size + len + 1)
> +               if (clc_len == len + 1)
>                         return 0;
>
>                 /*
> @@ -261,10 +250,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                  * Log the server error (once), but allow it and continue
>                  * since the frame is parseable.
>                  */
> -               if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) {
> +               if (clc_len < len) {
>                         printk_once(KERN_WARNING
> -                               "SMB2 server sent bad RFC1001 len %d not %zu\n",
> -                               len, clc_len - srvr->vals->header_preamble_size);
> +                               "SMB2 server sent bad RFC1001 len %d not %u\n",
> +                               len, clc_len);
>                         return 0;
>                 }
>
> --
> 2.13.3
>
diff mbox

Patch

From 5b540f13736fe4f7e11fd7d2ab27ae29b91c8ad0 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <lsahlber@redhat.com>
Date: Wed, 30 May 2018 10:47:01 +1000
Subject: [PATCH 1/2] cifs: update smb2_check_message to handle PDUs without a
 4 byte length header

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
---
 fs/cifs/smb2misc.c | 49 ++++++++++++++++++----------------------------
 1 file changed, 19 insertions(+), 30 deletions(-)

diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index f7f3ad760401..ba1a20cf9846 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -94,8 +94,8 @@  static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
 };
 
 #ifdef CONFIG_CIFS_SMB311
-static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
-				size_t hdr_preamble_size)
+static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
+			__u32 non_ctxlen, size_t hdr_preamble_size)
 {
 	__u16 neg_count;
 	__u32 nc_offset, size_of_pad_before_neg_ctxts;
@@ -131,25 +131,20 @@  static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
 #endif /* CIFS_SMB311 */
 
 int
-smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
+smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
 {
-	struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
-	struct smb2_hdr *hdr = &pdu->hdr;
-	struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)(buf + srvr->vals->header_preamble_size);
+	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
 	__u64 mid;
-	__u32 len = get_rfc1002_length(buf);
 	__u32 clc_len;  /* calculated length */
 	int command;
-
-	/* BB disable following printk later */
-	cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
-		 __func__, length, len);
+	int pdu_size = sizeof(struct smb2_sync_pdu);
+	int hdr_size = sizeof(struct smb2_sync_hdr);
 
 	/*
 	 * Add function to do table lookup of StructureSize by command
 	 * ie Validate the wct via smb2_struct_sizes table above
 	 */
-
 	if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
 		struct smb2_transform_hdr *thdr =
 			(struct smb2_transform_hdr *)buf;
@@ -173,8 +168,8 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 	}
 
 	mid = le64_to_cpu(shdr->MessageId);
-	if (length < sizeof(struct smb2_pdu)) {
-		if ((length >= sizeof(struct smb2_hdr))
+	if (len < pdu_size) {
+		if ((len >= hdr_size)
 		    && (shdr->Status != 0)) {
 			pdu->StructureSize2 = 0;
 			/*
@@ -227,31 +222,25 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		}
 	}
 
-	if (srvr->vals->header_preamble_size + len != length) {
-		cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n",
-			 length, srvr->vals->header_preamble_size + len, mid);
-		return 1;
-	}
-
-	clc_len = smb2_calc_size(hdr, srvr);
+	clc_len = smb2_calc_size(buf, srvr);
 
 #ifdef CONFIG_CIFS_SMB311
 	if (shdr->Command == SMB2_NEGOTIATE)
-		clc_len += get_neg_ctxt_len(hdr, len, clc_len,
+		clc_len += get_neg_ctxt_len(shdr, len, clc_len,
 					srvr->vals->header_preamble_size);
 #endif /* SMB311 */
-	if (srvr->vals->header_preamble_size + len != clc_len) {
-		cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n",
-			 clc_len, srvr->vals->header_preamble_size + len, mid);
+	if (len != clc_len) {
+		cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
+			 clc_len, len, mid);
 		/* create failed on symlink */
 		if (command == SMB2_CREATE_HE &&
 		    shdr->Status == STATUS_STOPPED_ON_SYMLINK)
 			return 0;
 		/* Windows 7 server returns 24 bytes more */
-		if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE)
+		if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
 			return 0;
 		/* server can return one byte more due to implied bcc[0] */
-		if (clc_len == srvr->vals->header_preamble_size + len + 1)
+		if (clc_len == len + 1)
 			return 0;
 
 		/*
@@ -261,10 +250,10 @@  smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 		 * Log the server error (once), but allow it and continue
 		 * since the frame is parseable.
 		 */
-		if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) {
+		if (clc_len < len) {
 			printk_once(KERN_WARNING
-				"SMB2 server sent bad RFC1001 len %d not %zu\n",
-				len, clc_len - srvr->vals->header_preamble_size);
+				"SMB2 server sent bad RFC1001 len %d not %u\n",
+				len, clc_len);
 			return 0;
 		}
 
-- 
2.17.0