• Daniel Borkmann's avatar
    net: sctp: fix ABI mismatch through sctp_assoc_to_state helper · 38ab1fa9
    Daniel Borkmann authored
    Since SCTP day 1, that is, 19b55a2af145 ("Initial commit") from lksctp
    tree, the official <netinet/sctp.h> header carries a copy of enum
    sctp_sstat_state that looks like (compared to the current in-kernel
    enumeration):
    
      User definition:                     Kernel definition:
    
      enum sctp_sstat_state {              typedef enum {
        SCTP_EMPTY             = 0,          <removed>
        SCTP_CLOSED            = 1,          SCTP_STATE_CLOSED            = 0,
        SCTP_COOKIE_WAIT       = 2,          SCTP_STATE_COOKIE_WAIT       = 1,
        SCTP_COOKIE_ECHOED     = 3,          SCTP_STATE_COOKIE_ECHOED     = 2,
        SCTP_ESTABLISHED       = 4,          SCTP_STATE_ESTABLISHED       = 3,
        SCTP_SHUTDOWN_PENDING  = 5,          SCTP_STATE_SHUTDOWN_PENDING  = 4,
        SCTP_SHUTDOWN_SENT     = 6,          SCTP_STATE_SHUTDOWN_SENT     = 5,
        SCTP_SHUTDOWN_RECEIVED = 7,          SCTP_STATE_SHUTDOWN_RECEIVED = 6,
        SCTP_SHUTDOWN_ACK_SENT = 8,          SCTP_STATE_SHUTDOWN_ACK_SENT = 7,
      };                                   } sctp_state_t;
    
    This header was later on also placed into the uapi, so that user space
    programs can compile without having <netinet/sctp.h>, but the shipped
    with <linux/sctp.h> instead.
    
    While RFC6458 under 8.2.1.Association Status (SCTP_STATUS) says that
    sstat_state can range from SCTP_CLOSED to SCTP_SHUTDOWN_ACK_SENT, we
    nevertheless have a what it appears to be dummy SCTP_EMPTY state from
    the very early days.
    
    While it seems to do just nothing, commit 0b8f9e25 ("sctp: remove
    completely unsed EMPTY state") did the right thing and removed this dead
    code. That however, causes an off-by-one when the user asks the SCTP
    stack via SCTP_STATUS API and checks for the current socket state thus
    yielding possibly undefined behaviour in applications as they expect
    the kernel to tell the right thing.
    
    The enumeration had to be changed however as based on the current socket
    state, we access a function pointer lookup-table through this. Therefore,
    I think the best way to deal with this is just to add a helper function
    sctp_assoc_to_state() to encapsulate the off-by-one quirk.
    Reported-by: default avatarTristan Su <sooqing@gmail.com>
    Fixes: 0b8f9e25 ("sctp: remove completely unsed EMPTY state")
    Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
    Acked-by: default avatarVlad Yasevich <vyasevich@gmail.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    38ab1fa9
socket.c 207 KB