Re: [PATCH 1/5] cifs: consolidate SendReceive response checks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2011/4/2 Jeff Layton <jlayton@xxxxxxxxxx>:
> Further consolidate the SendReceive code by moving the checks run over
> the packet into a separate function that all the SendReceive variants
> can call.
>
> We can also eliminate the check for a receive_len that's too big or too
> small. cifs_demultiplex_thread already checks that and disconnects the
> socket if that occurs, while setting the midStatus to MALFORMED. It'll
> never call this code if that's the case.
>
> Finally do a little cleanup. Use "goto out" on errors so that the flow
> of code in the normal case is more evident. Also switch the logErr
> variable in map_smb_to_linux_error to a bool.
>
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/cifs/cifsproto.h |    4 +-
>  fs/cifs/netmisc.c   |    2 +-
>  fs/cifs/transport.c |  158 ++++++++++++++-------------------------------------
>  3 files changed, 46 insertions(+), 118 deletions(-)
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 76c4dc7f..4af7db8 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -74,6 +74,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
>                        int * /* bytes returned */ , const int long_op);
>  extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
>                        struct smb_hdr *in_buf, int flags);
> +extern int cifs_check_receive(struct mid_q_entry *mid,
> +                       struct TCP_Server_Info *server, bool log_error);
>  extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
>                        struct kvec *, int /* nvec to send */,
>                        int * /* type of buf returned */ , const int flags);
> @@ -97,7 +99,7 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
>  extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);
>  extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
>                                const unsigned short int port);
> -extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
> +extern int map_smb_to_linux_error(struct smb_hdr *smb, bool logErr);
>  extern void header_assemble(struct smb_hdr *, char /* command */ ,
>                            const struct cifs_tcon *, int /* length of
>                            fixed section (word count) in two byte units */);
> diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
> index 79b71c2..73e47e8 100644
> --- a/fs/cifs/netmisc.c
> +++ b/fs/cifs/netmisc.c
> @@ -836,7 +836,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
>  }
>
>  int
> -map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
> +map_smb_to_linux_error(struct smb_hdr *smb, bool logErr)
>  {
>        unsigned int i;
>        int rc = -EIO;  /* if transport error smb error may not be set */
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 85063de..d9833fc 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -505,13 +505,32 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
>  }
>
>  int
> +cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
> +                  bool log_error)
> +{
> +       dump_smb(mid->resp_buf,
> +                min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length)));
> +
> +       /* convert the length into a more usable form */
> +       if (server->sec_mode & (SECMODE_SIGN_REQUIRED |
> +                               SECMODE_SIGN_ENABLED)) {
> +               /* FIXME: add code to kill session */
> +               if (cifs_verify_signature(mid->resp_buf, server,
> +                                         mid->sequence_number + 1) != 0)
> +                       cERROR(1, "Unexpected SMB signature");
> +       }
> +
> +       /* BB special case reconnect tid and uid here? */
> +       return map_smb_to_linux_error(mid->resp_buf, log_error);
> +}
> +
> +int
>  SendReceive2(const unsigned int xid, struct cifs_ses *ses,
>             struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
>             const int flags)
>  {
>        int rc = 0;
>        int long_op;
> -       unsigned int receive_len;
>        struct mid_q_entry *midQ;
>        struct smb_hdr *in_buf = iov[0].iov_base;
>
> @@ -604,54 +623,24 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
>                return rc;
>        }
>
> -       receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
> -
> -       if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
> -               cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
> -                       receive_len, xid);
> +       if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) {
>                rc = -EIO;
> +               cFYI(1, "Bad MID state?");
>                goto out;
>        }
>
> -       /* rcvd frame is ok */
> -
> -       if (midQ->resp_buf &&
> -           (midQ->midState == MID_RESPONSE_RECEIVED)) {
> -
> -               iov[0].iov_base = (char *)midQ->resp_buf;
> -               if (midQ->largeBuf)
> -                       *pRespBufType = CIFS_LARGE_BUFFER;
> -               else
> -                       *pRespBufType = CIFS_SMALL_BUFFER;
> -               iov[0].iov_len = receive_len + 4;
> -
> -               dump_smb(midQ->resp_buf, 80);
> -               /* convert the length into a more usable form */
> -               if ((receive_len > 24) &&
> -                   (ses->server->sec_mode & (SECMODE_SIGN_REQUIRED |
> -                                            SECMODE_SIGN_ENABLED))) {
> -                       rc = cifs_verify_signature(midQ->resp_buf,
> -                                               ses->server,
> -                                               midQ->sequence_number+1);
> -                       if (rc) {
> -                               cERROR(1, "Unexpected SMB signature");
> -                               /* BB FIXME add code to kill session */
> -                       }
> -               }
> -
> -               /* BB special case reconnect tid and uid here? */
> -               rc = map_smb_to_linux_error(midQ->resp_buf,
> -                                           flags & CIFS_LOG_ERROR);
> +       iov[0].iov_base = (char *)midQ->resp_buf;
> +       iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4;
> +       if (midQ->largeBuf)
> +               *pRespBufType = CIFS_LARGE_BUFFER;
> +       else
> +               *pRespBufType = CIFS_SMALL_BUFFER;
>
> -               if ((flags & CIFS_NO_RESP) == 0)
> -                       midQ->resp_buf = NULL;  /* mark it so buf will
> -                                                  not be freed by
> -                                                  delete_mid */
> -       } else {
> -               rc = -EIO;
> -               cFYI(1, "Bad MID state?");
> -       }
> +       rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR);
>
> +       /* mark it so buf will not be freed by delete_mid */
> +       if ((flags & CIFS_NO_RESP) == 0)
> +               midQ->resp_buf = NULL;
>  out:
>        delete_mid(midQ);
>        atomic_dec(&ses->server->inFlight);
> @@ -666,7 +655,6 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
>            int *pbytes_returned, const int long_op)
>  {
>        int rc = 0;
> -       unsigned int receive_len;
>        struct mid_q_entry *midQ;
>
>        if (ses == NULL) {
> @@ -753,47 +741,16 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
>                return rc;
>        }
>
> -       receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
> -
> -       if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
> -               cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
> -                       receive_len, xid);
> -               rc = -EIO;
> -               goto out;
> -       }
> -
> -       /* rcvd frame is ok */
> -
> -       if (midQ->resp_buf && out_buf
> -           && (midQ->midState == MID_RESPONSE_RECEIVED)) {
> -               out_buf->smb_buf_length = cpu_to_be32(receive_len);
> -               memcpy((char *)out_buf + 4,
> -                      (char *)midQ->resp_buf + 4,
> -                      receive_len);
> -
> -               dump_smb(out_buf, 92);
> -               /* convert the length into a more usable form */
> -               if ((receive_len > 24) &&
> -                   (ses->server->sec_mode & (SECMODE_SIGN_REQUIRED |
> -                                            SECMODE_SIGN_ENABLED))) {
> -                       rc = cifs_verify_signature(out_buf,
> -                                               ses->server,
> -                                               midQ->sequence_number+1);
> -                       if (rc) {
> -                               cERROR(1, "Unexpected SMB signature");
> -                               /* BB FIXME add code to kill session */
> -                       }
> -               }
> -
> -               *pbytes_returned = be32_to_cpu(out_buf->smb_buf_length);
> -
> -               /* BB special case reconnect tid and uid here? */
> -               rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
> -       } else {
> +       if (!midQ->resp_buf || !out_buf ||
> +           midQ->midState != MID_RESPONSE_RECEIVED) {
>                rc = -EIO;
>                cERROR(1, "Bad MID state?");
> +               goto out;
>        }
>
> +       *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
> +       memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
> +       rc = cifs_check_receive(midQ, ses->server, 0);
>  out:
>        delete_mid(midQ);
>        atomic_dec(&ses->server->inFlight);
> @@ -834,7 +791,6 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
>  {
>        int rc = 0;
>        int rstart = 0;
> -       unsigned int receive_len;
>        struct mid_q_entry *midQ;
>        struct cifs_ses *ses;
>
> @@ -953,46 +909,16 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
>        if (rc != 0)
>                return rc;
>
> -       receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
> -       if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
> -               cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
> -                       receive_len, xid);
> -               rc = -EIO;
> -               goto out;
> -       }
> -
>        /* rcvd frame is ok */
> -
> -       if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
> +       if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) {
>                rc = -EIO;
>                cERROR(1, "Bad MID state?");
>                goto out;
>        }
>
> -       out_buf->smb_buf_length = cpu_to_be32(receive_len);
> -       memcpy((char *)out_buf + 4,
> -              (char *)midQ->resp_buf + 4,
> -              receive_len);
> -
> -       dump_smb(out_buf, 92);
> -       /* convert the length into a more usable form */
> -       if ((receive_len > 24) &&
> -           (ses->server->sec_mode & (SECMODE_SIGN_REQUIRED |
> -                                    SECMODE_SIGN_ENABLED))) {
> -               rc = cifs_verify_signature(out_buf,
> -                                          ses->server,
> -                                          midQ->sequence_number+1);
> -               if (rc) {
> -                       cERROR(1, "Unexpected SMB signature");
> -                       /* BB FIXME add code to kill session */
> -               }
> -       }
> -
> -       *pbytes_returned = be32_to_cpu(out_buf->smb_buf_length);
> -
> -       /* BB special case reconnect tid and uid here? */
> -       rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
> -
> +       *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
> +       memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
> +       rc = cifs_check_receive(midQ, ses->server, 0);
>  out:
>        delete_mid(midQ);
>        if (rstart && rc == -EACCES)
> --
> 1.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Looks good.

Reviewed-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>

-- 
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux