lkml.org 
[lkml]   [2022]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6.0 222/862] SUNRPC: Fix svcxdr_init_decodes end-of-buffer calculation
    Date
    From: Chuck Lever <chuck.lever@oracle.com>

    [ Upstream commit 90bfc37b5ab91c1a6165e3e5cfc49bf04571b762 ]

    Ensure that stream-based argument decoding can't go past the actual
    end of the receive buffer. xdr_init_decode's calculation of the
    value of xdr->end over-estimates the end of the buffer because the
    Linux kernel RPC server code does not remove the size of the RPC
    header from rqstp->rq_arg before calling the upper layer's
    dispatcher.

    The server-side still uses the svc_getnl() macros to decode the
    RPC call header. These macros reduce the length of the head iov
    but do not update the total length of the message in the buffer
    (buf->len).

    A proper fix for this would be to replace the use of svc_getnl() and
    friends in the RPC header decoder, but that would be a large and
    invasive change that would be difficult to backport.

    Fixes: 5191955d6fc6 ("SUNRPC: Prepare for xdr_stream-style decoding on the server-side")
    Reviewed-by: Jeff Layton <jlayton@kernel.org>
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    include/linux/sunrpc/svc.h | 17 ++++++++++++++---
    1 file changed, 14 insertions(+), 3 deletions(-)

    diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
    index daecb009c05b..5a830b66f059 100644
    --- a/include/linux/sunrpc/svc.h
    +++ b/include/linux/sunrpc/svc.h
    @@ -544,16 +544,27 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space)
    }

    /**
    - * svcxdr_init_decode - Prepare an xdr_stream for svc Call decoding
    + * svcxdr_init_decode - Prepare an xdr_stream for Call decoding
    * @rqstp: controlling server RPC transaction context
    *
    + * This function currently assumes the RPC header in rq_arg has
    + * already been decoded. Upon return, xdr->p points to the
    + * location of the upper layer header.
    */
    static inline void svcxdr_init_decode(struct svc_rqst *rqstp)
    {
    struct xdr_stream *xdr = &rqstp->rq_arg_stream;
    - struct kvec *argv = rqstp->rq_arg.head;
    + struct xdr_buf *buf = &rqstp->rq_arg;
    + struct kvec *argv = buf->head;

    - xdr_init_decode(xdr, &rqstp->rq_arg, argv->iov_base, NULL);
    + /*
    + * svc_getnl() and friends do not keep the xdr_buf's ::len
    + * field up to date. Refresh that field before initializing
    + * the argument decoding stream.
    + */
    + buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len;
    +
    + xdr_init_decode(xdr, buf, argv->iov_base, NULL);
    xdr_set_scratch_page(xdr, rqstp->rq_scratch_page);
    }

    --
    2.35.1


    \
     
     \ /
      Last update: 2022-10-19 10:58    [W:3.331 / U:0.176 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site