lkml.org 
[lkml]   [2019]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.2 080/162] SMB3: Fix potential memory leak when processing compound chain
    Date
    [ Upstream commit 3edeb4a4146dc3b54d6fa71b7ee0585cb52ebfdf ]

    When a reconnect happens in the middle of processing a compound chain
    the code leaks a buffer from the memory pool. Fix this by properly
    checking for a return code and freeing buffers in case of error.

    Also maintain a buf variable to be equal to either smallbuf or bigbuf
    depending on a response buffer size while parsing a chain and when
    returning to the caller.

    Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
    Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
    Signed-off-by: Steve French <stfrench@microsoft.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/cifs/smb2ops.c | 29 +++++++++++++++++------------
    1 file changed, 17 insertions(+), 12 deletions(-)

    diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
    index 2ec37dc589a7b..ae10d6e297c3a 100644
    --- a/fs/cifs/smb2ops.c
    +++ b/fs/cifs/smb2ops.c
    @@ -4015,7 +4015,6 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
    {
    int ret, length;
    char *buf = server->smallbuf;
    - char *tmpbuf;
    struct smb2_sync_hdr *shdr;
    unsigned int pdu_length = server->pdu_size;
    unsigned int buf_size;
    @@ -4045,18 +4044,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
    return length;

    next_is_large = server->large_buf;
    - one_more:
    +one_more:
    shdr = (struct smb2_sync_hdr *)buf;
    if (shdr->NextCommand) {
    - if (next_is_large) {
    - tmpbuf = server->bigbuf;
    + if (next_is_large)
    next_buffer = (char *)cifs_buf_get();
    - } else {
    - tmpbuf = server->smallbuf;
    + else
    next_buffer = (char *)cifs_small_buf_get();
    - }
    memcpy(next_buffer,
    - tmpbuf + le32_to_cpu(shdr->NextCommand),
    + buf + le32_to_cpu(shdr->NextCommand),
    pdu_length - le32_to_cpu(shdr->NextCommand));
    }

    @@ -4085,12 +4081,21 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
    pdu_length -= le32_to_cpu(shdr->NextCommand);
    server->large_buf = next_is_large;
    if (next_is_large)
    - server->bigbuf = next_buffer;
    + server->bigbuf = buf = next_buffer;
    else
    - server->smallbuf = next_buffer;
    -
    - buf += le32_to_cpu(shdr->NextCommand);
    + server->smallbuf = buf = next_buffer;
    goto one_more;
    + } else if (ret != 0) {
    + /*
    + * ret != 0 here means that we didn't get to handle_mid() thus
    + * server->smallbuf and server->bigbuf are still valid. We need
    + * to free next_buffer because it is not going to be used
    + * anywhere.
    + */
    + if (next_is_large)
    + free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
    + else
    + free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
    }

    return ret;
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-08-27 10:03    [W:3.944 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site