lkml.org 
[lkml]   [2018]   [Mar]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 018/115] sctp: fix the issue that a __u16 variable may overflow in sctp_ulpq_renege
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Xin Long <lucien.xin@gmail.com>


    [ Upstream commit 5c468674d17056148da06218d4da5d04baf22eac ]

    Now when reneging events in sctp_ulpq_renege(), the variable freed
    could be increased by a __u16 value twice while freed is of __u16
    type. It means freed may overflow at the second addition.

    This patch is to fix it by using __u32 type for 'freed', while at
    it, also to remove 'if (chunk)' check, as all renege commands are
    generated in sctp_eat_data and it can't be NULL.

    Reported-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
    Signed-off-by: Xin Long <lucien.xin@gmail.com>
    Acked-by: Neil Horman <nhorman@tuxdriver.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/sctp/ulpqueue.c | 24 ++++++++----------------
    1 file changed, 8 insertions(+), 16 deletions(-)

    --- a/net/sctp/ulpqueue.c
    +++ b/net/sctp/ulpqueue.c
    @@ -1084,29 +1084,21 @@ void sctp_ulpq_partial_delivery(struct s
    void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
    gfp_t gfp)
    {
    - struct sctp_association *asoc;
    - __u16 needed, freed;
    + struct sctp_association *asoc = ulpq->asoc;
    + __u32 freed = 0;
    + __u16 needed;

    - asoc = ulpq->asoc;
    -
    - if (chunk) {
    - needed = ntohs(chunk->chunk_hdr->length);
    - needed -= sizeof(struct sctp_data_chunk);
    - } else
    - needed = SCTP_DEFAULT_MAXWINDOW;
    -
    - freed = 0;
    + needed = ntohs(chunk->chunk_hdr->length) -
    + sizeof(struct sctp_data_chunk);

    if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) {
    freed = sctp_ulpq_renege_order(ulpq, needed);
    - if (freed < needed) {
    + if (freed < needed)
    freed += sctp_ulpq_renege_frags(ulpq, needed - freed);
    - }
    }
    /* If able to free enough room, accept this chunk. */
    - if (chunk && (freed >= needed)) {
    - int retval;
    - retval = sctp_ulpq_tail_data(ulpq, chunk, gfp);
    + if (freed >= needed) {
    + int retval = sctp_ulpq_tail_data(ulpq, chunk, gfp);
    /*
    * Enter partial delivery if chunk has not been
    * delivered; otherwise, drain the reassembly queue.

    \
     
     \ /
      Last update: 2018-03-02 11:02    [W:4.148 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site